<script lang="ts">
// untrack import removed — task_id sync now uses direct $effect (no untrack needed)
// Imports
// Import components and elements
import * as Lucide from '@lucide/svelte';
import Element_input_files_tbl from '$lib/elements/element_input_files_tbl.svelte';

// Import storage, functions, and libraries
import type { key_val } from '$lib/stores/ae_stores';

import { api } from '$lib/ae_api/api';
import {
    ae_snip,
    ae_loc,
    ae_sess,
    ae_api,
    ae_trig,
    slct,
    slct_trigger
} from '$lib/stores/ae_stores';

// Exports

interface Props {
    log_lvl?: number;
    // Expecting these for link_to_type: 'event', 'event_location', 'archive_content', etc
    link_to_type: string;
    link_to_id: string;
    input_name?: string;
    multiple?: boolean;
    required?: boolean;
    accept?: string;
    class_li_default?: string;
    class_li?: string;
    input_class_li?: string[];
    table_class_li?: string[];
    upload_complete?: boolean;
    submit_status?: null | string;
    hosted_file_id_li?: string[];
    hosted_file_obj_li?: any[];
    hosted_file_obj_kv?: key_val;
    label?: import('svelte').Snippet;
}

let {
    log_lvl = 0,
    link_to_type,
    link_to_id,
    input_name = 'file_list',
    multiple = true,
    required = true,
    accept = 'audio/*, image/*, video/*, .bak, .cfg, .css, .csv, .doc, .docx, .gz, .htm, .html, .ini, .iso, .j2, .json, .key, .keynote, .md, .pdf, .ppt, .pptx, .rar, .rtf, .sql, .svelte, .ttf, .txt, .xls, .xlsx, .xz, .zip, .bin, .dmg, .exe, .js, .msi, .php, .py, .sh',
    class_li_default = 'flex flex-col gap-1 items-center justify-center w-full max-w-2xl mx-auto my-1',
    class_li = '',
    input_class_li = ['file_drop_area'],
    table_class_li = ['table', 'table-sm', 'table-striped', '', 'text-sm'],
    upload_complete = $bindable(false),
    submit_status = $bindable(null),
    hosted_file_id_li = $bindable([]),
    hosted_file_obj_li = $bindable([]),
    hosted_file_obj_kv = $bindable({}),
    label
}: Props = $props();

// Local Variables
let task_id: string = $state('');
let input_file_list: any = $state(null);
let ae_promises: key_val = $state({}); // Promise<any>;
// let ae_triggers: key_val = {};

let input_element_id = 'ae_comp__hosted_files_upload__input';

$effect(() => {
    if (log_lvl) {
        console.log(`*** ae_comp__hosted_files_upload.svelte ***`);
        console.log(`link_to_type: ${link_to_type} link_to_id: ${link_to_id}`);
    }
});

$effect(() => {
    // Only sync task_id when idle — don't reset during an in-flight upload.
    if (!ae_promises.upload__hosted_file_obj) {
        task_id = link_to_id;
    }
});

function prevent_default<T extends Event>(fn: (event: T) => void) {
    return function (event: T) {
        event.preventDefault();
        fn(event);
    };
}

// *** Functions and Logic
async function handle_submit_form_files(event: SubmitEvent) {
    if (log_lvl) console.log('*** handle_submit_form() ***');

    $ae_sess.files.disable_submit__hosted_file_obj = true;
    $ae_sess.files.submit_status = 'saving';
    submit_status = 'saving';
    upload_complete = false;

    hosted_file_id_li = [];
    hosted_file_obj_li = [];
    hosted_file_obj_kv = {};

    let hosted_file_results;

    const target = event.currentTarget as HTMLFormElement;
    const file_input = target
        ? (target[input_element_id] as HTMLInputElement)
        : null;

    if (
        target &&
        file_input &&
        file_input.files &&
        file_input.files.length > 0
    ) {
        for (let i = 0; i < file_input.files.length; i++) {
            task_id = $ae_sess.files.processed_file_list[i].hash_sha256;
            hosted_file_results = await handle_input_upload_files({
                input_upload_files: [file_input.files[i]],
                task_id: task_id
            });
            if (log_lvl > 1) console.log('hosted_file_results:', hosted_file_results);
        }
        $ae_sess.files.processed_file_list = [];
        target.reset();
        if (log_lvl) console.log('hosted_file_id_li:', hosted_file_id_li);
    }

    $ae_sess.files.disable_submit__hosted_file_obj = false;
    $ae_sess.files.submit_status = 'saved';
    submit_status = 'saved';
    upload_complete = true;
}

