import type { key_val } from '$lib/stores/ae_stores';
import { api } from '$lib/api/api';

import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
import { db_core } from '$lib/ae_core/db_core';

const ae_promises: key_val = {};

// Updated 2025-06-10
export async function load_ae_obj_id__person({
	api_cfg,
	person_id,
	params = {},
	try_cache = false,
	log_lvl = 0
}: {
	api_cfg: any;
	person_id: string;
	params?: key_val;
	try_cache?: boolean;
	log_lvl?: number;
}) {
	if (log_lvl) {
		console.log(`*** load_ae_obj_id__person() *** person_id=${person_id}`);
	}

	ae_promises.load__person_obj = await api
		.get_ae_obj_id_crud({
			api_cfg: api_cfg,
			obj_type: 'person',
			obj_id: person_id,
			use_alt_table: false,
			use_alt_base: false,
			params: params,
			log_lvl: log_lvl
		})
		.then(async function (person_obj_get_result) {
			if (person_obj_get_result) {
				if (try_cache) {
					// Process the results first
					const processed_obj_li = await process_ae_obj__person_props({
						obj_li: [person_obj_get_result],
						log_lvl: log_lvl
					});
					if (log_lvl) {
						console.log('Processed object list:', processed_obj_li);
					}
					// Save the updated results list to the database
					if (log_lvl) {
						console.log('Saving to DB...');
					}
					await db_save_ae_obj_li__ae_obj({
						db_instance: db_core,
						table_name: 'person',
						obj_li: processed_obj_li,
						properties_to_save: properties_to_save,
						log_lvl: log_lvl
					});
					if (log_lvl) {
						console.log('DB save completed.');
					}

					// // This is expecting a list
					// db_save_ae_obj_li__person({
					//     obj_type: 'person',
					//     obj_li: [person_obj_get_result],
					//     log_lvl: log_lvl
					// });
				}
				return person_obj_get_result;
			} else {
				console.log('No results returned.');
				return null;
			}
		})
		.catch(function (error: any) {
			console.log('No results returned or failed.', error);
		});

	if (log_lvl) {
		console.log('ae_promises.load__person_obj:', ae_promises.load__person_obj);
	}

	return ae_promises.load__person_obj;
}

