<script lang="ts">
/**
 * Badges Config Page
 * Route: /events/[event_id]/(badges)/badges/config
 *
 * Admin UI for managing event.mod_badges_json (BadgesRemoteCfg).
 * Access: administrator_access only (passcode fields present — stricter than pres_mgmt).
 *
 * Save pattern: load → merge draft → PATCH event via V3 API.
 */
import { untrack } from 'svelte';
import { liveQuery } from 'dexie';
import { db_events } from '$lib/ae_events/db_events';
import { ae_loc, ae_api } from '$lib/stores/ae_stores';
import { events_slct } from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events/ae_events_functions';
import { api } from '$lib/ae_api/api';
import type { BadgesRemoteCfg } from '$lib/stores/ae_events_stores__badges_defaults';
import {
    default_authenticated_can_edit,
    default_trusted_can_edit
} from '$lib/stores/ae_events_stores__badges_defaults';
import {
    TriangleAlert,
    ArrowLeft,
    Check,
    ChevronDown,
    ChevronUp,
    FileText,
    Lock,
    Monitor,
    Save,
    Settings
} from '@lucide/svelte';
import { badges_loc } from '$lib/stores/ae_events_stores__badges.svelte';

interface Props {
    data: any;
}
let { data }: Props = $props();

let event_id = $derived($events_slct.event_id ?? '');

let lq__event_obj = $derived(
    liveQuery(async () => {
        if (!event_id) return null;
        return await db_events.event.get(event_id);
    })
);

// ---------------------------------------------------------------------------
// Known editable field keys (used to render checkboxes in permission sections)
// ---------------------------------------------------------------------------
const attendee_field_options: { key: string; label: string }[] = [
    { key: 'pronouns_override', label: 'Pronouns' },
    { key: 'full_name_override', label: 'Full Name' },
    { key: 'professional_title_override', label: 'Professional Title' },
    { key: 'affiliations_override', label: 'Affiliations' },
    { key: 'phone_override', label: 'Phone' },
    { key: 'location_override', label: 'Location' },
    { key: 'allow_tracking', label: 'Allow Tracking (Exhibitor Leads)' },
    { key: 'agree_to_tc', label: 'Agree to Terms & Conditions (placeholder)' }
];

const staff_extra_field_options: { key: string; label: string }[] = [
    { key: 'email_override', label: 'Email' },
    { key: 'badge_type_code_override', label: 'Badge Type Code' },
    { key: 'registration_type_code_override', label: 'Registration Type Code' },
    { key: 'other_1_code', label: 'Option 1' },
    { key: 'other_2_code', label: 'Option 2' },
    { key: 'other_3_code', label: 'Option 3' },
    { key: 'other_4_code', label: 'Option 4' },
    { key: 'other_5_code', label: 'Option 5' },
    { key: 'other_6_code', label: 'Option 6' },
    { key: 'other_7_code', label: 'Option 7' },
    { key: 'other_8_code', label: 'Option 8' },
    { key: 'ticket_1_code', label: 'Ticket 1' },
    { key: 'ticket_2_code', label: 'Ticket 2' },
    { key: 'ticket_3_code', label: 'Ticket 3' },
    { key: 'ticket_4_code', label: 'Ticket 4' },
    { key: 'ticket_5_code', label: 'Ticket 5' },
    { key: 'ticket_6_code', label: 'Ticket 6' },
    { key: 'ticket_7_code', label: 'Ticket 7' },
    { key: 'ticket_8_code', label: 'Ticket 8' },
    { key: 'allow_tracking', label: 'Allow Tracking' },
    { key: 'agree_to_tc', label: 'Agree to Terms (placeholder)' },
    { key: 'hide', label: 'Hide (archive)' },
    { key: 'priority', label: 'Priority' },
    { key: 'notes', label: 'Notes' }
];

// All field options shown in the staff section (attendee fields first, then extras).
// Exclude agree_to_tc and allow_tracking from the attendee slice — both appear in
// staff_extra_field_options, so keeping them here would create duplicate keys.
const all_staff_field_options = [
    ...attendee_field_options.filter((f) => f.key !== 'agree_to_tc' && f.key !== 'allow_tracking'),
    ...staff_extra_field_options
];

