<script lang="ts">
/**
 * src/routes/events/ae_comp__event_files_upload.svelte
 * Specialized component for uploading files and automatically linking them to Event objects.
 */
import { LoaderCircle, Upload, UploadCloud } 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_loc,
    ae_sess,
    ae_api,
    ae_trig,
    slct,
    slct_trigger
} from '$lib/stores/ae_stores';
import {
    events_sess,
    events_slct,
    events_trig
} from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events/ae_events_functions';

interface Props {
    log_lvl?: number;
    // Expecting these for link_to_type: 'event', 'event_location', 'event_presentation', 'event_presenter', 'event_session'
    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;
    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),
    label
}: Props = $props();

// Local Variables
let task_id: string = $state('');
let input_file_list: any = $state(null);
let ae_promises: key_val = $state({});
let input_element_id = 'ae_comp__event_files_upload__input';

// WHY: Keep task_id in sync with prop if it hasn't been set by an upload cycle yet
$effect(() => {
    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);
    };
}

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

    $events_sess.files.disable_submit__event_file_obj = true;
    $events_sess.files.submit_status = 'saving';
    submit_status = 'saving';
    upload_complete = false;

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

    if (file_input && file_input.files && file_input.files.length > 0) {
        // Sequential upload to provide reliable progress and avoid server race conditions
        for (let i = 0; i < file_input.files.length; i++) {
            const tmp_file = file_input.files[i];
            task_id = $events_sess.files.processed_file_list[i].hash_sha256;

            await handle_input_upload_files({
                input_upload_files: [tmp_file],
                task_id: task_id
            });
        }

        // Cleanup after batch
        $events_sess.files.processed_file_list = [];
        target.reset();

        // Refresh the file list for this object only.
        // WHY: Previously used db_events.file.clear() here, which nuked the ENTIRE
        // file table in Dexie. Every liveQuery watching any file list would immediately
        // show 0 results, and only this object's files were reloaded. Files for all
        // other objects (locations, sessions, presenters) remained missing until their
        // own background syncs fired. Targeted reload avoids that side effect.
        await events_func.load_ae_obj_li__event_file({
            api_cfg: $ae_api,
            for_obj_type: link_to_type,
            for_obj_id: link_to_id,
            enabled: 'all',
            hidden: 'all',
            try_cache: true
        });
    }

    $events_sess.files.disable_submit__event_file_obj = false;
    $events_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() *** task_id = ${task_id}`);

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

    // STEP 1: Upload to Hosted Files
    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 minutes — large presentation files can be very slow to upload
            task_id: task_id,
            track_progress: true,
            log_lvl: log_lvl
        })
        .then(async function (result) {
            // WARNING: endpoint returns a list, we sequentially handle one at a time.
            if (!result || !result[0]) {
                console.error('Upload failed or timed out — no result returned.');
                return false;
            }
            const hosted_file_obj = result[0];
            const hosted_file_id = hosted_file_obj.hosted_file_id;

            const event_file_data: key_val = {
                hosted_file_id: hosted_file_id,
                for_type: link_to_type,
                for_id: link_to_id,
                filename: hosted_file_obj.filename,
                extension: hosted_file_obj.extension,
                enable: true
            };

            // STEP 2: Create Event File Link
            return await events_func.create_event_file_obj_from_hosted_file_async(
                {
                    api_cfg: $ae_api,
                    hosted_file_id: hosted_file_id,
                    data: event_file_data,
                    log_lvl: log_lvl
                }
            );
        })
        .catch(function (error: any) {
            console.error('Upload Process Failed:', error);
            return false;
        })
        .finally(function () {
            $slct_trigger = 'load__event_file_obj_li';
        });

    return ae_promises.upload__hosted_file_obj;
}
</script>

<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">
            <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}

    <div
        class="
            border-primary-500 preset-filled-primary-50-950 hover:border-primary-800 w-full
            cursor-pointer rounded-lg border-2
            border-dashed p-1
            transition-colors hover:border-2
            "
        class:hidden={$events_sess.files.disable_submit__event_file_obj}>
        <label
            for={input_element_id}
            class="
            svelte_input_file_label
            cursor-pointer
            text-center
            "
            class:hidden={$events_sess.files.disable_submit__event_file_obj}>
            {#if label}{@render label()}{:else}
                <div class="mb-2 flex items-center justify-center gap-2 pt-2">
                    <Upload class="text-primary-500" />
                    <strong class="preset-tonal-primary rounded-full px-3 py-1"
                        >Select Files</strong>
                </div>
                <div
                    class="pb-2 text-sm text-gray-600 italic dark:text-gray-400">
                    <strong>Presentation materials only</strong><br />
                    (PPTX, Keynote, PDF, MP4, etc)
                </div>
            {/if}
        </label>

        <input
            id={input_element_id}
            type="file"
            bind:files={input_file_list}
            {multiple}
            {required}
            {accept}
            name={input_name}
            class:hidden={$events_sess.files.disable_submit__event_file_obj}
            class="
            svelte_input_file_element file-dropzone-input
            preset-tonal-primary preset-outlined-primary-200-800 hover:preset-filled-success-200-800 block
            w-full
            cursor-pointer
            rounded-lg
            p-1 text-center text-lg
            transition-all
            {input_class_li.join(' ')}
            " />
    </div>

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

    <button
        type="submit"
        class="
            btn btn-lg
            preset-tonal-primary
            border-primary-500 hover:preset-tonal-success hover:border-success-500 flex w-54
            items-center justify-center border
            text-lg
            transition-all
            "
        disabled={$events_sess.files.disable_submit__event_file_obj ||
            $events_sess.files.status__file_list === 'blocked_legacy'}>
        {#await ae_promises.upload__hosted_file_obj}
            <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}
            <UploadCloud class="m-1" size={20} />
            <span class="text-sm"> Upload </span>
            <span class="ml-2 grow font-bold">
                {#if $events_sess.files.processed_file_list?.length > 0}
                    {$events_sess.files.processed_file_list.length}
                    {$events_sess.files.processed_file_list.length === 1
                        ? 'file'
                        : 'files'}
                {:else}
                    <span class="text-xs"> 0 </span>
                {/if}
            </span>
        {/await}
    </button>
</form>