// Updated 2025-06-10
export async function load_ae_obj_li__person({
	api_cfg,
	for_obj_type = 'account',
	for_obj_id,
	qry_email = null,
	qry_user_id = null,
	enabled = 'enabled',
	hidden = 'not_hidden',
	limit = 99,
	offset = 0,
	order_by_li = [
		{ family_name: 'ASC' },
		{ given_name: 'ASC' },
		{ updated_on: 'DESC' },
		{ created_on: 'DESC' }
	],
	// params_json = {},
	params = {},
	try_cache = true,
	log_lvl = 0
}: {
	api_cfg: any;
	for_obj_type: string;
	for_obj_id: string;
	qry_email?: string | null;
	qry_user_id?: string | null;
	enabled?: 'enabled' | 'all' | 'not_enabled' | undefined; // all, disabled, enabled
	hidden?: 'hidden' | 'all' | 'not_hidden' | undefined; // all, hidden, not_hidden
	limit?: number;
	offset?: number;
	order_by_li?: { [key: string]: 'ASC' | 'DESC' }[] | null;
	// params_json?: null|key_val,
	params?: key_val;
	try_cache?: boolean;
	log_lvl?: number;
}) {
	if (log_lvl) {
		console.log(
			`*** load_ae_obj_li__person() *** for_obj_type=${for_obj_type} for_obj_id=${for_obj_id} enabled=${enabled} hidden=${hidden} limit=${limit} offset=${offset}`
		);
	}

	const params_json: key_val = {};

	// console.log('params_json:', params_json);
	if (qry_user_id) {
		// params_json['and_qry'] = {};
		// params_json['and_qry']['user_id_random'] = qry_user_id;

		params_json['qry'] = [];

		const qry_param = {
			type: 'AND',
			field: 'user_id_random',
			operator: '=',
			value: qry_user_id
		};
		params_json['qry'].push(qry_param);
	}

	if (log_lvl) {
		console.log('params_json:', params_json);
	}

	ae_promises.load__person_obj_li = await api
		.get_ae_obj_li_for_obj_id_crud_v2({
			api_cfg: api_cfg,
			obj_type: 'person',
			for_obj_type: for_obj_type,
			for_obj_id: for_obj_id,
			use_alt_tbl: false,
			use_alt_mdl: false,
			use_alt_exp: false,
			enabled: enabled,
			hidden: hidden,
			order_by_li: order_by_li,
			limit: limit,
			offset: offset,
			params_json: params_json,
			params: params,
			log_lvl: log_lvl
		})
		.then(async function (person_obj_li_get_result) {
			if (person_obj_li_get_result) {
				if (try_cache) {
					// Process the results first
					const processed_obj_li = await process_ae_obj__person_props({
						obj_li: person_obj_li_get_result,
						log_lvl: log_lvl
					});
					if (log_lvl) {
						console.log('Processed object list:', processed_obj_li);
					}
					// Save the updated results list to the database
					if (log_lvl) {
						console.log('Saving to DB...');
					}
					await db_save_ae_obj_li__ae_obj({
						db_instance: db_core,
						table_name: 'person',
						obj_li: processed_obj_li,
						properties_to_save: properties_to_save,
						log_lvl: log_lvl
					});
					if (log_lvl) {
						console.log('DB save completed.');
					}

					// db_save_ae_obj_li__person({
					//     obj_type: 'person',
					//     obj_li: person_obj_li_get_result,
					//     log_lvl: log_lvl
					// });
				}
				return person_obj_li_get_result;
			} else {
				return [];
			}
		})
		.catch(function (error: any) {
			console.log('No results returned or failed.', error);
		});

	console.log('ae_promises.load__person_obj_li:', ae_promises.load__person_obj_li);
	return ae_promises.load__person_obj_li;
}

// Updated 2025-06-10
export async function create_ae_obj__person({
	api_cfg,
	user_id,
	data_kv,
	params = {},
	try_cache = true,
	log_lvl = 0
}: {
	api_cfg: any;
	user_id?: string;
	data_kv: key_val;
	params?: key_val;
	try_cache?: boolean;
	log_lvl?: number;
}) {
	if (log_lvl) {
		console.log(`*** create_ae_obj__person() *** user_id=${user_id}`);
	}

	ae_promises.create__person = await api
		.create_ae_obj_crud({
			api_cfg: api_cfg,
			obj_type: 'person',
			fields: {
				user_id_random: user_id,
				...data_kv
			},
			key: api_cfg.api_crud_super_key,
			params: params,
			return_obj: true,
			log_lvl: log_lvl
		})
		.then(async function (person_obj_create_result) {
			if (person_obj_create_result) {
				if (try_cache) {
					// Process the results first
					const processed_obj_li = await process_ae_obj__person_props({
						obj_li: [person_obj_create_result],
						log_lvl: log_lvl
					});
					if (log_lvl) {
						console.log('Processed object list:', processed_obj_li);
					}
					// Save the updated results list to the database
					if (log_lvl) {
						console.log('Saving to DB...');
					}
					await db_save_ae_obj_li__ae_obj({
						db_instance: db_core,
						table_name: 'person',
						obj_li: processed_obj_li,
						properties_to_save: properties_to_save,
						log_lvl: log_lvl
					});
					if (log_lvl) {
						console.log('DB save completed.');
					}

					// db_save_ae_obj_li__person(
					//     {
					//         obj_type: 'person',
					//         obj_li: [person_obj_create_result],
					//         log_lvl: log_lvl
					//     });
				}
				return person_obj_create_result;
			} else {
				return null;
			}
		})
		.catch(function (error: any) {
			console.log('No results returned or failed.', error);
		})
		.finally(function () {});

	if (log_lvl) {
		console.log('ae_promises.create__person:', ae_promises.create__person);
	}
	return ae_promises.create__person;
}

