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 { db_core } from '$lib/ae_core/db_core';
import type { ae_HostedFile } from '$lib/types/ae_types';

const ae_promises: key_val = {};

// Updated 2026-01-20 to V3
export async function load_ae_obj_id__hosted_file({
    api_cfg,
    hosted_file_id,
    view = 'default',
    try_cache = true,
    log_lvl = 0
}: {
    api_cfg: any;
    hosted_file_id: string;
    view?: string;
    try_cache?: boolean;
    log_lvl?: number;
}): Promise<ae_HostedFile | null> {
    if (log_lvl) {
        console.log(
            `*** load_ae_obj_id__hosted_file() *** [V3] id=${hosted_file_id}`
        );
    }

    try {
        ae_promises.load__hosted_file_obj = await api.get_ae_obj({
            api_cfg,
            obj_type: 'hosted_file',
            obj_id: hosted_file_id,
            view,
            log_lvl
        });

        if (ae_promises.load__hosted_file_obj) {
            if (try_cache) {
                const processed_obj_li =
                    await process_ae_obj__hosted_file_props({
                        obj_li: [ae_promises.load__hosted_file_obj],
                        log_lvl
                    });
                await db_save_ae_obj_li__ae_obj({
                    db_instance: db_core,
                    table_name: 'file',
                    obj_li: processed_obj_li,
                    properties_to_save,
                    log_lvl
                });
            }
        } else if (try_cache) {
            ae_promises.load__hosted_file_obj =
                await db_core.file.get(hosted_file_id);
        }
    } catch (error: any) {
        console.log('V3 Request failed.', error);
        if (try_cache) {
            ae_promises.load__hosted_file_obj =
                await db_core.file.get(hosted_file_id);
        }
    }

    return ae_promises.load__hosted_file_obj || null;
}

// Updated 2026-01-20 to V3
export async function load_ae_obj_li__hosted_file({
    api_cfg,
    for_obj_type,
    for_obj_id,
    enabled = 'enabled',
    hidden = 'not_hidden',
    limit = 100,
    offset = 0,
    order_by_li = [
        { priority: 'DESC' },
        { sort: 'DESC' },
        { updated_on: 'DESC' }
    ],
    try_cache = true,
    log_lvl = 0
}: {
    api_cfg: any;
    for_obj_type: string;
    for_obj_id: string;
    enabled?: 'enabled' | 'all' | 'not_enabled';
    hidden?: 'hidden' | 'all' | 'not_hidden';
    limit?: number;
    offset?: number;
    order_by_li?: any;
    try_cache?: boolean;
    log_lvl?: number;
}): Promise<ae_HostedFile[]> {
    if (log_lvl) {
        console.log(
            `*** load_ae_obj_li__hosted_file() *** [V3] for=${for_obj_type}:${for_obj_id}`
        );
    }

    try {
        ae_promises.load__hosted_file_obj_li = await api.get_ae_obj_li({
            api_cfg,
            obj_type: 'hosted_file',
            for_obj_type,
            for_obj_id,
            enabled,
            hidden,
            limit,
            offset,
            order_by_li,
            log_lvl
        });

        if (ae_promises.load__hosted_file_obj_li) {
            if (try_cache) {
                const processed_obj_li =
                    await process_ae_obj__hosted_file_props({
                        obj_li: ae_promises.load__hosted_file_obj_li,
                        log_lvl
                    });
                await db_save_ae_obj_li__ae_obj({
                    db_instance: db_core,
                    table_name: 'file',
                    obj_li: processed_obj_li,
                    properties_to_save,
                    log_lvl
                });
            }
        } else if (try_cache) {
            ae_promises.load__hosted_file_obj_li = await db_core.file
                .where('for_id')
                .equals(for_obj_id)
                .toArray();
        }
    } catch (error: any) {
        console.log('V3 List Request failed.', error);
        if (try_cache) {
            ae_promises.load__hosted_file_obj_li = await db_core.file
                .where('for_id')
                .equals(for_obj_id)
                .toArray();
        }
    }

    return ae_promises.load__hosted_file_obj_li || [];
}