// ---------------------------------------------------------------------------
// Draft state — initialized from the live event config
// ---------------------------------------------------------------------------
const cfg_defaults: BadgesRemoteCfg = {
    enable_mass_print: false,
    enable_add_badge_btn: false,
    enable_upload_badge_li_btn: false,
    enable_search_qr: false,
    qr_type: null,
    trusted_passcode: null,
    administrator_passcode: null,
    edit_permissions: {
        authenticated: { can_edit: [...default_authenticated_can_edit] },
        trusted: { can_edit: [...default_trusted_can_edit] },
        administrator: { can_edit: '*' }
    },
    anon_search_result_limit: 15,
    anon_search_min_chars: 3,
    auth_search_result_limit: 25,
    auth_search_min_chars: 2,
    trusted_search_result_limit: 150,
    trusted_search_min_chars: 1
};

let draft: BadgesRemoteCfg = $state({ ...cfg_defaults });
// edit_permissions is a nested object — deep-clone it separately
let draft_auth_fields: string[] = $state([...default_authenticated_can_edit]);
let draft_trusted_fields: string[] = $state([...default_trusted_can_edit]);

let draft_initialized = $state(false);
let initial_json = $state('');

$effect(() => {
    // Initialize once the event object is available — even if mod_badges_json is null/unset,
    // so admins can configure a fresh event rather than getting stuck on "Loading...".
    const event_obj = $lq__event_obj;
    if (event_obj && !draft_initialized) {
        const event_cfg = event_obj.mod_badges_json;
        untrack(() => {
            draft = { ...cfg_defaults, ...(event_cfg ?? {}) };
            // Normalize edit_permissions to ensure sub-objects exist
            draft.edit_permissions = {
                authenticated: event_cfg?.edit_permissions?.authenticated ?? {
                    can_edit: [...default_authenticated_can_edit]
                },
                trusted: event_cfg?.edit_permissions?.trusted ?? {
                    can_edit: [...default_trusted_can_edit]
                },
                administrator: { can_edit: '*' }
            };
            const auth_cfg = draft.edit_permissions.authenticated?.can_edit;
            draft_auth_fields = Array.isArray(auth_cfg)
                ? [...auth_cfg]
                : [...default_authenticated_can_edit];
            const trusted_cfg = draft.edit_permissions.trusted?.can_edit;
            draft_trusted_fields = Array.isArray(trusted_cfg)
                ? [...trusted_cfg]
                : [...default_trusted_can_edit];

            initial_json = JSON.stringify({
                ...draft,
                _auth: draft_auth_fields,
                _trusted: draft_trusted_fields
            });
            draft_initialized = true;
        });
    }
});

let is_dirty = $derived(
    draft_initialized &&
        JSON.stringify({
            ...draft,
            _auth: draft_auth_fields,
            _trusted: draft_trusted_fields
        }) !== initial_json
);

// Toggle a field in the auth checkbox list
function toggle_auth_field(key: string) {
    if (draft_auth_fields.includes(key)) {
        draft_auth_fields = draft_auth_fields.filter((f) => f !== key);
    } else {
        draft_auth_fields = [...draft_auth_fields, key];
    }
}

// Toggle a field in the trusted checkbox list
function toggle_trusted_field(key: string) {
    if (draft_trusted_fields.includes(key)) {
        draft_trusted_fields = draft_trusted_fields.filter((f) => f !== key);
    } else {
        draft_trusted_fields = [...draft_trusted_fields, key];
    }
}

// ---------------------------------------------------------------------------
// Save
// ---------------------------------------------------------------------------
let save_status: 'idle' | 'saving' | 'success' | 'error' = $state('idle');

async function save() {
    if (!event_id) return;
    save_status = 'saving';
    try {
        const payload: BadgesRemoteCfg = {
            ...draft,
            edit_permissions: {
                authenticated: { can_edit: draft_auth_fields },
                trusted: { can_edit: draft_trusted_fields },
                administrator: { can_edit: '*' }
            }
        };
        await api.update_ae_obj({
            api_cfg: $ae_api,
            obj_type: 'event',
            obj_id: event_id,
            fields: { mod_badges_json: payload },
            log_lvl: 1
        });
        await events_func.load_ae_obj_id__event({
            api_cfg: $ae_api,
            event_id: event_id,
            log_lvl: 1
        });
        initial_json = JSON.stringify({
            ...draft,
            _auth: draft_auth_fields,
            _trusted: draft_trusted_fields
        });
        save_status = 'success';
        setTimeout(() => (save_status = 'idle'), 3000);
    } catch (e) {
        console.error('Failed to save badges config', e);
        save_status = 'error';
        setTimeout(() => (save_status = 'idle'), 5000);
    }
}