// Updated 2025-05-10
export async function delete_ae_obj_id__person({
	api_cfg,
	person_id,
	method = 'delete', // 'delete', 'disable', 'hide'
	params = {},
	try_cache = true,
	log_lvl = 0
}: {
	api_cfg: any;
	person_id: string;
	method?: string;
	params?: key_val;
	try_cache?: boolean;
	log_lvl?: number;
}) {
	if (log_lvl) {
		console.log(`*** delete_ae_obj_id__person() *** person_id=${person_id}`);
	}

	ae_promises.delete__person_obj = await api
		.delete_ae_obj_id_crud({
			api_cfg: api_cfg,
			obj_type: 'person',
			obj_id: person_id,
			key: api_cfg.api_crud_super_key,
			params: params,
			method: method,
			log_lvl: log_lvl
		})
		.catch(function (error: any) {
			console.log('No results returned or failed.', error);
		})
		.finally(async function () {
			if (try_cache) {
				if (log_lvl) {
					console.log(`Attempting to remove IDB entry for person_id=${person_id}`);
				}
				await db_core.person.delete(person_id);
			}
		});

	if (log_lvl) {
		console.log('ae_promises.delete__person_obj:', ae_promises.delete__person_obj);
	}

	return ae_promises.delete__person_obj;
}

// Updated 2025-06-10
export async function update_ae_obj__person({
	api_cfg,
	person_id,
	data_kv,
	params = {},
	try_cache = true,
	log_lvl = 0
}: {
	api_cfg: any;
	person_id: string;
	data_kv: key_val;
	params?: key_val;
	try_cache?: boolean;
	log_lvl?: number;
}) {
	if (log_lvl) {
		console.log(`*** update_ae_obj__person() *** person_id=${person_id}`, data_kv);
	}

	// log_lvl = 1;

	// Perform the API update
	const result = await api.update_ae_obj_id_crud({
		api_cfg: api_cfg,
		obj_type: 'person',
		obj_id: person_id,
		fields: data_kv,
		key: api_cfg.api_crud_super_key,
		params: params,
		return_obj: true,
		log_lvl: log_lvl
	});

	// Handle the result
	if (result) {
		if (try_cache) {
			// Process the results first
			const processed_obj_li = await process_ae_obj__person_props({
				obj_li: [result],
				log_lvl: log_lvl
			});
			if (log_lvl) {
				console.log('Processed object list:', processed_obj_li);
			}
			// Save the updated results list to the database
			if (log_lvl) {
				console.log('Saving to DB...');
			}
			await db_save_ae_obj_li__ae_obj({
				db_instance: db_core,
				table_name: 'person',
				obj_li: processed_obj_li,
				properties_to_save: properties_to_save,
				log_lvl: log_lvl
			});
			if (log_lvl) {
				console.log('DB save completed.');
			}

			// await db_save_ae_obj_li__person({
			//     obj_type: 'person',
			//     obj_li: [result],
			//     log_lvl: log_lvl,
			// });
		}
		return result;
	} else {
		console.error('Failed to update person.');
		return null;
	}
}