async function handle_input_upload_files({
    input_upload_files,
    task_id
}: {
    input_upload_files: any[];
    task_id: string;
}) {
    if (log_lvl) console.log('*** handle_input_upload_files() ***');

    const form_data = new FormData();
    form_data.append('account_id', $ae_loc.account_id);
    form_data.append('link_to_type', link_to_type);
    form_data.append('link_to_id', link_to_id);
    for (let i = 0; i < input_upload_files.length; i++) {
        form_data.append('file_list', input_upload_files[i]);
    }

    // Promise assigned to state so {#await ae_promises.upload__hosted_file_obj} in the
    // template can track it. Using await here instead would hide the promise from the template.
    ae_promises.upload__hosted_file_obj = api
        .post_object({
            api_cfg: $ae_api,
            endpoint: '/v3/action/hosted_file/upload',
            form_data: form_data,
            timeout: 1200000, // 20 min — large video/audio files
            task_id: task_id,
            track_progress: true,
            log_lvl: log_lvl
        })
        .then(function (result) {
            // Endpoint always returns a list; we upload one file at a time.
            if (!result || !result[0]) {
                console.error('Upload failed — no result returned.');
                return false;
            }
            const hosted_file_obj = result[0];
            const hosted_file_id = hosted_file_obj.hosted_file_id;

            hosted_file_id_li.push(hosted_file_id);
            hosted_file_obj_li.push(hosted_file_obj);

            const hosted_file_data: key_val = {
                id: hosted_file_id,
                hosted_file_id: hosted_file_id,
                for_type: link_to_type,
                for_id: link_to_id,
                hash_sha256: hosted_file_obj.hash_sha256,
                filename: hosted_file_obj.filename,
                extension: hosted_file_obj.extension,
                content_type: hosted_file_obj.content_type,
                size: hosted_file_obj.size,
                enable: true,
                created_on: hosted_file_obj.created_on,
                updated_on: hosted_file_obj.updated_on
            };
            hosted_file_obj_kv[hosted_file_id] = hosted_file_data;
            if (log_lvl) console.log('hosted_file_data:', hosted_file_data);
            return hosted_file_data;
        })
        .catch(function (error: any) {
            console.error('Upload failed:', error);
            return false;
        })
        .finally(function () {
            $slct_trigger = 'load__hosted_file_obj_li';
        });

    return ae_promises.upload__hosted_file_obj;
}
</script>

<!-- class:hidden={!$ae_loc.trusted_access} -->
<form onsubmit={prevent_default(handle_submit_form_files)} class="{class_li_default} {class_li}">
    {#await ae_promises.upload__hosted_file_obj}
        <div class="flex flex-row items-center justify-center gap-1 text-lg">
            <Lucide.LoaderCircle class="m-1 animate-spin" />
            <span class="">
                Uploading
                {#if $ae_sess.api_upload_kv[task_id]}
                    {$ae_sess.api_upload_kv[task_id].percent_completed}%
                {/if}
            </span>
        </div>
    {/await}

    <label
        for={input_element_id}
        class="svelte_input_file_label text-center"
        class:hidden={$ae_sess.files.disable_submit__hosted_file_obj}>
        {#if label}{@render label()}{:else}
            <div class="mb-2 flex items-center justify-center gap-2">
                <Lucide.Upload class="text-primary-500" />
                <strong class="preset-tonal-primary rounded-full px-3 py-1"
                    >Select Files</strong>
            </div>
            <span class="text-sm text-gray-600 italic dark:text-gray-400">
                <strong>Supported formats</strong><br />
                (PowerPoint, Keynote, PDF, Media, etc)
            </span>
        {/if}
    </label>

    <input
        id={input_element_id}
        type="file"
        bind:files={input_file_list}
        {multiple}
        {required}
        {accept}
        name={input_name}
        class="
            svelte_input_file_element
            file-dropzone-input
            preset-filled-surface-50-950
            text-surface-900 dark:text-surface-100 border-surface-300
            dark:border-surface-700
            focus:ring-primary-500 block
            w-full cursor-pointer rounded-lg border
            px-1
            text-lg focus:ring-2 focus:outline-hidden
            {input_class_li.join(' ')}
            "
        class:hidden={$ae_sess.files.disable_submit__hosted_file_obj} />

    <Element_input_files_tbl
        bind:input_file_list
        bind:file_list_status={$ae_sess.files.status__file_list}
        bind:processed_file_list={$ae_sess.files.processed_file_list}
        {table_class_li} />

    <button
        type="submit"
        class="
            btn btn-lg btn-primary
            preset-tonal-primary
            border border-primary-500
            hover:preset-tonal-success hover:border-success-500
            w-54
            transition-all
            "
        class:opacity-30={$ae_sess.files.disable_submit__hosted_file_obj ||
            $ae_sess.files.status__file_list != 'ready'}
        disabled={$ae_sess.files.disable_submit__hosted_file_obj ||
            $ae_sess.files.status__file_list != 'ready'}
        >
        {#await ae_promises.upload__hosted_file_obj}
            <Lucide.LoaderCircle class="m-1 animate-spin" />
            <span class="">
                {#if $ae_sess.api_upload_kv[task_id]}
                    {$ae_sess.api_upload_kv[task_id].percent_completed}%
                {:else}
                    ...
                {/if}
            </span>
        {:then}
            <Lucide.CloudUpload class="m-1" size={20} />
            <span class="text-sm"> Upload </span>
            {#if $ae_sess.files.processed_file_list?.length > 0}
            <span class="ml-2 grow font-bold">
                    {$ae_sess.files.processed_file_list.length}
                    {$ae_sess.files.processed_file_list.length === 1
                        ? 'file'
                        : 'files'}
            </span>
                {:else}
                    <span class="text-xs"> none </span>
                {/if}
        {/await}
    </button>
</form>
