<script lang="ts">
// import { createEventDispatcher } from 'svelte';
import { Loader2 } from '@lucide/svelte';
import type { key_val } from '$lib/stores/ae_stores';
import { events_func } from '$lib/ae_events/ae_events_functions';
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
import { api } from '$lib/ae_api/api';

interface Props {
    event_id: string;
    onsuccess?: () => void;
    oncancel?: () => void;
    onerror?: (error: any) => void;
}

let { event_id, onsuccess, oncancel, onerror }: Props = $props();

// const dispatch = createEventDispatcher();

let file_input: HTMLInputElement | undefined = $state();
let selected_file: File | null = $state(null);
let upload_status: string = $state('idle'); // idle, loading, processing, success, error
let upload_message: string = $state('');
let processed_badges_count: number = $state(0);
let total_badges_in_file: number = $state(0);
let upload_mode: 'client_csv' | 'axonius_zoom' | 'axonius_splash_xlsx' = $state('axonius_zoom');
let begin_at: number | null = $state(null);
let end_at: number | null = $state(null);
let return_detail: boolean = $state(false);
let import_status_filter: string = $state('Attending'); // splash only; set to '' to import all statuses

// A very basic CSV parser that assumes the first row is headers
function parse_csv(text: string): key_val[] {
    const lines = text.trim().split('\n');
    if (lines.length === 0) return [];

    const headers = lines[0].split(',').map((h) => h.trim());
    const data = lines.slice(1).map((line) => {
        const values = line.split(',').map((v) => v.trim());
        const obj: key_val = {};
        headers.forEach((header, index) => {
            obj[header] = values[index];
        });
        return obj;
    });
    return data;
}

async function handle_file_change(event: Event) {
    const target = event.target as HTMLInputElement;
    if (target.files && target.files.length > 0) {
        selected_file = target.files[0];
        upload_message = `Selected file: ${selected_file.name}`;
    } else {
        selected_file = null;
        upload_message = '';
    }
}