// Updated 2024-06-10
export function db_save_ae_obj_li__person({
	obj_type,
	obj_li,
	log_lvl = 0
}: {
	obj_type: string;
	obj_li: any;
	log_lvl?: number;
}) {
	if (log_lvl) {
		console.log(`*** db_save_ae_obj_li__person() ***`);
	}

	if (obj_li && obj_li.length) {
		obj_li.forEach(async function (obj: any) {
			if (log_lvl) {
				console.log(`ae_obj ${obj_type}:`, obj);
			}

			const obj_record = {
				id: obj.person_id_random,
				// id_random: obj.person_id_random,
				person_id: obj.person_id_random,
				person_id_random: obj.person_id_random,

				external_id: obj.external_id,
				external_sys_id: obj.external_sys_id,
				code: obj.code,

				account_id: obj.account_id_random,
				account_id_random: obj.account_id_random,

				person_profile_id: obj.person_profile_id_random,
				person_profile_id_random: obj.person_profile_id_random, // The new table person_profile will be used soon...

				user_id: obj.user_id_random,
				user_id_random: obj.user_id_random,

				pronouns: obj.pronouns,
				informal_name: obj.informal_name,
				title_names: obj.title_names,
				given_name: obj.given_name,
				middle_name: obj.middle_name,
				family_name: obj.family_name,
				designations: obj.designations,

				professional_title: obj.professional_title,

				full_name: obj.full_name,
				full_name_override: obj.full_name_override, // was display_name and display_name_override

				affiliations: obj.affiliations,

				primary_email: obj.primary_email,

				biography: obj.biography,

				agree: obj.agree,
				comments: obj.comments,

				allow_auth_key: obj.allow_auth_key, // For sign in without password
				// auth_key: obj.auth_key,
				passcode: obj.passcode,

				data_json: obj.data_json,

				enable: obj.enable,
				hide: obj.hide,
				priority: obj.priority,
				sort: obj.sort,
				group: obj.group,
				notes: obj.notes,
				created_on: obj.created_on,
				updated_on: obj.updated_on,

				// From SQL view
				username: obj.username,
				user_name: obj.user_name,
				user_email: obj.user_email,
				user_allow_auth_key: obj.user_allow_auth_key, // For sign in without password
				user_super: obj.user_super,
				user_manager: obj.user_manager,
				user_administrator: obj.user_administrator,
				user_public: obj.user_public
			};

			let id_random = null;

			try {
				id_random = await db_core.person.update(obj_record.id, obj_record);
			} catch (error) {
				console.log(`Error: Failed to update ${obj_record.id}: ${error}`);
			}
			if (!id_random) {
				if (log_lvl) {
					console.log(`Failed to update record with ID: ${obj_record.id}. Trying put...`);
				}
				try {
					id_random = await db_core.person.put(obj_record);
				} catch (error) {
					console.log(`Error: Failed to put ${obj.person_id_random}: ${error}`);
				}
			} else {
				if (log_lvl) {
					console.log(`Updated record with ID: ${obj_record.id}`);
				}
			}
			if (!id_random) {
				console.log(`Failed to save record with ID: ${obj_record.id}`);
			} else {
				if (log_lvl) {
					console.log(`Saved record with ID: ${obj_record.id}`);
				}
			}
		});

		return true;
	}
}

// Updated 2025-06-10
const properties_to_save = [
	'id',
	'person_id',
	// 'person_id_random',

	'external_id',
	'external_sys_id',
	'code',

	'account_id',
	// 'account_id_random',

	'person_profile_id',
	// 'person_profile_id_random', // The new table person_profile will be used soon...

	'user_id',
	// 'user_id_random',

	'pronouns',
	'informal_name',
	'title_names',
	'given_name',
	'middle_name',
	'family_name',
	'designations',

	'professional_title',

	'full_name',
	'full_name_override', // was display_name and display_name_override

	'affiliations',
	'primary_email',
	'biography',
	'agree',
	'comments',

	'allow_auth_key', // For sign in without password
	// 'auth_key', // Should this be saved locally?
	'passcode',

	// 'passcode_timeout',
	// 'passcode_read', // For LLM (AI) generated summary...???
	// 'passcode_read_expire',
	// 'passcode_write',
	// 'passcode_write_expire',
	// 'private_passcode',

	// 'alert',
	// 'alert_msg',

	'data_json',

	'enable',
	'hide',
	'priority',
	'sort',
	'group',
	'notes',
	'created_on',
	'updated_on',

	// Generated fields for sorting locally only
	'tmp_sort_1',
	'tmp_sort_2',
	'tmp_sort_3',

	// From SQL view
	'username',
	// 'user_username', // Same as username
	'user_name',
	'user_email',
	'user_allow_auth_key', // For sign in without password
	'user_super',
	'user_manager',
	'user_administrator',
	'user_public',

	'organization_id',
	// 'organization_id_random',
	'organization_name',

	'contact_id',
	// 'contact_id_random',
	'contact_name',
	'contact_email',
	'contact_cc_email',
	'contact_phone_mobile',
	'contact_phone_home',
	'contact_phone_office',
	'contact_phone_land',
	'contact_phone_fax',
	'contact_phone_other',

	'address_id',
	// 'address_id_random',
	'address_city',
	'address_country_alpha_2_code' // contact_address_country_alpha_2_code
];

