<script lang="ts">
/**
 * Badge Review Page
 *
 * Access modes (checked in order):
 * 1. Administrator ($ae_loc.administrator_access) — full edit access, no passcode needed
 * 2. Trusted staff ($ae_loc.trusted_access) — trusted-level fields, no passcode needed
 * 3. Attendee (URL ?passcode=... matches badge.person_passcode) — attendee-level fields
 * 4. Passcode entry form — if none of the above, prompt for passcode
 *
 * Editable fields per level come from event.mod_badges_json.edit_permissions.
 * Defaults apply if not configured in event settings.
 */

interface Props {
    /** @type {import('./$types').PageData} */
    data: any;
    log_lvl?: number;
}

let { data, log_lvl = 0 }: Props = $props();

import { untrack } from 'svelte';
import { liveQuery } from 'dexie';

import { ae_loc } from '$lib/stores/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils';
import { db_events } from '$lib/ae_events/db_events';
import { EVENTS_MODULE_TITLE } from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events/ae_events_functions';
import {
    default_authenticated_can_edit,
    default_trusted_can_edit
} from '$lib/stores/ae_events_stores__badges_defaults';
import { page } from '$app/state';
import {
    ArrowLeft,
    Check,
    Link,
    LoaderCircle,
    Mail,
    Printer
} from '@lucide/svelte';
import Comp_badge_review_form from '../ae_comp__badge_review_form.svelte';
import Element_access_denied from '$lib/elements/element_access_denied.svelte';

let event_badge_id = $derived(page.params.badge_id);
let event_id = $derived(page.params.event_id);

let is_loading_idb = $state(true);

// *** LiveQuery: badge object
let lq__event_badge_obj = $derived(
    liveQuery(async () => {
        if (!event_badge_id) return null;
        return await db_events.badge.get(event_badge_id);
    })
);

$effect(() => {
    if ($lq__event_badge_obj !== undefined) {
        untrack(() => (is_loading_idb = false));
    }
});

// LiveQuery for the event object — needed to read mod_badges_json.edit_permissions.
let lq__event_obj = $derived(
    liveQuery(async () => {
        if (!event_id) return null;
        return await db_events.event.get(event_id);
    })
);

// Mirror server-side badges config into the local persisted store when the
// event object is available. This ensures pages that read badges_loc get the
// authoritative event flags even when the review page is loaded directly.
$effect(() => {
    const remote_cfg = $lq__event_obj?.mod_badges_json;
    if (remote_cfg) {
        untrack(() => {
            events_func.sync_config__event_badges({
                badges_cfg_remote: remote_cfg,
                log_lvl: log_lvl
            });
        });
    }
});

// *** Passcode logic
let url_passcode = $derived(page.url?.searchParams?.get('passcode') ?? '');
let entered_passcode = $state('');
let passcode_checked = $state(false);
let passcode_valid = $state(false);
let passcode_error = $state('');

// Once the badge loads: grant open access if no passcode is set, or auto-validate URL passcode.
$effect(() => {
    const badge = $lq__event_badge_obj;
    if (!badge || passcode_checked) return;
    untrack(() => {
        if (!badge.person_passcode) {
            // No passcode on this badge — open access for attendees
            passcode_valid = true;
            passcode_checked = true;
        } else if (url_passcode) {
            check_passcode(url_passcode);
        }
        // else: badge requires a passcode but none in URL — show the entry form
    });
});

function check_passcode(code: string) {
    passcode_checked = true;
    const badge_passcode = $lq__event_badge_obj?.person_passcode;
    if (!badge_passcode) {
        // No passcode on badge — open access
        passcode_valid = true;
        passcode_error = '';
    } else if (code && code === badge_passcode) {
        passcode_valid = true;
        passcode_error = '';
    } else {
        passcode_valid = false;
        passcode_error =
            'Incorrect passcode. Please check your email link or contact event staff.';
    }
}

// *** Access level shortcuts
let is_administrator = $derived($ae_loc?.administrator_access === true);
let is_trusted = $derived($ae_loc?.trusted_access === true);
let is_edit_mode = $derived($ae_loc?.edit_mode === true);
let has_staff_access = $derived(is_administrator || is_trusted);
let has_attendee_access = $derived(passcode_valid);
let has_any_access = $derived(has_staff_access || has_attendee_access);

