import { createAction, Property } from '@activepieces/pieces-framework';
import {
	areSheetIdsValid,
	Dimension,
	getAccessToken,
	GoogleSheetsAuthValue,
	googleSheetsCommon,
	objectToArray,
	stringifyArray,
	ValueInputOption,
} from '../common/common';
import { googleSheetsAuth } from '../common/common';
import { isNil } from '@activepieces/pieces-framework';
import {
	AuthenticationType,
	httpClient,
	HttpMethod,
	HttpRequest,
} from '@activepieces/pieces-common';
import { commonProps, isFirstRowHeaderProp, rowValuesProp } from '../common/props';

export const insertRowAction = createAction({
	auth: googleSheetsAuth,
	name: 'insert_row',
	description: 'Add a new row of data to a specific spreadsheet.',
	audience: 'both',
	aiMetadata: {
		description:
			'Appends a single new row to the end of a worksheet. Use when an agent needs to record one new entry into a Google Sheet. Requires a spreadsheet and sheet to be selected; values map to columns either positionally or by header name. Not idempotent — calling it again appends another row.',
		idempotent: false,
	},
	displayName: 'Add Row',
	props: {
		...commonProps,
		first_row_headers: isFirstRowHeaderProp(),
		as_string: Property.Checkbox({
			displayName: 'As String',
			description:
				'Inserted values that are dates and formulas will be entered strings and have no effect',
			required: false,
		}),
		values: rowValuesProp(),
	},
	async run({ propsValue, auth }) {
		const {
			values,
			spreadsheetId: inputSpreadsheetId,
			sheetId: inputSheetId,
			as_string,
			first_row_headers,
		} = propsValue;

		if (!areSheetIdsValid(inputSpreadsheetId, inputSheetId)) {
			throw new Error('Please select a spreadsheet and sheet first.');
		}

		const sheetId = Number(inputSheetId);
		const spreadsheetId = inputSpreadsheetId as string;

		const sheetName = await googleSheetsCommon.findSheetName(auth, spreadsheetId, sheetId);

		const formattedValues = first_row_headers
			? objectToArray(values).map((val) => (isNil(val) ? '' : val))
			: values.values;

		const res = await appendGoogleSheetValues({
			auth,
			majorDimension: Dimension.COLUMNS,
			range: sheetName,
			spreadSheetId: spreadsheetId,
			valueInputOption: as_string ? ValueInputOption.RAW : ValueInputOption.USER_ENTERED,
			values: stringifyArray(formattedValues),
		});

		const updatedRowNumber = extractRowNumber(res.body.updates.updatedRange);
		return { ...res.body, row: updatedRowNumber };
	},
});

function extractRowNumber(updatedRange: string): number {
	const rowRange = updatedRange.split('!')[1];
	return parseInt(rowRange.split(':')[0].substring(1), 10);
}

async function appendGoogleSheetValues(params: AppendGoogleSheetValuesParams) {
	const { auth, majorDimension, range, spreadSheetId, valueInputOption, values } = params;
	const accessToken = await getAccessToken(auth);
	const request: HttpRequest = {
		method: HttpMethod.POST,
		url: `https://sheets.googleapis.com/v4/spreadsheets/${spreadSheetId}/values/${encodeURIComponent(
			`${range}!A:A`,
		)}:append`,
		body: {
			majorDimension,
			range: `${range}!A:A`,
			values: values.map((val) => ({ values: val })),
		},
		authentication: {
			type: AuthenticationType.BEARER_TOKEN,
			token: accessToken,
		},
		queryParams: {
			valueInputOption,
		},
	};

	return httpClient.sendRequest(request);
}

type AppendGoogleSheetValuesParams = {
	values: string[];
	spreadSheetId: string;
	range: string;
	valueInputOption: ValueInputOption;
	majorDimension: Dimension;
	auth: GoogleSheetsAuthValue;
};