/**
 * NON-EXPORTED LOCAL HELPER
 * Processes a list of Aether objects by applying common and specific transformations.
 */
async function _process_generic_props<T extends Record<string, any>>({
	obj_li,
	obj_type,
	log_lvl = 0,
	specific_processor
}: {
	obj_li: T[];
	obj_type: string;
	log_lvl?: number;
	specific_processor?: (obj: T) => Promise<T> | T;
}): Promise<T[]> {
	if (log_lvl > 0) {
		console.log(
			`*** _process_generic_props: Processing ${obj_li.length} objects of type "${obj_type}" ***`
		);
	}

	if (!obj_li || obj_li.length === 0) {
		if (log_lvl > 0) console.log('No objects to process.');
		return [];
	}

	const processed_obj_li: T[] = [];

	for (const original_obj of obj_li) {
		let processed_obj = { ...original_obj };

		// --- Common Transformations ---

		// 1. Standardize ID and other '_random' fields
		// The API often returns fields like 'person_id_random', which need to be aliased to 'person_id'.
		for (const key in processed_obj) {
			if (key.endsWith('_random')) {
				const new_key = key.slice(0, -7); // Remove '_random' suffix
				(processed_obj as any)[new_key] = processed_obj[key];
			}
		}
		// Ensure 'id' is set from '[obj_type]_id_random'
		const random_id_key = `${obj_type}_id_random`;
		if (processed_obj[random_id_key]) {
			(processed_obj as any).id = processed_obj[random_id_key];
		}

		// 2. Create common computed properties for client-side sorting.
		const group = processed_obj.group ?? '0';
		const priority = processed_obj.priority ? 1 : 0;
		const sort = processed_obj.sort ?? '0';
		const updated = processed_obj.updated_on ?? processed_obj.created_on;
		const name = processed_obj.name ?? '';

		(processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`;
		(processed_obj as any).tmp_sort_2 = `${group}_${priority}_${sort}_${name}_${updated}`;

		// --- Specific Transformations ---
		if (specific_processor) {
			processed_obj = await Promise.resolve(specific_processor(processed_obj));
		}

		processed_obj_li.push(processed_obj as T);
	}

	return processed_obj_li;
}

// Updated 2025-06-10
export async function process_ae_obj__person_props({
	obj_li,
	log_lvl = 0
}: {
	obj_li: any[];
	log_lvl?: number;
}) {
	return _process_generic_props({
		obj_li,
		obj_type: 'person',
		log_lvl,
		specific_processor: (obj) => {
			// Person-specific computed sort fields, overriding generic ones if needed
			obj.tmp_sort_1 = `${obj.group ?? '0'}_${obj.priority ? 1 : 0}_${
				obj.sort ?? '0'
			}_${obj.updated_on}_${obj.created_on}`;
			obj.tmp_sort_2 = `${obj.group ?? '0'}_${obj.priority ? 1 : 0}_${
				obj.sort ?? '0'
			}_${obj.updated_on ?? obj.created_on}`;
			obj.tmp_sort_3 = `${obj.group ?? '0'}_${obj.priority ? 1 : 0}_${
				obj.sort ?? '0'
			}_${obj.name ?? ''}_${obj.updated_on ?? obj.created_on}`;

			return obj;
		}
	});
}