async function handle_upload(event: Event) {
    event.preventDefault();
    if (!selected_file) {
        upload_message = 'Please select a file first.';
        upload_status = 'error';
        return;
    }

    // Server-side import for Cvent Splash XLSX
    if (upload_mode === 'axonius_splash_xlsx') {
        upload_status = 'loading';
        upload_message = 'Uploading to server...';

        const formData = new FormData();
        formData.append('file', selected_file, selected_file.name);

        const params: any = {};
        if (begin_at !== null && begin_at !== undefined) params.begin_at = String(begin_at);
        if (end_at !== null && end_at !== undefined) params.end_at = String(end_at);
        if (import_status_filter !== 'Attending') params.import_status_filter = import_status_filter;
        if (return_detail) params.return_detail = String(true);

        const task_id = (crypto && (crypto as any).randomUUID)
            ? (crypto as any).randomUUID()
            : String(Date.now());

        try {
            upload_status = 'processing';
            upload_message = 'Processing on server… this may take a minute or two.';
            const endpoint = `/event/${event_id}/badge/import/splash_xlsx`;
            const result = await api.post_object({
                api_cfg: $ae_api,
                endpoint,
                form_data: formData,
                params,
                return_meta: true,
                task_id,
                timeout: 300000, // 5 min — server-side import can be slow; no retry to avoid duplicate imports
                retry_count: 1,
                log_lvl: 0
            });

            if (!result) {
                upload_status = 'error';
                upload_message = 'Server import failed (no response).';
                if (onerror) onerror(result);
                return;
            }

            const meta = result.meta ?? result;
            if (meta && meta.success === false) {
                upload_status = 'error';
                upload_message = meta?.details?.message || 'Server import failed';
                if (onerror) onerror(result);
                return;
            }

            const processed = meta?.processed ?? meta?.data_list_count ?? (Array.isArray(result?.data) ? result.data.length : 0);
            processed_badges_count = processed || 0;
            total_badges_in_file = meta?.total ?? processed_badges_count;

            upload_status = 'success';
            upload_message = `Server processed ${processed_badges_count} badges.`;
            if (onsuccess) onsuccess();
        } catch (err: any) {
            upload_status = 'error';
            upload_message = `Upload failed: ${err?.message || 'Unknown error'}`;
            console.error('Upload error:', err);
            if (onerror) onerror(err);
        }

        return;
    }

    // Server-side import for Axonius Zoom CSV
    if (upload_mode === 'axonius_zoom') {
        upload_status = 'loading';
        upload_message = 'Uploading to server...';

        const formData = new FormData();
        formData.append('file', selected_file, selected_file.name);

        const params: any = {};
        if (begin_at !== null && begin_at !== undefined) params.begin_at = String(begin_at);
        if (end_at !== null && end_at !== undefined) params.end_at = String(end_at);
        if (return_detail) params.return_detail = String(true);

        const task_id = (crypto && (crypto as any).randomUUID)
            ? (crypto as any).randomUUID()
            : String(Date.now());

        try {
            upload_status = 'processing';
            upload_message = 'Processing on server… this may take a minute or two.';
            const endpoint = `/event/${event_id}/badge/import/zoom_csv`;
            const result = await api.post_object({
                api_cfg: $ae_api,
                endpoint,
                form_data: formData,
                params,
                return_meta: true,
                task_id,
                timeout: 300000, // 5 min — server-side import can be slow; no retry to avoid duplicate imports
                retry_count: 1,
                log_lvl: 0
            });

            if (!result) {
                upload_status = 'error';
                upload_message = 'Server import failed (no response).';
                if (onerror) onerror(result);
                return;
            }

            const meta = result.meta ?? result;
            if (meta && meta.success === false) {
                upload_status = 'error';
                upload_message = meta?.details?.message || 'Server import failed';
                if (onerror) onerror(result);
                return;
            }

            const processed = meta?.processed ?? meta?.data_list_count ?? (Array.isArray(result?.data) ? result.data.length : 0);
            processed_badges_count = processed || 0;
            total_badges_in_file = meta?.total ?? processed_badges_count;

            upload_status = 'success';
            upload_message = `Server processed ${processed_badges_count} badges.`;
            if (onsuccess) onsuccess();
        } catch (err: any) {
            upload_status = 'error';
            upload_message = `Upload failed: ${err?.message || 'Unknown error'}`;
            console.error('Upload error:', err);
            if (onerror) onerror(err);
        }

        return;
    }

    // Fallback: client-side CSV parsing (existing behavior)
    upload_status = 'loading';
    upload_message = 'Reading file...';

    const reader = new FileReader();
    reader.onload = async (e) => {
        try {
            upload_status = 'processing';
            upload_message = 'Processing file content...';
            processed_badges_count = 0;

            const text = e.target?.result as string;
            const badge_data_li = parse_csv(text);
            total_badges_in_file = badge_data_li.length;

            for (const data_kv of badge_data_li) {
                // Simple mapping, customize as needed
                const badge_payload: key_val = {
                    full_name_override:
                        data_kv.full_name || data_kv.name || null,
                    professional_title_override:
                        data_kv.professional_title || null,
                    affiliations_override:
                        data_kv.affiliations || data_kv.company || null,
                    location_override: data_kv.location || null,
                    email: data_kv.email || null,
                    allow_tracking:
                        data_kv.allow_tracking === 'true' ||
                        data_kv.allow_tracking === '1' ||
                        false,
                    badge_type_code: data_kv.badge_type_code || 'guest' // Default to 'guest' if not provided
                };

                await events_func.create_ae_obj__event_badge({
                    api_cfg: $ae_api,
                    event_id: event_id,
                    data_kv: badge_payload
                });
                processed_badges_count++;
            }

            upload_status = 'success';
            upload_message = `Successfully uploaded ${processed_badges_count} out of ${total_badges_in_file} badges.`;
            if (onsuccess) onsuccess();
        } catch (error: any) {
            upload_status = 'error';
            upload_message = `Error processing file: ${error?.message || 'Unknown error'}`;
            console.error('Error during file upload:', error);
            if (onerror) onerror(error);
        }
    };
    reader.onerror = (e) => {
        upload_status = 'error';
        upload_message = `Error reading file: ${reader.error?.message}`;
        console.error('FileReader error:', reader.error);
        if (onerror) onerror(reader.error);
    };
    reader.readAsText(selected_file);
}

function handle_cancel() {
    // dispatch('cancel');
    if (oncancel) oncancel();
}
</script>