// Updated 2026-01-22 to use special endpoint
export async function delete_ae_obj_id__hosted_file({
    api_cfg,
    hosted_file_id,
    link_to_type,
    link_to_id,
    rm_orphan = false,
    fake_delete = false,
    try_cache = true,
    log_lvl = 0
}: {
    api_cfg: any;
    hosted_file_id: string;
    link_to_type: string;
    link_to_id: string;
    rm_orphan?: boolean;
    fake_delete?: boolean;
    try_cache?: boolean;
    log_lvl?: number;
}) {
    if (log_lvl) {
        console.log(
            `*** delete_ae_obj_id__hosted_file() *** [Special] id=${hosted_file_id}`
        );
    }

    // Use the specialized hosted file delete endpoint
    const result = await api.delete_hosted_file({
        api_cfg,
        hosted_file_id,
        link_to_type,
        link_to_id,
        rm_orphan,
        params: { fake_delete },
        log_lvl
    });

    if (try_cache) {
        await db_core.file.delete(hosted_file_id);
    }

    return result;
}

/**
 * Download a hosted file (V3 Action)
 * Uses the new /v3/action/... standard.
 * Updated 2026-02-03
 */
export async function download_ae_obj_id__hosted_file({
    api_cfg,
    hosted_file_id,
    return_file = true,
    filename,
    auto_download = false,
    params = {},
    log_lvl = 0
}: {
    api_cfg: any;
    hosted_file_id: string;
    return_file?: boolean;
    filename?: string;
    auto_download?: boolean;
    params?: key_val;
    log_lvl?: number;
}) {
    if (log_lvl) {
        console.log(
            `*** download_ae_obj_id__hosted_file() *** id=${hosted_file_id}`
        );
    }

    const task_id = hosted_file_id;
    const endpoint = `/v3/action/hosted_file/${hosted_file_id}/download`;

    const query_params: key_val = { ...params };
    if (filename) {
        query_params['filename'] = filename;
    }
    query_params['return_file'] = 'true'; // V3 prefers string 'true' for bool flags in query

    return await api.get_object({
        api_cfg,
        endpoint,
        params: query_params,
        return_blob: return_file,
        filename,
        auto_download,
        task_id,
        log_lvl
    });
}

export const properties_to_save = [
    'id',
    'hosted_file_id',
    'hash_sha256',
    'for_type',
    'for_id',
    'account_id',
    'filename',
    'extension',
    'content_type',
    'size',
    'enable',
    'hide',
    'priority',
    'sort',
    'group',
    'notes',
    'created_on',
    'updated_on',
    'tmp_sort_1',
    'tmp_sort_2',
    'filename_no_ext',
    'filename_w_ext'
];

/**
 * NON-EXPORTED LOCAL HELPER
 */
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 (!obj_li || obj_li.length === 0) return [];

    const processed_obj_li: T[] = [];

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

        for (const key in processed_obj) {
            if (key.endsWith('_random')) {
                const newKey = key.slice(0, -7);
                (processed_obj as any)[newKey] = processed_obj[key];
            }
        }
        const randomIdKey = `${obj_type}_id_random`;
        if (processed_obj[randomIdKey]) {
            (processed_obj as any).id = processed_obj[randomIdKey];
        }

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

        if (specific_processor) {
            processed_obj = await Promise.resolve(
                specific_processor(processed_obj)
            );
        }

        processed_obj_li.push(processed_obj as T);
    }

    return processed_obj_li;
}

export async function process_ae_obj__hosted_file_props({
    obj_li,
    log_lvl = 0
}: {
    obj_li: any[];
    log_lvl?: number;
}) {
    return _process_generic_props({
        obj_li,
        obj_type: 'hosted_file',
        log_lvl
    });
}
