import { marked } from 'marked';

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

import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
import { build_tmp_sort } from '$lib/ae_core/core__idb_sort';
import { db_journals } from '$lib/ae_journals/db_journals';
import type { ae_JournalEntry } from '$lib/types/ae_types';

const ae_promises: key_val = {};

// Updated 2026-01-05
export async function load_ae_obj_id__journal_entry({
    api_cfg,
    journal_entry_id,
    try_cache = true,
    log_lvl = 0
}: {
    api_cfg: any;
    journal_entry_id: string;
    try_cache?: boolean;
    log_lvl?: number;
}): Promise<ae_JournalEntry | null> {
    if (log_lvl) {
        console.log(
            `*** load_ae_obj_id__journal_entry() *** journal_entry_id=${journal_entry_id}`
        );
    }

    ae_promises.load__journal_entry_obj = await api
        .get_ae_obj({
            api_cfg: api_cfg,
            obj_type: 'journal_entry',
            obj_id: journal_entry_id,
            log_lvl: log_lvl
        })
        .then(async function (journal_entry_obj_get_result) {
            if (journal_entry_obj_get_result) {
                if (try_cache) {
                    // Process the results first
                    const processed_obj_li =
                        await process_ae_obj__journal_entry_props({
                            obj_li: [journal_entry_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.
                    // IDB write is optional caching — quota failures must not discard the API result.
                    try {
                        await db_save_ae_obj_li__ae_obj({
                            db_instance: db_journals,
                            table_name: 'journal_entry',
                            obj_li: processed_obj_li,
                            properties_to_save: properties_to_save,
                            log_lvl: log_lvl
                        });
                    } catch (save_error) {
                        console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
                    }
                }
                return journal_entry_obj_get_result;
            } else {
                console.log('No results returned.');
                return null;
            }
        })
        .catch(function (error: any) {
            console.log('No results returned or failed.', error);
        });

    return ae_promises.load__journal_entry_obj;
}

// Updated 2026-01-02
export async function load_ae_obj_li__journal_entry({
    api_cfg,
    for_obj_type = 'journal',
    for_obj_id,
    enabled = 'enabled',
    hidden = 'not_hidden',
    limit = 99,
    offset = 0,
    order_by_li = {
        priority: 'DESC',
        sort: 'DESC',
        name: 'ASC',
        updated_on: 'DESC',
        created_on: 'DESC'
    },
    params = {},
    try_cache = true,
    log_lvl = 0
}: {
    api_cfg: any;
    for_obj_type: string;
    for_obj_id: string;
    enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
    hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
    limit?: number;
    offset?: number;
    order_by_li?: key_val;
    params?: key_val;
    try_cache?: boolean;
    log_lvl?: number;
}): Promise<ae_JournalEntry[]> {
    if (log_lvl) {
        console.log(
            `*** load_ae_obj_li__journal_entry() *** for_obj_type=${for_obj_type} for_obj_id=${for_obj_id}`
        );
    }

    let promise;

    if (for_obj_type === 'journal' && for_obj_id) {
        promise = api.get_nested_obj_li({
            api_cfg,
            parent_type: 'journal',
            parent_id: for_obj_id,
            child_type: 'journal_entry',
            limit,
            offset,
            enabled,
            hidden,
            order_by_li,
            log_lvl
        });
    } else {
        promise = api.get_ae_obj_li({
            api_cfg,
            obj_type: 'journal_entry',
            for_obj_type,
            for_obj_id,
            enabled,
            hidden,
            limit,
            offset,
            order_by_li,
            log_lvl
        });
    }

    ae_promises.load__journal_entry_obj_li = await promise
        .then(async function (journal_entry_obj_li_get_result) {
            if (journal_entry_obj_li_get_result) {
                if (try_cache) {
                    // Process the results first
                    const processed_obj_li =
                        await process_ae_obj__journal_entry_props({
                            obj_li: journal_entry_obj_li_get_result,
                            journal_id:
                                for_obj_type === 'journal'
                                    ? for_obj_id
                                    : undefined,
                            log_lvl: log_lvl
                        });
                    if (log_lvl) {
                        console.log('Processed object list:', processed_obj_li);
                    }
                    // Save the updated results list to the database.
                    // IDB write is optional caching — quota failures must not discard the API result.
                    if (log_lvl) {
                        console.log('Saving to DB...');
                    }
                    try {
                        await db_save_ae_obj_li__ae_obj({
                            db_instance: db_journals,
                            table_name: 'journal_entry',
                            obj_li: processed_obj_li,
                            properties_to_save: properties_to_save,
                            log_lvl: log_lvl
                        });
                        if (log_lvl) {
                            console.log('DB save completed.');
                        }
                    } catch (save_error) {
                        console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
                    }
                }
                return journal_entry_obj_li_get_result;
            } else {
                return [];
            }
        })
        .catch(function (error: any) {
            console.log('No results returned or failed.', error);
        });

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

    return ae_promises.load__journal_entry_obj_li;
}

// Updated 2026-01-05
export async function create_ae_obj__journal_entry({
    api_cfg,
    journal_id,
    data_kv,
    params = {},
    try_cache = true,
    log_lvl = 0
}: {
    api_cfg: any;
    journal_id: string;
    data_kv: key_val;
    params?: key_val;
    try_cache?: boolean;
    log_lvl?: number;
}): Promise<ae_JournalEntry | null> {
    if (log_lvl) {
        console.log(
            `*** create_ae_obj__journal_entry() *** journal_id=${journal_id}`
        );
    }

    if (!journal_id) {
        console.log(`ERROR: Journals - Entry - journal_id required to create`);
        return null;
    }

    ae_promises.create__journal_entry = await api
        .create_nested_obj({
            api_cfg: api_cfg,
            parent_type: 'journal',
            parent_id: journal_id,
            child_type: 'journal_entry',
            fields: data_kv,
            params: params,
            log_lvl: log_lvl
        })
        .then(async function (journal_entry_obj_create_result) {
            if (journal_entry_obj_create_result) {
                if (try_cache) {
                    // Process the results first
                    const processed_obj_li =
                        await process_ae_obj__journal_entry_props({
                            obj_li: [journal_entry_obj_create_result],
                            journal_id,
                            log_lvl: log_lvl
                        });
                    if (log_lvl) {
                        console.log('Processed object list:', processed_obj_li);
                    }
                    // IDB write is optional caching — quota failures must not discard the API result.
                    try {
                        await db_save_ae_obj_li__ae_obj({
                            db_instance: db_journals,
                            table_name: 'journal_entry',
                            obj_li: processed_obj_li,
                            properties_to_save: properties_to_save,
                            log_lvl: log_lvl
                        });
                    } catch (save_error) {
                        console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
                    }
                }
                return journal_entry_obj_create_result;
            } else {
                return null;
            }
        })
        .catch(function (error: any) {
            console.log('No results returned or failed.', error);
        });

    return ae_promises.create__journal_entry;
}

// Updated 2026-01-05
export async function delete_ae_obj_id__journal_entry({
    api_cfg,
    journal_entry_id,
    method = 'delete', // 'delete', 'disable', 'hide'
    params = {},
    try_cache = true,
    log_lvl = 0
}: {
    api_cfg: any;
    journal_entry_id: string;
    method?: 'delete' | 'soft_delete' | 'disable' | 'hide';
    params?: key_val;
    try_cache?: boolean;
    log_lvl?: number;
}) {
    if (log_lvl) {
        console.log(
            `*** delete_ae_obj_id__journal_entry() *** journal_entry_id=${journal_entry_id}`
        );
    }

    ae_promises.delete__journal_entry_obj = await api
        .delete_ae_obj({
            api_cfg: api_cfg,
            obj_type: 'journal_entry',
            obj_id: journal_entry_id,
            method: method,
            params: params,
            log_lvl: log_lvl
        })
        .catch(function (error: any) {
            console.log('No results returned or failed.', error);
        })
        .finally(function () {
            if (try_cache) {
                if (log_lvl) {
                    console.log(
                        `Attempting to remove IDB entry for journal_entry_id=${journal_entry_id}`
                    );
                }
                db_journals.journal_entry.delete(journal_entry_id); // Delete from the DB no matter what.
            }
        });

    return ae_promises.delete__journal_entry_obj;
}

// This new function is using CRUD V3 Search.
// Updated 2026-01-27
export async function qry__journal_entry({
    api_cfg,
    journal_id,
    person_id = null,
    qry_str = null, // Example: 'name:contains:"test"'
    qry_category_code = null,
    qry_created_on = null, // Example greater than: '2024-10-24'
    qry_alert = null,
    qry_priority = null,
    enabled = 'enabled',
    hidden = 'not_hidden',
    limit = 50,
    offset = 0,
    order_by_li = {
        group: 'DESC',
        priority: 'DESC',
        sort: 'DESC',
        alert: 'DESC',
        name: 'ASC',
        updated_on: 'DESC',
        created_on: 'DESC'
    },
    params = {},
    try_cache = true,
    log_lvl = 0
}: {
    api_cfg: any;
    journal_id: any;
    person_id?: string | null;
    qry_str?: null | string;
    qry_category_code?: null | string;
    qry_created_on?: null | string;
    qry_alert?: null | string;
    qry_priority?: null | number;
    enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
    hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
    limit?: number;
    offset?: number;
    order_by_li?: key_val;
    params?: any;
    try_cache?: boolean;
    log_lvl?: number;
}) {
    if (log_lvl) {
        console.log(
            `*** qry__journal_entry() *** journal_id=${journal_id} person_id=${person_id}`
        );
    }

    const search_query: any = { and: [] };

    if (qry_str) {
        // Using 'like' with wildcards to ensure compatibility
        search_query.and.push({
            field: 'default_qry_str',
            op: 'like',
            value: `%${qry_str.trim()}%`
        });
        params['lk_qry'] = { default_qry_str: qry_str.trim() };
    }

    if (qry_category_code) {
        search_query.and.push({
            field: 'category_code',
            op: 'eq',
            value: qry_category_code
        });
    }

    if (qry_created_on) {
        search_query.and.push({
            field: 'created_on',
            op: 'gt',
            value: qry_created_on
        });
    }

    if (qry_priority) {
        search_query.and.push({
            field: 'priority',
            op: 'eq',
            value: qry_priority
        });
    }

    // Context scoping: Prefer journal_id if provided, otherwise fallback to person_id (global search)
    if (journal_id) {
        search_query.and.push({
            field: 'journal_id',
            op: 'eq',
            value: journal_id
        });
    } else if (person_id) {
        search_query.and.push({
            field: 'person_id',
            op: 'eq',
            value: person_id
        });
    } else {
        console.warn(
            'qry__journal_entry: No journal_id or person_id provided. Search might be too broad.'
        );
    }

    // Add enabled/hidden filters
    if (enabled === 'enabled') {
        search_query.and.push({ field: 'enable', op: 'eq', value: true });
    } else if (enabled === 'not_enabled') {
        search_query.and.push({ field: 'enable', op: 'eq', value: false });
    }

    if (hidden === 'hidden') {
        search_query.and.push({ field: 'hide', op: 'eq', value: true });
    } else if (hidden === 'not_hidden') {
        search_query.and.push({ field: 'hide', op: 'eq', value: false });
    }

    ae_promises.load__journal_entry_obj_li = await api
        .search_ae_obj({
            api_cfg: api_cfg,
            obj_type: 'journal_entry',
            search_query,
            order_by_li,
            limit,
            offset,
            params,
            log_lvl
        })
        .then(async function (journal_entry_obj_li_get_result) {
            // Handle V3 API envelope { data: [], meta: ... } or direct array
            let valid_result_li: ae_JournalEntry[] = [];
            if (Array.isArray(journal_entry_obj_li_get_result)) {
                valid_result_li = journal_entry_obj_li_get_result;
            } else if (
                journal_entry_obj_li_get_result &&
                typeof journal_entry_obj_li_get_result === 'object' &&
                Array.isArray((journal_entry_obj_li_get_result as any).data)
            ) {
                valid_result_li = (journal_entry_obj_li_get_result as any).data;
            }

            if (valid_result_li && valid_result_li.length > 0) {
                if (try_cache) {
                    const processed_obj_li =
                        await process_ae_obj__journal_entry_props({
                            obj_li: valid_result_li,
                            journal_id,
                            log_lvl
                        });
                    // IDB write is optional caching — quota failures must not discard the API result.
                    try {
                        await db_save_ae_obj_li__ae_obj({
                            db_instance: db_journals,
                            table_name: 'journal_entry',
                            obj_li: processed_obj_li,
                            properties_to_save,
                            log_lvl
                        });
                    } catch (save_error) {
                        console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
                    }
                }
                return valid_result_li;
            } else {
                return [];
            }
        });

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

// Updated 2025-03-15
// export async function update_ae_obj__journal_entry(
//         {
//             api_cfg,
//             journal_entry_id,
//             data_kv,
//             params = {},
//             try_cache = true,
//             log_lvl = 0
//         }: {
//             api_cfg: any,
//             journal_entry_id: string,
//             data_kv: key_val,
//             params?: key_val,
//             try_cache?: boolean,
//             log_lvl?: number
//         }
//     ) {
//     if (log_lvl) {
//         console.log(`*** update_ae_obj__journal_entry() *** journal_entry_id=${journal_entry_id}`, data_kv);
//     }
//     ae_promises.update__journal_entry_obj = api.update_ae_obj_id_crud({
//         api_cfg: api_cfg,
//         obj_type: 'journal_entry',
//         obj_id: journal_entry_id,
//         fields: data_kv,
//         key: api_cfg.api_crud_super_key,
//         params: params,
//         return_obj: true,
//         log_lvl: log_lvl
//         })
//     .then(async function (journal_entry_obj_update_result) {
//         // if (journal_entry_obj_update_result) {
//             if (try_cache) {
//                 db_save_ae_obj_li__journal_entry({
//                     obj_type: 'journal_entry',
//                     obj_li: [journal_entry_obj_update_result],
//                     log_lvl: log_lvl
//                 })
//                 .then(function (result) {
//                     return result;
//                 })
//                 .finally(function () {
//                     return journal_entry_obj_update_result;
//                 });
//             } else {
//                 return journal_entry_obj_update_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.update__journal_entry_obj:', ae_promises.update__journal_entry_obj);
//     }
//     return await ae_promises.update__journal_entry_obj;
// }

// Updated 2026-01-05
export async function update_ae_obj__journal_entry({
    api_cfg,
    journal_entry_id,
    data_kv,
    params = {},
    try_cache = true,
    log_lvl = 0
}: {
    api_cfg: any;
    journal_entry_id: string;
    data_kv: key_val;
    params?: key_val;
    try_cache?: boolean;
    log_lvl?: number;
}): Promise<ae_JournalEntry | null> {
    if (log_lvl) {
        console.log(
            `*** update_ae_obj__journal_entry() *** journal_entry_id=${journal_entry_id}`,
            data_kv
        );
    }

    // Perform the API update
    const result = await api.update_ae_obj({
        api_cfg: api_cfg,
        obj_type: 'journal_entry',
        obj_id: journal_entry_id,
        fields: data_kv,
        params: params,
        log_lvl: log_lvl
    });

    // Handle the result
    if (result) {
        if (try_cache) {
            // Process the results first
            const processed_obj_li = await process_ae_obj__journal_entry_props({
                obj_li: [result],
                log_lvl: log_lvl
            });
            if (log_lvl) {
                console.log('Processed object list:', processed_obj_li);
            }
            // IDB write is optional caching — quota failures must not discard the API result.
            try {
                await db_save_ae_obj_li__ae_obj({
                    db_instance: db_journals,
                    table_name: 'journal_entry',
                    obj_li: processed_obj_li,
                    properties_to_save: properties_to_save,
                    log_lvl: log_lvl
                });
            } catch (save_error) {
                console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
            }
        }
        return result;
    } else {
        console.error('Failed to update journal entry.');
        return null;
    }
}

// // This function will loop through the journal_entry_obj_li and save each one to the DB.
// // Updated 2025-05-09
// export async function db_save_ae_obj_li__journal_entry({
//     obj_type,
//     obj_li,
//     log_lvl = 0
// }: {
//     obj_type: string;
//     obj_li: any;
//     log_lvl?: number;
// }) {
//     // log_lvl = 1;
//     if (log_lvl) {
//         console.log(`*** db_save_ae_obj_li__journal_entry() *** obj_type=${obj_type}`, obj_li);
//     }

//     if (obj_li && obj_li.length) {
//         // let obj_li_id = obj_li.map((obj: any) => obj.journal_entry_id);
//         const obj_li_id: string[] = [];

//         for (const obj of obj_li) {
//             // obj_li.forEach(async function (obj: any) {
//             if (log_lvl) {
//                 console.log(`Processing ae_obj ${obj_type}:`, obj);
//             }

//             let content = obj.content ?? '';
//             // remove the most common zerowidth characters from the start of the file
//             let content_cleaned: null | string = null;
//             let content_md_html: null | string = null; // await marked.parse(content_cleaned ?? '') ?? null;
//             // let content_md_html_alt: null|string = await marked.parse(content_cleaned ?? '', { gfm: false }) ?? null;

//             if (obj.content_encrypted) {
//                 // In theory "content" should be null if "content_encrypted" has a value.
//                 content = null; // obj.content_encrypted;
//                 content_cleaned = null;
//                 content_md_html = null;
//             } else {
//                 content_cleaned = content.replace(/^[\u200B\u200C\u200D\u200E\u200F\uFEFF]/, '');
//                 content_md_html = (await marked.parse(content_cleaned ?? '')) ?? null;
//             }

//             let history = obj.history ?? '';
//             let history_cleaned: null | string = null;
//             let history_md_html: null | string = null; // await marked.parse(history_cleaned ?? '') ?? null;

//             if (obj.history_encrypted) {
//                 // In theory "history" should be null if "history_encrypted" has a value.
//                 history = null; // obj.history_encrypted;
//                 history_cleaned = null;
//                 history_md_html = null;
//             } else {
//                 history_cleaned = history.replace(/^[\u200B\u200C\u200D\u200E\u200F\uFEFF]/, '');
//                 history_md_html = (await marked.parse(history_cleaned ?? '')) ?? null;
//             }

//             const obj_record = {
//                 id: obj.journal_entry_id,
//                 journal_entry_id: obj.journal_entry_id,

//                 journal_id: obj.journal_id,

//                 code: obj.code,

//                 for_type: obj.for_type,
//                 for_id: obj.for_id,

//                 journal_entry_type: obj.journal_entry_type,

//                 person_id: obj.person_id,

//                 template: obj.template ?? null, // Allow for a template to be used, otherwise null

//                 activity_code: obj.activity_code,
//                 category_code: obj.category_code,
//                 type_code: obj.type_code,
//                 topic_code: obj.topic_code,
//                 tags: obj.tags,

//                 public: obj.public,
//                 private: obj.private,
//                 personal: obj.personal,
//                 professional: obj.professional,

//                 name: obj.name,
//                 short_name: obj.short_name ?? null,
//                 summary: obj.summary,
//                 outline: obj.outline,
//                 // description: obj.description,

//                 content: obj.content,
//                 content_md_html: content_md_html ?? undefined,
//                 // content_md_html_alt: content_md_html_alt,
//                 content_html: obj.content_html,
//                 content_json: obj.content_json,
//                 content_encrypted: obj.content_encrypted,

//                 history: obj.history,
//                 history_md_html: history_md_html ?? undefined,
//                 history_encrypted: obj.history_encrypted,

//                 passcode_hash: obj.passcode_hash,

//                 // url: obj.url,
//                 // url_text: obj.url_text,

//                 // hosted_file_id: obj.hosted_file_id,

//                 // file_path: obj.file_path,

//                 // filename: obj.filename,
//                 // file_extension: obj.file_extension,

//                 // start_datetime: obj.start_datetime,
//                 // end_datetime: obj.end_datetime,
//                 // timezone: obj.timezone,

//                 // original_datetime: obj.original_datetime,
//                 // original_timezone: obj.original_timezone,
//                 // original_location: obj.original_location,
//                 // original_url: obj.original_url,
//                 // original_url_text: obj.original_url_text,

//                 // enable_for_public: obj.enable_for_public,

//                 alert: obj.alert,
//                 alert_msg: obj.alert_msg,

//                 // cfg_json: obj.cfg_json ?? {},
//                 data_json: obj.data_json ?? {},

//                 // This only allows for basic access to the data.
//                 // passcode_read: obj.passcode_read, // For LLM (AI) generated summary...???
//                 // passcode_read_expire: obj.passcode_read_expire,
//                 // passcode_write: obj.passcode_write,
//                 // passcode_write_expire: obj.passcode_write_expire,

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

//                 // Generated fields for sorting locally only
//                 tmp_sort_1: `${obj.group}_${obj.priority}_${obj.sort}_${obj.updated_on}_${obj.created_on}`,
//                 tmp_sort_2: `${obj.group}_${obj.priority}_${obj.sort}_${obj.updated_on ?? obj.created_on}`,
//                 // tmp_sort_1: `${obj.original_datetime}_${obj.group}_${obj.priority}_${obj.sort}`,
//                 // tmp_sort_2: `${obj.group}_${obj.original_datetime}_${obj.priority}_${obj.sort}`,

//                 // Generated fields for sorting locally only
//                 // tmp_sort_1: `${obj.original_datetime}_${obj.group}_${obj.priority}_${obj.sort}`,
//                 // tmp_sort_2: `${obj.group}_${obj.original_datetime}_${obj.priority}_${obj.sort}`,

//                 // From SQL view
//                 journal_code: obj.journal_code,
//                 journal_name: obj.journal_name

//                 // A key value list of the others
//                 // journal_other_kv: obj.journal_other_kv,
//                 // journal_other_li: obj.journal_other_li,
//             };

//             let id_random = null;

//             try {
//                 id_random = await db_journals.journal_entry.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_journals.journal_entry.put(obj_record);
//                 } catch (error) {
//                     console.log(`Error: Failed to put ${obj.journal_entry_id}: ${error}`);
//                 }
//             } else {
//                 if (log_lvl) {
//                     console.log(`Updated record with ID: ${obj_record.id}`);
//                 }
//                 obj_li_id.push(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 obj_li_id;
//     } else {
//         if (log_lvl) {
//             console.log('No objects to save.');
//         }
//         return [];
//     }
// }

// Updated 2025-05-09
const properties_to_save = [
    'id',
    'journal_entry_id',

    'journal_id',

    'code',

    'for_type',
    'for_id',

    'journal_entry_type',

    'person_id',

    'template', // Allow for a template to be used, otherwise null

    'activity_code',
    'category_code',
    'type_code',
    'topic_code',
    'tags',

    'public',
    'private',
    'personal',
    'professional',

    'name',
    'short_name',
    'summary',
    'outline',
    // 'description',

    'content',
    // content_md_html is computed from content on every load — not stored to save IDB quota
    'content_html',
    'content_json',
    'content_encrypted',

    'history',
    // history_md_html is computed from history on every load — not stored to save IDB quota
    'history_encrypted',

    'passcode_hash',

    'alert',
    'alert_msg',

    // 'cfg_json',
    'data_json',

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

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

    // From SQL view
    'journal_code',
    'journal_name'

    // A key value list of the others
    // 'journal_other_kv',
    // 'journal_other_li',
];

/**
 * 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
        for (const key in processed_obj) {
            if (key.endsWith('_random')) {
                const newKey = key.slice(0, -7); // Remove '_random' suffix
                (processed_obj as any)[newKey] = processed_obj[key];
            }
        }
        // Ensure 'id' is set from '[obj_type]_id_random'
        const randomIdKey = `${obj_type}_id`;
        if (processed_obj[randomIdKey]) {
            (processed_obj as any).id = processed_obj[randomIdKey];
        }

        // 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 ??
            new Date(0).toISOString();
        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-05-09
export async function process_ae_obj__journal_entry_props({
    obj_li,
    journal_id,
    log_lvl = 0
}: {
    obj_li: any[];
    journal_id?: string;
    log_lvl?: number;
}) {
    return _process_generic_props({
        obj_li,
        obj_type: 'journal_entry',
        log_lvl,
        specific_processor: async (obj) => {
            // Inject journal_id if provided and missing
            if (journal_id) {
                if (!obj.journal_id) obj.journal_id = journal_id;
                // if (!obj.journal_id_random) obj.journal_id_random = journal_id;
            }

            // Content processing
            let content = obj.content ?? '';
            let content_cleaned: null | string = null;
            let content_md_html: null | string = null;

            if (obj.content_encrypted) {
                content = null;
                content_cleaned = null;
                content_md_html = null;
            } else {
                content_cleaned = content.replace(
                    /^[\u200B\u200C\u200D\u200E\u200F\uFEFF]/,
                    ''
                );
                content_md_html =
                    (await marked.parse(content_cleaned ?? '')) ?? null;
            }
            obj.content = content;
            obj.content_md_html = content_md_html;

            // History processing
            let history = obj.history ?? '';
            let history_cleaned: null | string = null;
            let history_md_html: null | string = null;

            if (obj.history_encrypted) {
                history = null;
                history_cleaned = null;
                history_md_html = null;
            } else {
                history_cleaned = history.replace(
                    /^[\u200B\u200C\u200D\u200E\u200F\uFEFF]/,
                    ''
                );
                history_md_html =
                    (await marked.parse(history_cleaned ?? '')) ?? null;
            }
            obj.history = history;
            obj.history_md_html = history_md_html;

            // Journal entry-specific computed sort fields via build_tmp_sort.
            // Order: priority DESC → sort ASC → name ASC → updated ASC (all ascending, no .reverse())
            const updated =
                obj.updated_on ?? obj.created_on ?? new Date(0).toISOString();
            const { tmp_sort_1, tmp_sort_2, tmp_sort_3 } = build_tmp_sort({
                prefix: [obj.group ?? ''],
                priority: obj.priority,
                sort: obj.sort,
                fields_2: [obj.name],
                fields_3: [updated]
            });
            obj.tmp_sort_1 = tmp_sort_1;
            obj.tmp_sort_2 = tmp_sort_2;
            obj.tmp_sort_3 = tmp_sort_3;

            return obj;
        }
    });
}