// *** Print state derived from badge
let print_count = $derived($lq__event_badge_obj?.print_count ?? 0);
let is_printed = $derived(print_count >= 1);

// *** Copy review link state
let copy_status: 'idle' | 'copied' = $state('idle');

function build_review_url(): string {
    // TODO: append ?passcode=... when person_passcode is added to the event_badge schema
    return `/events/${$lq__event_badge_obj?.event_id}/badges/${$lq__event_badge_obj?.event_badge_id}/review`;
}

async function copy_review_link() {
    const full_url = window.location.origin + build_review_url();
    try {
        await navigator.clipboard.writeText(full_url);
        copy_status = 'copied';
        setTimeout(() => {
            copy_status = 'idle';
        }, 2000);
    } catch {
        console.error('Clipboard write failed');
    }
}


// TODO: replace alert with actual email API call when available
function send_review_email() {
    const badge = $lq__event_badge_obj;
    const name =
        badge?.full_name_override ??
        badge?.full_name ??
        `${badge?.given_name ?? ''} ${badge?.family_name ?? ''}`.trim();
    const email = is_trusted
        ? (badge?.email ?? '(no email on file)')
        : ae_util.obscure_email(badge?.email);
    const event_name = EVENTS_MODULE_TITLE;
    alert(
        `PLACEHOLDER: An email will be sent to ${name} at ${email}. Use that link to review your ${event_name} badge.`
    );
}

// *** Resolve editable field list based on access level.
// Reads from event.mod_badges_json.edit_permissions when available;
// falls back to module-level defaults from ae_events_stores__badges_defaults.
let can_edit_fields: string[] = $derived.by(() => {
    if (is_administrator) return ['*'];
    const edit_permissions = $lq__event_obj?.mod_badges_json?.edit_permissions;
    if (is_trusted) {
        const cfg = edit_permissions?.trusted?.can_edit;
        if (cfg === '*') return ['*'];
        if (Array.isArray(cfg) && cfg.length > 0) return cfg;
        return default_trusted_can_edit;
    }
    if (has_attendee_access) {
        const cfg = edit_permissions?.authenticated?.can_edit;
        if (cfg === '*') return ['*'];
        if (Array.isArray(cfg) && cfg.length > 0) return cfg;
        return default_authenticated_can_edit;
    }
    return [];
});
</script>

<svelte:head>
    <title>
        &AElig;: Review Badge —
        {$lq__event_badge_obj?.full_name_override ??
            $lq__event_badge_obj?.full_name ??
            '—'}
         — {EVENTS_MODULE_TITLE}
    </title>
</svelte:head>