// Section collapse state
let sections: Record<string, boolean> = $state({
    ui: true,
    search_limits: true,
    qr: true,
    passcodes: true,
    auth_fields: true,
    trusted_fields: true
});
function toggle(key: string) {
    sections[key] = !sections[key];
}
</script>

<svelte:head>
    <title>Badges Config</title>
</svelte:head>

{#if !$ae_loc.administrator_access}
    <div class="p-8 text-center opacity-50">
        <Lock size="3em" class="mx-auto mb-2" />
        <p>Administrator access required.</p>
    </div>
{:else}
    <div class="mx-auto w-full max-w-3xl space-y-4 px-2 py-4">

        <!-- Header -->
        <header class="flex items-center justify-between gap-4">
            <div class="flex items-center gap-2">
                <a href="/events/{event_id}/badges"
                    class="btn btn-sm preset-tonal-surface"
                    title="Back to Badges">
                    <ArrowLeft size="1em" />
                </a>
                <Settings size="1.2em" class="text-primary-500" />
                <h1 class="text-xl font-bold">Badges Config</h1>
            </div>
            <a href="/events/{event_id}/templates"
                class="btn btn-sm preset-tonal-surface border border-surface-300-700"
                title="Manage Badge Templates">
                <FileText size="1em" /> Templates
            </a>
            <div class="flex items-center gap-2">
                {#if save_status === 'success'}
                    <span class="badge preset-tonal-success flex items-center gap-1">
                        <Check size="1em" /> Saved
                    </span>
                {:else if save_status === 'error'}
                    <span class="badge preset-tonal-error flex items-center gap-1">
                        <TriangleAlert size="1em" /> Error
                    </span>
                {/if}
                <button
                    type="button"
                    class="btn preset-filled-primary-500"
                    onclick={save}
                    disabled={!is_dirty || save_status === 'saving'}>
                    <Save size="1em" class="mr-1" />
                    {save_status === 'saving' ? 'Saving...' : 'Save'}
                </button>
            </div>
        </header>

        <p class="text-surface-500 text-sm">
            Changes here update <code>event.mod_badges_json</code> and take effect on the
            next page load. Field permission changes affect which badge fields each access
            level may edit on the Badge Review page.
        </p>

        {#if !draft_initialized}
            <p class="text-surface-400 italic">Loading event config...</p>
        {:else}

        <!-- ================================================================ -->
        <!-- SEARCH & UI -->
        <!-- ================================================================ -->
        <section class="border-surface-200-800 rounded-xl border">
            <button
                type="button"
                class="flex w-full items-center justify-between px-4 py-3 text-left font-semibold"
                onclick={() => toggle('ui')}>
                <span>Search &amp; UI Controls</span>
                {#if sections.ui}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
            </button>
            {#if sections.ui}
                <div class="border-surface-200-800 grid grid-cols-2 gap-3 border-t px-4 py-3">
                    {#each [
                        { field: 'enable_mass_print' as const, label: 'Enable Mass Print' },
                        { field: 'enable_add_badge_btn' as const, label: 'Enable Add Badge Button' },
                        { field: 'enable_upload_badge_li_btn' as const, label: 'Enable Upload Badge List Button' },
                        { field: 'enable_search_qr' as const, label: 'Enable QR Scan Search' }
                    ] as item (item.field)}
                        <label class="flex items-center gap-2">
                            <input
                                type="checkbox"
                                class="checkbox"
                                bind:checked={draft[item.field]} />
                            <span class="text-sm">{item.label}</span>
                        </label>
                    {/each}
                </div>
            {/if}
        </section>

        <!-- ================================================================ -->
        <!-- SEARCH LIMITS -->
        <!-- ================================================================ -->
        <section class="border-surface-200-800 rounded-xl border">
            <button
                type="button"
                class="flex w-full items-center justify-between px-4 py-3 text-left font-semibold"
                onclick={() => toggle('search_limits')}>
                <span>Search Limits per Access Tier</span>
                {#if sections.search_limits}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
            </button>
            {#if sections.search_limits}
                <div class="border-surface-200-800 border-t px-4 py-3 space-y-4">
                    <p class="text-xs text-surface-400">
                        Controls how many results each access tier can see and how many characters
                        they must type before a search fires. Trusted and above use the trusted limits.
                    </p>
                    <div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
                        <!-- Anonymous -->
                        <div class="space-y-2">
                            <p class="text-sm font-semibold">Anonymous <span class="text-xs font-normal text-surface-400">(not signed in)</span></p>
                            <label class="flex flex-col gap-1">
                                <span class="text-xs text-surface-500">Result limit</span>
                                <input
                                    type="number"
                                    class="input input-sm"
                                    min="1"
                                    max="500"
                                    bind:value={draft.anon_search_result_limit} />
                            </label>
                            <label class="flex flex-col gap-1">
                                <span class="text-xs text-surface-500">Min characters to search</span>
                                <input
                                    type="number"
                                    class="input input-sm"
                                    min="1"
                                    max="10"
                                    bind:value={draft.anon_search_min_chars} />
                            </label>
                        </div>
                        <!-- Auth (Public / Authenticated) -->
                        <div class="space-y-2">
                            <p class="text-sm font-semibold">Auth <span class="text-xs font-normal text-surface-400">(public passcode / identity-verified)</span></p>
                            <label class="flex flex-col gap-1">
                                <span class="text-xs text-surface-500">Result limit</span>
                                <input
                                    type="number"
                                    class="input input-sm"
                                    min="1"
                                    max="500"
                                    bind:value={draft.auth_search_result_limit} />
                            </label>
                            <label class="flex flex-col gap-1">
                                <span class="text-xs text-surface-500">Min characters to search</span>
                                <input
                                    type="number"
                                    class="input input-sm"
                                    min="1"
                                    max="10"
                                    bind:value={draft.auth_search_min_chars} />
                            </label>
                        </div>
                        <!-- Trusted+ -->
                        <div class="space-y-2">
                            <p class="text-sm font-semibold">Trusted+ <span class="text-xs font-normal text-surface-400">(onsite staff and above)</span></p>
                            <label class="flex flex-col gap-1">
                                <span class="text-xs text-surface-500">Result limit</span>
                                <input
                                    type="number"
                                    class="input input-sm"
                                    min="1"
                                    max="1000"
                                    bind:value={draft.trusted_search_result_limit} />
                            </label>
                            <label class="flex flex-col gap-1">
                                <span class="text-xs text-surface-500">Min characters to search</span>
                                <input
                                    type="number"
                                    class="input input-sm"
                                    min="1"
                                    max="10"
                                    bind:value={draft.trusted_search_min_chars} />
                            </label>
                        </div>
                    </div>
                </div>
            {/if}
        </section>

        <!-- ================================================================ -->
        <!-- QR CONFIG -->
        <!-- ================================================================ -->
        <section class="border-surface-200-800 rounded-xl border">
            <button
                type="button"
                class="flex w-full items-center justify-between px-4 py-3 text-left font-semibold"
                onclick={() => toggle('qr')}>
                <span>QR Code Config</span>
                {#if sections.qr}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
            </button>
            {#if sections.qr}
                <div class="border-surface-200-800 space-y-3 border-t px-4 py-3">
                    <label class="flex flex-col gap-1">
                        <span class="text-sm font-medium">QR Type</span>
                        <input
                            type="text"
                            class="input input-sm"
                            placeholder="e.g. badge_id, url (leave blank for default)"
                            bind:value={draft.qr_type} />
                        <span class="text-surface-400 text-xs">
                            Controls the QR payload format. Verify against the scan component before changing.
                        </span>
                    </label>
                </div>
            {/if}
        </section>

        <!-- ================================================================ -->
        <!-- PASSCODES -->
        <!-- ================================================================ -->
        <section class="border-surface-200-800 rounded-xl border">
            <button
                type="button"
                class="flex w-full items-center justify-between px-4 py-3 text-left font-semibold"
                onclick={() => toggle('passcodes')}>
                <span class="flex items-center gap-2">
                    <Lock size="1em" class="text-warning-500" />
                    Access Passcodes
                    <span class="text-surface-400 text-xs font-normal">(administrator only)</span>
                </span>
                {#if sections.passcodes}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
            </button>
            {#if sections.passcodes}
                <div class="border-surface-200-800 grid grid-cols-1 gap-3 border-t px-4 py-3 sm:grid-cols-2">
                    <label class="flex flex-col gap-1">
                        <span class="text-sm font-medium">Trusted Staff Passcode</span>
                        <input
                            type="text"
                            class="input input-sm font-mono"
                            placeholder="leave blank to disable"
                            bind:value={draft.trusted_passcode} />
                    </label>
                    <label class="flex flex-col gap-1">
                        <span class="text-sm font-medium">Administrator Passcode</span>
                        <input
                            type="text"
                            class="input input-sm font-mono"
                            placeholder="leave blank to disable"
                            bind:value={draft.administrator_passcode} />
                    </label>
                </div>
            {/if}
        </section>

        <!-- ================================================================ -->
        <!-- ATTENDEE EDITABLE FIELDS -->
        <!-- ================================================================ -->
        <section class="border-surface-200-800 rounded-xl border">
            <button
                type="button"
                class="flex w-full items-center justify-between px-4 py-3 text-left font-semibold"
                onclick={() => toggle('auth_fields')}>
                <span>
                    Attendee Editable Fields
                    <span class="text-surface-400 text-xs font-normal">(passcode-authenticated)</span>
                </span>
                {#if sections.auth_fields}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
            </button>
            {#if sections.auth_fields}
                <div class="border-surface-200-800 grid grid-cols-2 gap-2 border-t px-4 py-3">
                    {#each attendee_field_options as field (field.key)}
                        <label class="flex items-center gap-2 text-sm">
                            <input
                                type="checkbox"
                                class="checkbox"
                                checked={draft_auth_fields.includes(field.key)}
                                onchange={() => toggle_auth_field(field.key)} />
                            <span>{field.label}</span>
                        </label>
                    {/each}
                </div>
            {/if}
        </section>

        <!-- ================================================================ -->
        <!-- STAFF EDITABLE FIELDS -->
        <!-- ================================================================ -->
        <section class="border-surface-200-800 rounded-xl border">
            <button
                type="button"
                class="flex w-full items-center justify-between px-4 py-3 text-left font-semibold"
                onclick={() => toggle('trusted_fields')}>
                <span>
                    Staff Editable Fields
                    <span class="text-surface-400 text-xs font-normal">(trusted access)</span>
                </span>
                {#if sections.trusted_fields}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
            </button>
            {#if sections.trusted_fields}
                <div class="border-surface-200-800 grid grid-cols-2 gap-2 border-t px-4 py-3">
                    {#each all_staff_field_options as field (field.key)}
                        <label class="flex items-center gap-2 text-sm">
                            <input
                                type="checkbox"
                                class="checkbox"
                                checked={draft_trusted_fields.includes(field.key)}
                                onchange={() => toggle_trusted_field(field.key)} />
                            <span>{field.label}</span>
                        </label>
                    {/each}
                    <p class="col-span-2 mt-1 text-xs text-surface-400 italic">
                        Administrators always have access to all fields — not configurable here.
                    </p>
                </div>
            {/if}
        </section>

        <!-- ================================================================ -->
        <!-- LOCAL DEVICE SETTINGS (localStorage only — not saved to event)  -->
        <!-- ================================================================ -->
        <section class="border-surface-200-800 rounded-xl border">
            <div class="flex w-full items-center justify-between px-4 py-3">
                <span class="flex items-center gap-2 font-semibold">
                    <Monitor size="1em" class="text-surface-400" />
                    Local Device Settings
                </span>
                <span class="text-xs text-surface-400 italic">saved to this browser only · not synced</span>
            </div>
            <div class="border-surface-200-800 space-y-3 border-t px-4 py-3">
                <label class="flex items-start gap-3">
                    <input
                        type="checkbox"
                        class="checkbox mt-0.5 shrink-0"
                        bind:checked={badges_loc.current.print_nav_use_goto} />
                    <div>
                        <p class="text-sm font-medium">Use fast navigation after print</p>
                        <p class="text-xs text-surface-400 italic">
                            On by default. Uses SvelteKit client-side navigation to return to Badge Search
                            after printing — faster and avoids a full page reload. Turn off to fall back to
                            a hard page reload if the print loop behaves unexpectedly on this device.
                        </p>
                    </div>
                </label>
            </div>
        </section>

        <!-- Bottom save button -->
        <div class="flex justify-end">
            <button
                type="button"
                class="btn preset-filled-primary-500"
                onclick={save}
                disabled={!is_dirty || save_status === 'saving'}>
                <Save size="1em" class="mr-1" />
                {save_status === 'saving' ? 'Saving...' : 'Save Config'}
            </button>
        </div>

        {/if}
    </div>
{/if}
