/* eslint-disable prefer-template */
import type { AxiosResponse } from 'axios';
import axios from 'axios';
import JSZip from 'jszip';
import environment from '../../../../Environments/environment';
import type { FinancialsModel } from '../../../Financials/Components/FinancialsForm/FinancialsForm.helper';

const { apiUrl, backendRoutes } = environment;

export const getFinancialsList = async (
	company_id: string | undefined
): Promise<FinancialsModel[] | null> => {
	if (!company_id) {
		return null;
	}
	let ret;
	await await axios
		.get(apiUrl + backendRoutes.financials.get, {
			params: {
				company_id
			}
		})
		.then((results: AxiosResponse<FinancialsModel[]>) => results.data as FinancialsModel[])
		.catch((error) => {
			console.error(error.message);
			return null;
		});
	return ret || null;
};

export const getInvitesList = async (company_id: string | undefined) => {
	if (!company_id) {
		return null;
	}
	// eslint-disable-next-line @typescript-eslint/return-await
	return await axios
		.get(`${apiUrl}${backendRoutes.account.getInvites}?companyId=${company_id}`)
		.then((response) => {
			if (response.status === 200) {
				return response.data;
			}
			// eslint-disable-next-line no-alert
			alert('an error occurred while retrieving the list of invites for the selected company');
		})
		.catch((e) => {
			// eslint-disable-next-line no-console
			console.error(e);
		});
};

function flattenObject(
	obj: Record<string, any>,
	parentKey: string = '',
	result: Record<string, any> = {},
	level: number = 0
): Record<string, any> {
	for (const key in obj) {
		if (Object.prototype.hasOwnProperty.call(obj, key)) {
			const value = obj[key];
			const newKey = parentKey ? `${parentKey}-${key}` : key;

			if (Array.isArray(value)) {
				if (level === 0) {
					// Keep array at first level as is
					result[newKey] = value;
				} else {
					// Flatten array at deeper levels
					value.forEach((item, index) => {
						const arrayKey = `${newKey}-${index}`;
						if (item !== null && typeof item === 'object') {
							// Recurse for nested objects inside array
							flattenObject(item, arrayKey, result, level + 1);
						} else {
							result[arrayKey] = item;
						}
					});
				}
			} else if (value !== null && typeof value === 'object') {
				// Recurse for nested objects
				flattenObject(value, newKey, result, level + 1);
			} else {
				// Primitive value
				result[newKey] = value;
			}
		}
	}
	return result;
}

export const convertToCSV = <T extends object>(
	jsonArray: T[],
	filename: string = 'data.csv'
): string => {
	if (!jsonArray || jsonArray.length === 0) {
		// eslint-disable-next-line no-alert
		alert('No data available to export');
		return '';
	}

	// Flatten each object in the array
	const flattenedArray = jsonArray.map((item) => flattenObject(item));

	// Get all unique headers from all flattened objects
	const headersSet = new Set<string>();
	flattenedArray.forEach((item) => {
		Object.keys(item).forEach((k) => headersSet.add(k));
	});
	const headers = Array.from(headersSet);

	// Generate CSV header row
	const csvRows = [headers.join(',')];

	// Generate CSV data rows
	flattenedArray.forEach((item) => {
		const row = headers
			.map((header) => {
				const value = item[header] !== undefined ? item[header] : '';
				const escaped = ('' + value).replace(/"/g, '""'); // escape quotes
				return `"${escaped}"`; // wrap in quotes
			})
			.join(',');
		csvRows.push(row);
	});

	// Optionally, trigger download or return CSV string
	return csvRows.join('\n');
};

export const downloadMultipleCSVsAsZip = async (
	datasets: { data: object[]; filename: string }[]
): Promise<void> => {
	const zip = new JSZip();

	// Generate each CSV and add to zip
	datasets.forEach(({ data, filename }) => {
		const csvContent = convertToCSV(data);
		// Add CSV as a file in the zip archive
		zip.file(filename, csvContent);
	});

	// Generate the ZIP file as a blob
	const blob = await zip.generateAsync({ type: 'blob' });

	// Trigger download
	const url = URL.createObjectURL(blob);
	const a = document.createElement('a');
	a.href = url;
	a.download = 'files.zip'; // name of the zip file
	document.body.appendChild(a);
	a.click();
	document.body.removeChild(a);
	URL.revokeObjectURL(url);
};
