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;
        }
    });
}