{#if $lq__event_badge_obj}
    <!-- Page header -->
    <header
        class="mb-4 flex w-full flex-row flex-wrap items-center justify-between gap-2 border-b border-gray-300 pb-2">
        <!-- Left: Back to Search (staff only) + title + name -->
        <div class="flex min-w-0 flex-row items-center gap-2">
            {#if has_staff_access}
                <a
                    href={`/events/${$lq__event_badge_obj.event_id}/badges`}
                    class="btn btn-sm preset-tonal-surface flex shrink-0 items-center gap-1"
                    title="Back to badge search">
                    <ArrowLeft size="1em" />
                    <span class="hidden sm:inline">Search</span>
                </a>
            {/if}
            <div class="flex min-w-0 flex-col">
                <h2 class="text-base font-bold">Review Badge</h2>
                <p class="truncate text-sm text-gray-500">
                    {$lq__event_badge_obj.full_name_override ??
                        $lq__event_badge_obj.full_name ??
                        '— no name —'}
                </p>
            </div>
        </div>

        <!-- Right: Action buttons -->
        <div class="flex shrink-0 flex-row items-center gap-1">
            <!-- 1. Print Badge: Trusted+, not printed OR Edit Mode (reprint) -->
            {#if is_trusted && (!is_printed || is_edit_mode)}
                <a
                    href={`/events/${$lq__event_badge_obj.event_id}/badges/${$lq__event_badge_obj.event_badge_id}/print`}
                    class="btn btn-sm preset-tonal-primary flex items-center gap-1"
                    title={is_printed
                        ? `Reprint badge (printed ${print_count}×)`
                        : 'Print badge'}>
                    <Printer size="1em" />
                    {#if is_printed}
                        <span class="text-xs font-bold">{print_count}×</span>
                    {/if}
                    <span class="hidden sm:inline">Print</span>
                </a>
            {/if}

            <!-- 2. Copy review link to clipboard: Trusted + Edit Mode -->
            {#if is_trusted && is_edit_mode}
                <button
                    type="button"
                    class="btn btn-sm flex items-center gap-1"
                    class:preset-tonal-secondary={copy_status !== 'copied'}
                    class:preset-filled-success-500={copy_status === 'copied'}
                    onclick={() => copy_review_link()}
                    title="Copy review link to clipboard">
                    {#if copy_status === 'copied'}
                        <Check size="1em" />
                        <span class="hidden sm:inline">Copied!</span>
                    {:else}
                        <Link size="1em" />
                        <span class="hidden sm:inline">Copy Link</span>
                    {/if}
                </button>
            {/if}

            <!-- 3. Email Review Link: Administrator + Edit Mode only
                 Temporarily restricted — TODO: restore broader access after Axonius 2026 -->
            {#if is_administrator && is_edit_mode}
                <button
                    type="button"
                    class="btn btn-sm preset-tonal-surface flex items-center gap-1"
                    onclick={() => send_review_email()}
                    title="Email a review link to this attendee">
                    <Mail size="1em" />
                    <span class="hidden sm:inline">Email Link</span>
                </button>
            {/if}
        </div>
    </header>

    {#if has_any_access}
        <div class="space-y-4">
            <Comp_badge_review_form
                event_id={event_id as string}
                event_badge_id={event_badge_id as string}
                {lq__event_badge_obj}
                {can_edit_fields}
                is_staff={has_staff_access}
                {log_lvl} />
        </div>
    {:else if !passcode_checked && !url_passcode && !!$lq__event_badge_obj?.person_passcode}
        <!-- Passcode entry (badge requires a passcode, attendee navigated directly without one) -->
        <div class="card max-w-sm space-y-4 p-6">
            <h3 class="text-lg font-semibold">Enter Your Passcode</h3>
            <p class="text-sm text-gray-500">
                Enter the passcode from your badge review email to view and
                update your badge information.
            </p>
            <div class="space-y-2">
                <label for="passcode-entry" class="block text-sm font-medium"
                    >Passcode</label>
                <input
                    id="passcode-entry"
                    type="text"
                    class="input w-full font-mono tracking-widest"
                    bind:value={entered_passcode}
                    placeholder="Enter passcode"
                    onkeydown={(e) => {
                        if (e.key === 'Enter') check_passcode(entered_passcode);
                    }}
                    data-testid="badge-review-passcode-input" />
            </div>
            {#if passcode_error}
                <p class="text-error-500 text-sm">{passcode_error}</p>
            {/if}
            <button
                type="button"
                class="btn preset-filled-primary w-full"
                onclick={() => check_passcode(entered_passcode)}
                data-testid="badge-review-passcode-submit">
                Access My Badge
            </button>
        </div>
    {:else if passcode_checked && !passcode_valid}
        <!-- Invalid passcode -->
        <Element_access_denied
            message={passcode_error}
            action_label="Try Again"
            on_action={() => {
                passcode_checked = false;
                passcode_error = '';
                entered_passcode = '';
            }} />
    {/if}
{:else if is_loading_idb || !event_badge_id}
    <div
        class="flex flex-col items-center justify-center gap-4 p-20 opacity-50">
        <LoaderCircle size="3em" class="animate-spin" />
        <p class="text-center text-xl font-bold">Loading Badge Information…</p>
    </div>
{:else}
    <div class="card space-y-4 p-8 text-center">
        <h2 class="text-error-500 text-2xl font-bold">Badge Not Found</h2>
        <p class="opacity-70">
            No record found for ID: <span class="font-mono"
                >{event_badge_id}</span>
        </p>
        <button
            class="btn preset-filled-primary"
            onclick={() => window.location.reload()}>
            Retry
        </button>
    </div>
{/if}