<form onsubmit={handle_upload} class="space-y-4 p-4">
    <h3 class="h3">Upload Badge List (CSV)</h3>
    <!-- <p>
        Upload a CSV file containing badge data. The first row should be
        headers.
    </p> -->
    <!-- <p>
        Supported headers (case-sensitive): <code>full_name</code>,
        <code>name</code>,
        <code>professional_title</code>, <code>affiliations</code>,
        <code>company</code>,
        <code>location</code>, <code>email</code>, <code>allow_tracking</code>
        (true/false or 1/0),
        <code>badge_type_code</code>.
    </p> -->
    <p>
        {#if upload_mode === 'axonius_splash_xlsx'}
            Upload the Cvent Splash XLSX registrant export file here. Only registrants with status "Attending" are imported by default. Server-side processing can take a few seconds to a few minutes.
        {:else}
            Upload the standard Axonius Zoom event tickets CSV export file here. This will trigger server-side processing to import the new and changed badges. This can take a few seconds to a few minutes.
        {/if}
    </p>

    <fieldset class="space-y-2">
        <legend class="label"><span>Upload format</span></legend>
        <div class="flex gap-4 items-center">
            <label class="label flex items-center gap-2">
                <input type="radio" name="upload_mode" value="axonius_zoom" bind:group={upload_mode} />
                <span>Axonius Zoom CSV (event tickets)</span>
            </label>
            <label class="label flex items-center gap-2">
                <input type="radio" name="upload_mode" value="axonius_splash_xlsx" bind:group={upload_mode} />
                <span>Cvent Splash XLSX (registrant export)</span>
            </label>
        </div>

        {#if $ae_loc.administrator_access && (upload_mode === 'axonius_zoom' || upload_mode === 'axonius_splash_xlsx')}
            <div class="grid grid-cols-3 gap-2 items-center">
                <input type="number" min="0" placeholder="begin_at (0)" bind:value={begin_at} class="input" />
                <input type="number" min="0" placeholder="end_at (20000)" bind:value={end_at} class="input" />
                <label class="label flex items-center gap-2">
                    <input type="checkbox" bind:checked={return_detail} class="checkbox" />
                    <span>Return detail</span>
                </label>
            </div>
            {#if upload_mode === 'axonius_splash_xlsx'}
                <div class="flex items-center gap-2">
                    <label class="label" for="import_status_filter">Status filter</label>
                    <input
                        id="import_status_filter"
                        type="text"
                        placeholder="Attending (leave blank for all)"
                        bind:value={import_status_filter}
                        class="input flex-1" />
                </div>
            {/if}
        {/if}
    </fieldset>

    <label class="label">
        <span>Select {upload_mode === 'axonius_splash_xlsx' ? 'XLSX' : 'CSV'} File</span>
        <input
            type="file"
            accept={upload_mode === 'axonius_splash_xlsx' ? '.xlsx' : '.csv'}
            bind:this={file_input}
            onchange={handle_file_change}
            class="input" />
    </label>

    {#if selected_file}
        <p>File: {selected_file.name} ({selected_file.size} bytes)</p>
    {/if}

    {#if upload_status !== 'idle'}
        <div
            class="alert"
            class:preset-tonal-error={upload_status === 'error'}
            class:preset-tonal-surface={upload_status !== 'error'}>
            <p>{upload_message}</p>
            {#if upload_status === 'processing' || upload_status === 'loading'}
                {#if upload_mode === 'client_csv'}
                    <progress
                        class="progress"
                        value={processed_badges_count}
                        max={total_badges_in_file}></progress>
                    <p>Processed: {processed_badges_count} / {total_badges_in_file}</p>
                {:else}
                    <progress class="progress"></progress>
                {/if}
            {/if}
        </div>
    {/if}

    <div class="flex justify-end gap-2">
        <button
            type="button"
            class="btn preset-tonal-surface"
            onclick={handle_cancel}
            disabled={upload_status === 'loading' ||
                upload_status === 'processing'}>Cancel</button>
        <button
            type="submit"
            class="btn preset-filled-primary"
            disabled={!selected_file ||
                upload_status === 'loading' ||
                upload_status === 'processing'}>
            {#if upload_status === 'loading' || upload_status === 'processing'}
                <Loader2 size="1em" class="animate-spin" aria-hidden="true" />
            {/if}
            Upload Badges
        </button>
    </div>
</form>
