<script lang="ts">
import { untrack } from 'svelte';
import { ChevronDown, ChevronUp, 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 } from '$lib/stores/ae_stores';
import type { BadgeTemplateCfg } from '$lib/ae_events/ae_events__badge_template_cfg';

interface Props {
    event_id: string;
    template_id?: string | null; // Null for creation, string for editing
    onsuccess?: (result: any) => void;
    onerror?: (error: any) => void;
    oncancel?: () => void;
}

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

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

// Form fields (Runes)
let name = $state('');
let background_image_path = $state('');
let header_path = $state('');
let logo_path = $state('');
let header_row_1 = $state('');
let header_row_2 = $state('');
let secondary_header_path = $state('');
let footer_text = $state('');
// show_qr_front / show_qr_back: removed — UI now binds directly to cfg_show_qr_front/cfg_show_qr_back
let wireless_ssid = $state('');
let wireless_password = $state('');
let ticket_1_text = $state('');
let ticket_2_text = $state('');
let ticket_3_text = $state('');

// Advanced / cfg_json states
let advanced_open = $state(false);
let existing_cfg_raw = $state('');
let cfg_hide_badge_header = $state(false);
let cfg_hide_badge_footer = $state(false);
let cfg_show_qr_front = $state(false);
let cfg_show_qr_back = $state(true);
// Per-field hide toggles
let cfg_hide_title = $state(false);
let cfg_hide_affiliations = $state(false);
let cfg_hide_location = $state(true);
// Controls menu config (per-template) — which fields the controls panel shows
// and which fields authenticated users may edit. Stored under cfg_json.controls_cfg
// Defaults match DEFAULT_SHOWN in ae_comp__badge_print_controls.svelte (pronouns/leads off by default).
let cfg_controls_shown: string[] = $state(['name', 'title', 'affiliations', 'location']);
let cfg_controls_auth_editable: string[] = $state([]);
// Body text color (hex)
let cfg_body_text_color = $state('#000000');
// Background image bleed (CSS length, e.g. "0.125in", "3mm"). Empty = no bleed.
let cfg_bleed = $state('');
// Header image vertical offset (CSS length). Empty = default 2rem. Negative = shift up.
let cfg_header_margin_top = $state('');
// Header div padding per side (CSS length). Empty = default 0.5rem (Tailwind p-2).
let cfg_header_padding_top    = $state('');
let cfg_header_padding_right  = $state('');
let cfg_header_padding_bottom = $state('');
let cfg_header_padding_left   = $state('');
// Punch-out hole markers (left/right/center badge clip slots).
let cfg_punch_holes_left = $state(false);
let cfg_punch_holes_right = $state(false);
let cfg_punch_holes_center = $state(false);
// Per-slot colors and rainbow. Empty color = use component default.
let cfg_punch_holes_left_fg      = $state('');
let cfg_punch_holes_left_bg      = $state('');
let cfg_punch_holes_left_rainbow = $state(false);
let cfg_punch_holes_right_fg      = $state('');
let cfg_punch_holes_right_bg      = $state('');
let cfg_punch_holes_right_rainbow = $state(false);
let cfg_punch_holes_center_fg      = $state('');
let cfg_punch_holes_center_bg      = $state('');
let cfg_punch_holes_center_rainbow = $state(false);
// Horizontal inset per side (mm). null = use component default (2mm).
let cfg_punch_holes_inset_x_mm: number | null = $state(null);
// Applies to all rainbow slots: slow breathing pulse instead of fast cycle
let cfg_punch_holes_slow_pulse = $state(false);
// Header bottom border. Empty color = no border.
let cfg_header_border_color = $state('');
let cfg_header_border_width = $state('');
// Alignment overrides: 'left' | 'center' | 'right' | 'justify'
let cfg_align_name = $state('center');
let cfg_align_title = $state('center');
let cfg_align_affiliations = $state('center');
let cfg_align_location = $state('center');
let cfg_qr_alignment_front = $state('center');
let cfg_qr_alignment_back = $state('center');

let submit_status = $state('idle'); // idle, loading, success, error

// Section collapse state — General open by default (required name field); rest closed.
let sections_open = $state({
    general: true,
    branding: false,
    footer: false,
    qr: false,
    tickets: false
});

// Load template data if in edit mode
$effect(() => {
    if (template_id) {
        untrack(() => {
            load_template(template_id);
        });
    }
});

async function load_template(id: string) {
    submit_status = 'loading';
    try {
        const template_obj =
            await events_func.load_ae_obj_id__event_badge_template({
                api_cfg: $ae_api,
                event_badge_template_id: id
            });
        if (template_obj) {
            name = template_obj.name || '';
            background_image_path = template_obj.background_image_path || '';
            header_path = template_obj.header_path || '';
            logo_path = template_obj.logo_path || '';
            header_row_1 = template_obj.header_row_1 || '';
            header_row_2 = template_obj.header_row_2 || '';
            secondary_header_path = template_obj.secondary_header_path || '';
            footer_text = template_obj.footer_text || '';
            wireless_ssid = template_obj.wireless_ssid || '';
            wireless_password = template_obj.wireless_password || '';
            ticket_1_text = template_obj.ticket_1_text || '';
            ticket_2_text = template_obj.ticket_2_text || '';
            ticket_3_text = template_obj.ticket_3_text || '';

            // Preserve existing cfg_json and expose cfg flags in the form
            existing_cfg_raw = template_obj.cfg_json || '';
            let parsed_cfg: any = {};
            try {
                parsed_cfg = existing_cfg_raw
                    ? typeof existing_cfg_raw === 'string'
                        ? JSON.parse(existing_cfg_raw)
                        : existing_cfg_raw
                    : {};
            } catch {
                parsed_cfg = {};
            }

            cfg_hide_badge_header = parsed_cfg.hide_badge_header ?? false;
            cfg_hide_badge_footer = parsed_cfg.hide_badge_footer ?? false;
            cfg_show_qr_front = parsed_cfg.hasOwnProperty('show_qr_front')
                ? parsed_cfg.show_qr_front
                : (template_obj.show_qr_front ?? false);
            cfg_show_qr_back = parsed_cfg.hasOwnProperty('show_qr_back')
                ? parsed_cfg.show_qr_back
                : (template_obj.show_qr_back ?? true);

            // Per-field hide toggles
            cfg_hide_title = parsed_cfg.hasOwnProperty('hide_title') ? !!parsed_cfg.hide_title : false;
            cfg_hide_affiliations = parsed_cfg.hasOwnProperty('hide_affiliations') ? !!parsed_cfg.hide_affiliations : false;
            cfg_hide_location = parsed_cfg.hasOwnProperty('hide_location') ? !!parsed_cfg.hide_location : false;

            // Controls menu cfg (preferred location: cfg_json.controls_cfg)
            const parsed_controls = parsed_cfg?.controls_cfg ?? parsed_cfg?.controlsCfg ?? parsed_cfg?.controls ?? null;
            cfg_controls_shown = Array.isArray(parsed_controls?.shown) ? [...parsed_controls.shown] : [];
            cfg_controls_auth_editable = Array.isArray(parsed_controls?.auth_editable)
                ? [...parsed_controls.auth_editable]
                : [];

            // Body text color (hex-only). Prefer explicit hex keys.
            const _hex_candidate = parsed_cfg.body_text_color_hex ?? parsed_cfg.body_text_color ?? parsed_cfg.text_color ?? '';
            if (typeof _hex_candidate === 'string' && /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(_hex_candidate.trim())) {
                cfg_body_text_color = _hex_candidate.trim();
            } else {
                cfg_body_text_color = '#000000';
            }

            // Background bleed (CSS length, e.g. "0.125in"). Empty = no bleed.
            cfg_bleed = parsed_cfg.bleed ?? '';
            cfg_header_margin_top = parsed_cfg.header_margin_top ?? '';
            cfg_punch_holes_left   = parsed_cfg?.punch_holes?.left   ?? false;
            cfg_punch_holes_right  = parsed_cfg?.punch_holes?.right  ?? false;
            cfg_punch_holes_center = parsed_cfg?.punch_holes?.center ?? false;
            cfg_punch_holes_left_fg      = parsed_cfg?.punch_holes?.left_fg      ?? '';
            cfg_punch_holes_left_bg      = parsed_cfg?.punch_holes?.left_bg      ?? '';
            cfg_punch_holes_left_rainbow = parsed_cfg?.punch_holes?.left_rainbow ?? false;
            cfg_punch_holes_right_fg      = parsed_cfg?.punch_holes?.right_fg      ?? '';
            cfg_punch_holes_right_bg      = parsed_cfg?.punch_holes?.right_bg      ?? '';
            cfg_punch_holes_right_rainbow = parsed_cfg?.punch_holes?.right_rainbow ?? false;
            cfg_punch_holes_center_fg      = parsed_cfg?.punch_holes?.center_fg      ?? '';
            cfg_punch_holes_center_bg      = parsed_cfg?.punch_holes?.center_bg      ?? '';
            cfg_punch_holes_center_rainbow = parsed_cfg?.punch_holes?.center_rainbow ?? false;
            cfg_punch_holes_slow_pulse     = parsed_cfg?.punch_holes?.slow_pulse     ?? false;
            cfg_punch_holes_inset_x_mm     = parsed_cfg?.punch_holes?.inset_x_mm    ?? null;
            cfg_header_border_color = parsed_cfg.header_border_color ?? '';
            cfg_header_border_width = parsed_cfg.header_border_width ?? '';
            cfg_header_padding_top    = parsed_cfg.header_padding_top    ?? '';
            cfg_header_padding_right  = parsed_cfg.header_padding_right  ?? '';
            cfg_header_padding_bottom = parsed_cfg.header_padding_bottom ?? '';
            cfg_header_padding_left   = parsed_cfg.header_padding_left   ?? '';

            // Alignment overrides (nested under cfg_json.align and cfg_json.qr_alignment)
            cfg_align_name = parsed_cfg?.align?.name ?? parsed_cfg.align_name ?? 'center';
            cfg_align_title = parsed_cfg?.align?.title ?? parsed_cfg.align_title ?? 'center';
            cfg_align_affiliations = parsed_cfg?.align?.affiliations ?? parsed_cfg.align_affiliations ?? 'center';
            cfg_align_location = parsed_cfg?.align?.location ?? parsed_cfg.align_location ?? 'center';
            cfg_qr_alignment_front = parsed_cfg?.qr_alignment?.front ?? parsed_cfg.qr_alignment_front ?? 'center';
            cfg_qr_alignment_back = parsed_cfg?.qr_alignment?.back ?? parsed_cfg.qr_alignment_back ?? 'center';

            submit_status = 'idle';
        } else {
            submit_status = 'error';
            console.error('Template not found for editing.');
        }
    } catch (error) {
        submit_status = 'error';
        console.error('Error loading template for editing:', error);
    }
}

async function handle_submit() {
    submit_status = 'loading';

    // Merge cfg_json preserving unknown keys, then set our cfg flags
    let cfg_obj: BadgeTemplateCfg = {};
    try {
        cfg_obj = existing_cfg_raw
            ? typeof existing_cfg_raw === 'string'
                ? JSON.parse(existing_cfg_raw)
                : existing_cfg_raw
            : {};
    } catch {
        cfg_obj = {};
    }

    cfg_obj.hide_badge_header = cfg_hide_badge_header;
    cfg_obj.hide_badge_footer = cfg_hide_badge_footer;
    cfg_obj.show_qr_front = cfg_show_qr_front;
    cfg_obj.show_qr_back = cfg_show_qr_back;

    // Per-field hide toggles
    cfg_obj.hide_title = cfg_hide_title;
    cfg_obj.hide_affiliations = cfg_hide_affiliations;
    cfg_obj.hide_location = cfg_hide_location;

    // Save alignment overrides under nested objects to keep cfg_json organized
    cfg_obj.align = cfg_obj.align || {};
    cfg_obj.align.name = cfg_align_name;
    cfg_obj.align.title = cfg_align_title;
    cfg_obj.align.affiliations = cfg_align_affiliations;
    cfg_obj.align.location = cfg_align_location;

    cfg_obj.qr_alignment = cfg_obj.qr_alignment || {};
    cfg_obj.qr_alignment.front = cfg_qr_alignment_front;
    cfg_obj.qr_alignment.back = cfg_qr_alignment_back;

    // Controls menu config: which fields the controls panel shows and which
    // fields authenticated users may edit. Stored under cfg_json.controls_cfg
    cfg_obj.controls_cfg = cfg_obj.controls_cfg || {};
    if (cfg_controls_shown && cfg_controls_shown.length > 0) cfg_obj.controls_cfg.shown = [...cfg_controls_shown];
    if (cfg_controls_auth_editable && cfg_controls_auth_editable.length > 0) cfg_obj.controls_cfg.auth_editable = [...cfg_controls_auth_editable];

    // Body text color (hex-only)
    if (typeof cfg_body_text_color === 'string' && /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(cfg_body_text_color.trim())) {
        cfg_obj.body_text_color = cfg_body_text_color.trim();
    } else {
        // Remove any stale color keys to avoid keeping invalid values
        if ((cfg_obj as any)?.body_text_color) delete (cfg_obj as any).body_text_color;
        if ((cfg_obj as any)?.body_text_color_hex) delete (cfg_obj as any).body_text_color_hex;
    }

    // Background bleed: save if set, remove key entirely when cleared
    if (cfg_bleed.trim()) {
        cfg_obj.bleed = cfg_bleed.trim();
    } else {
        delete cfg_obj.bleed;
    }

    // Punch-out hole markers: save the nested object only when at least one is enabled
    if (cfg_punch_holes_left || cfg_punch_holes_right || cfg_punch_holes_center) {
        const ph: NonNullable<BadgeTemplateCfg['punch_holes']> = {
            left:   cfg_punch_holes_left,
            right:  cfg_punch_holes_right,
            center: cfg_punch_holes_center
        };
        if (cfg_punch_holes_left_fg.trim())    ph.left_fg       = cfg_punch_holes_left_fg.trim();
        if (cfg_punch_holes_left_bg.trim())    ph.left_bg       = cfg_punch_holes_left_bg.trim();
        if (cfg_punch_holes_left_rainbow)      ph.left_rainbow  = true;
        if (cfg_punch_holes_right_fg.trim())   ph.right_fg      = cfg_punch_holes_right_fg.trim();
        if (cfg_punch_holes_right_bg.trim())   ph.right_bg      = cfg_punch_holes_right_bg.trim();
        if (cfg_punch_holes_right_rainbow)     ph.right_rainbow = true;
        if (cfg_punch_holes_center_fg.trim())  ph.center_fg       = cfg_punch_holes_center_fg.trim();
        if (cfg_punch_holes_center_bg.trim())  ph.center_bg       = cfg_punch_holes_center_bg.trim();
        if (cfg_punch_holes_center_rainbow)    ph.center_rainbow  = true;
        if (cfg_punch_holes_slow_pulse)        ph.slow_pulse      = true;
        if (cfg_punch_holes_inset_x_mm !== null && !isNaN(cfg_punch_holes_inset_x_mm)) ph.inset_x_mm = cfg_punch_holes_inset_x_mm;
        cfg_obj.punch_holes = ph;
    } else {
        delete cfg_obj.punch_holes;
    }

    // Header image vertical offset: save if set, remove key when cleared (falls back to 2rem default)
    if (cfg_header_margin_top.trim()) {
        cfg_obj.header_margin_top = cfg_header_margin_top.trim();
    } else {
        delete cfg_obj.header_margin_top;
    }

    // Header bottom border: save color + width if color is set, remove both if cleared
    if (cfg_header_border_color.trim()) {
        cfg_obj.header_border_color = cfg_header_border_color.trim();
        if (cfg_header_border_width.trim()) {
            cfg_obj.header_border_width = cfg_header_border_width.trim();
        } else {
            delete cfg_obj.header_border_width;
        }
    } else {
        delete cfg_obj.header_border_color;
        delete cfg_obj.header_border_width;
    }

    // Header padding — per side; each saved independently, removed when cleared
    if (cfg_header_padding_top.trim())    { cfg_obj.header_padding_top    = cfg_header_padding_top.trim();    } else { delete cfg_obj.header_padding_top; }
    if (cfg_header_padding_right.trim())  { cfg_obj.header_padding_right  = cfg_header_padding_right.trim();  } else { delete cfg_obj.header_padding_right; }
    if (cfg_header_padding_bottom.trim()) { cfg_obj.header_padding_bottom = cfg_header_padding_bottom.trim(); } else { delete cfg_obj.header_padding_bottom; }
    if (cfg_header_padding_left.trim())   { cfg_obj.header_padding_left   = cfg_header_padding_left.trim();   } else { delete cfg_obj.header_padding_left; }

    const data_to_save: key_val = {
        name,
        background_image_path,
        header_path,
        logo_path,
        header_row_1,
        header_row_2,
        secondary_header_path,
        footer_text,
        // keep top-level show_qr fields in sync for backward compatibility
        show_qr_front: cfg_show_qr_front,
        show_qr_back: cfg_show_qr_back,
        wireless_ssid,
        wireless_password,
        ticket_1_text,
        ticket_2_text,
        ticket_3_text,
        cfg_json: JSON.stringify(cfg_obj)
    };

    try {
        let result;
        if (template_id) {
            result = await events_func.update_ae_obj__event_badge_template({
                api_cfg: $ae_api,
                event_id: event_id,
                event_badge_template_id: template_id,
                data_kv: data_to_save
            });
        } else {
            result = await events_func.create_ae_obj__event_badge_template({
                api_cfg: $ae_api,
                event_id: event_id,
                data_kv: data_to_save
            });
        }

        if (result) {
            submit_status = 'success';
            if (onsuccess) onsuccess(result);
        } else {
            submit_status = 'error';
            if (onerror) onerror('Failed to save template');
        }
    } catch (error) {
        submit_status = 'error';
        console.error('Error saving template:', error);
        if (onerror) onerror(error);
    }
}

function handle_cancel() {
    if (oncancel) oncancel();
}

// Toggle helpers for controls_cfg arrays
function toggle_cfg_controls_shown(key: string) {
    if (cfg_controls_shown.includes(key)) cfg_controls_shown = cfg_controls_shown.filter((k) => k !== key);
    else cfg_controls_shown = [...cfg_controls_shown, key];
}

function toggle_cfg_controls_auth_editable(key: string) {
    if (cfg_controls_auth_editable.includes(key)) cfg_controls_auth_editable = cfg_controls_auth_editable.filter((k) => k !== key);
    else cfg_controls_auth_editable = [...cfg_controls_auth_editable, key];
}
</script>

<form onsubmit={prevent_default(handle_submit)} class="space-y-4 p-4">
    <h3 class="h3">{template_id ? 'Edit' : 'Create New'} Badge Template</h3>

    <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={() => (sections_open.general = !sections_open.general)}>
            <span>General</span>
            {#if sections_open.general}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
        </button>
        {#if sections_open.general}
            <div class="border-surface-200-800 space-y-3 border-t px-4 py-3">
                <label class="label">
                    <span>Template Name</span>
                    <input type="text" bind:value={name} class="input" required />
                </label>
                <label class="label">
                    <span>Background Image Path (URL) — full-badge background, replaces header</span>
                    <input type="text" bind:value={background_image_path} class="input" />
                </label>
                {#if background_image_path}
                    <p class="text-xs text-amber-600 dark:text-amber-400">
                        ⚠ When a background image is set, the header path and logo/text header are hidden on the badge front — the background image covers the full badge.
                    </p>
                {/if}
            </div>
        {/if}
    </section>

    <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={() => (sections_open.branding = !sections_open.branding)}>
            <span>Header &amp; Branding</span>
            {#if sections_open.branding}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
        </button>
        {#if sections_open.branding}
            <div class="border-surface-200-800 space-y-3 border-t px-4 py-3">
                <label class="label">
                    <span>Header Path (URL) — top banner image (used when no background image)</span>
                    <input type="text" bind:value={header_path} class="input" />
                </label>
                <div class="space-y-2">
                    <p class="text-sm font-medium">Punch-Out Hole Markers</p>
                    <p class="text-xs text-surface-400 italic">
                        Show X overlays at the physical badge clip slot positions (5/8″ × 1/8″ slots, 1/4″ from top).
                        Markers help attendees know where to push out the perforations.
                        Leave colors blank to use defaults (gray stroke, semi-transparent white fill).
                    </p>
                    {#snippet hole_colors(label: string, enabled: boolean, fg: string, bg: string, rainbow: boolean, on_fg: (v: string) => void, on_bg: (v: string) => void, on_rainbow: (v: boolean) => void)}
                        <div class="space-y-1 rounded border border-surface-200-800 p-2">
                            <label class="label flex items-center gap-2 font-medium">
                                <input type="checkbox" checked={enabled} onchange={(e) => { if (e.target instanceof HTMLInputElement) { if (label === 'Left') cfg_punch_holes_left = e.target.checked; else if (label === 'Right') cfg_punch_holes_right = e.target.checked; else cfg_punch_holes_center = e.target.checked; } }} class="checkbox" />
                                <span>{label} slot</span>
                            </label>
                            {#if enabled}
                                <div class="pl-6 space-y-2">
                                    <label class="label flex items-center gap-2">
                                        <input type="checkbox" checked={rainbow} onchange={(e) => { if (e.target instanceof HTMLInputElement) on_rainbow(e.target.checked); }} class="checkbox" />
                                        <span class="text-sm">🌈 Rainbow</span>
                                    </label>
                                    {#if !rainbow}
                                        <div class="grid grid-cols-2 gap-2">
                                            <label class="label">
                                                <span class="text-xs">Stroke / line (fg)</span>
                                                <div class="flex items-center gap-1">
                                                    <input type="color" value={fg || '#777777'} oninput={(e) => { if (e.target instanceof HTMLInputElement) on_fg(e.target.value); }} class="w-8 h-7 p-0" />
                                                    <input type="text" value={fg} oninput={(e) => { if (e.target instanceof HTMLInputElement) on_fg(e.target.value); }} class="input input-sm w-24" placeholder="#777777" />
                                                </div>
                                            </label>
                                            <label class="label">
                                                <span class="text-xs">Fill (bg)</span>
                                                <div class="flex items-center gap-1">
                                                    <input type="color" value={bg || '#ffffff'} oninput={(e) => { if (e.target instanceof HTMLInputElement) on_bg(e.target.value); }} class="w-8 h-7 p-0" />
                                                    <input type="text" value={bg} oninput={(e) => { if (e.target instanceof HTMLInputElement) on_bg(e.target.value); }} class="input input-sm w-24" placeholder="#ffffff" />
                                                </div>
                                            </label>
                                        </div>
                                    {/if}
                                </div>
                            {/if}
                        </div>
                    {/snippet}
                    {@render hole_colors('Left',   cfg_punch_holes_left,   cfg_punch_holes_left_fg,   cfg_punch_holes_left_bg,   cfg_punch_holes_left_rainbow,   (v) => cfg_punch_holes_left_fg = v,   (v) => cfg_punch_holes_left_bg = v,   (v) => cfg_punch_holes_left_rainbow = v)}
                    {@render hole_colors('Right',  cfg_punch_holes_right,  cfg_punch_holes_right_fg,  cfg_punch_holes_right_bg,  cfg_punch_holes_right_rainbow,  (v) => cfg_punch_holes_right_fg = v,  (v) => cfg_punch_holes_right_bg = v,  (v) => cfg_punch_holes_right_rainbow = v)}
                    {@render hole_colors('Center', cfg_punch_holes_center, cfg_punch_holes_center_fg, cfg_punch_holes_center_bg, cfg_punch_holes_center_rainbow, (v) => cfg_punch_holes_center_fg = v, (v) => cfg_punch_holes_center_bg = v, (v) => cfg_punch_holes_center_rainbow = v)}

                    {#if cfg_punch_holes_left_rainbow || cfg_punch_holes_right_rainbow || cfg_punch_holes_center_rainbow}
                        <label class="label flex items-center gap-2 pt-1 border-t border-surface-200-800">
                            <input type="checkbox" bind:checked={cfg_punch_holes_slow_pulse} class="checkbox" />
                            <span class="text-sm">Slow Pulse <span class="text-xs text-surface-400 italic">(gentle breathing instead of fast cycle)</span></span>
                        </label>
                    {/if}

                    {#if cfg_punch_holes_left || cfg_punch_holes_right || cfg_punch_holes_center}
                        <div class="pt-1 border-t border-surface-200-800">
                            <label class="label">
                                <span class="text-sm">Hole Marker Inset (mm per side)</span>
                                <div class="flex items-center gap-2">
                                    <input
                                        type="number"
                                        min="0"
                                        max="8"
                                        step="0.5"
                                        placeholder="2"
                                        value={cfg_punch_holes_inset_x_mm ?? ''}
                                        oninput={(e) => {
                                            const v = parseFloat((e.target as HTMLInputElement).value);
                                            cfg_punch_holes_inset_x_mm = isNaN(v) ? null : v;
                                        }}
                                        class="input w-24" />
                                    {#if cfg_punch_holes_inset_x_mm !== null}
                                        <button
                                            type="button"
                                            onclick={() => (cfg_punch_holes_inset_x_mm = null)}
                                            class="btn btn-sm preset-tonal-surface">
                                            Reset to default
                                        </button>
                                    {/if}
                                </div>
                                <p class="text-xs text-surface-400 italic">
                                    Shrinks the printed marker width by this many mm on each horizontal side,
                                    keeping it inside the physical hole slot. Default is 2mm. Increase if markers
                                    bleed outside the hole on your printer or badge stock.
                                </p>
                            </label>
                        </div>
                    {/if}
                </div>

                <label class="label">
                    <span>Header Image Vertical Offset</span>
                    <input type="text" bind:value={cfg_header_margin_top} class="input" placeholder="e.g. 0.5in, -4px, 1rem (default: 2rem)" />
                    <p class="text-xs text-surface-400 italic">
                        Shifts the header image up (negative) or down (positive) within the badge front.
                        Any CSS length works. Leave blank to use the default (2rem).
                    </p>
                </label>

                <div class="space-y-2">
                    <p class="text-sm font-medium">Header Bottom Border</p>
                    <label class="label">
                        <span>Border Color (hex) — leave blank to disable border</span>
                        <div class="flex items-center gap-2">
                            <input type="color" bind:value={cfg_header_border_color} class="w-10 h-8 p-0"
                                oninput={(e) => { if ((e.target as HTMLInputElement).value === '#000000' && !cfg_header_border_color) cfg_header_border_color = ''; }} />
                            <input type="text" bind:value={cfg_header_border_color} class="input w-36" placeholder="e.g. #FE6111 or empty" />
                        </div>
                    </label>
                    <label class="label">
                        <span>Border Thickness</span>
                        <input type="text" bind:value={cfg_header_border_width} class="input" placeholder="e.g. 2px, 0.5mm (default: 2px)" />
                    </label>
                </div>

                <div class="space-y-1">
                    <p class="text-sm font-medium">Header Padding</p>
                    <p class="text-xs text-surface-400 italic">Per-side padding of the header image container. Any CSS length. Leave blank for default (0.5rem). Bottom padding creates space between the image and the border line.</p>
                    <div class="grid grid-cols-2 gap-2">
                        <label class="label">
                            <span>Top</span>
                            <input type="text" bind:value={cfg_header_padding_top} class="input" placeholder="0.5rem" />
                        </label>
                        <label class="label">
                            <span>Right</span>
                            <input type="text" bind:value={cfg_header_padding_right} class="input" placeholder="0.5rem" />
                        </label>
                        <label class="label">
                            <span>Bottom</span>
                            <input type="text" bind:value={cfg_header_padding_bottom} class="input" placeholder="0.5rem" />
                        </label>
                        <label class="label">
                            <span>Left</span>
                            <input type="text" bind:value={cfg_header_padding_left} class="input" placeholder="0.5rem" />
                        </label>
                    </div>
                </div>

                <label class="label">
                    <span>Logo Path (URL, if no Header Path)</span>
                    <input type="text" bind:value={logo_path} class="input" />
                </label>
                <label class="label">
                    <span>Header Row 1 Text (HTML allowed)</span>
                    <textarea bind:value={header_row_1} class="textarea" rows="2"></textarea>
                </label>
                <label class="label">
                    <span>Header Row 2 Text (HTML allowed)</span>
                    <textarea bind:value={header_row_2} class="textarea" rows="2"></textarea>
                </label>
                <label class="label">
                    <span>Secondary Header Path (URL, back of badge)</span>
                    <input type="text" bind:value={secondary_header_path} class="input" />
                </label>
            </div>
        {/if}
    </section>

    <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={() => (sections_open.footer = !sections_open.footer)}>
            <span>Footer</span>
            {#if sections_open.footer}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
        </button>
        {#if sections_open.footer}
            <div class="border-surface-200-800 space-y-3 border-t px-4 py-3">
                <label class="label">
                    <span>Footer Text (HTML allowed)</span>
                    <textarea bind:value={footer_text} class="textarea" rows="2"></textarea>
                </label>
            </div>
        {/if}
    </section>

    <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={() => (sections_open.qr = !sections_open.qr)}>
            <span>QR &amp; Wireless</span>
            {#if sections_open.qr}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
        </button>
        {#if sections_open.qr}
            <div class="border-surface-200-800 space-y-3 border-t px-4 py-3">
                <label class="label flex items-center gap-2">
                    <input type="checkbox" bind:checked={cfg_show_qr_front} class="checkbox" />
                    <span>Show QR Code on Front</span>
                </label>
                <label class="label flex items-center gap-2">
                    <input type="checkbox" bind:checked={cfg_show_qr_back} class="checkbox" />
                    <span>Show QR Code on Back</span>
                </label>
                <label class="label">
                    <span>Wireless SSID</span>
                    <input type="text" bind:value={wireless_ssid} class="input" />
                </label>
                <label class="label">
                    <span>Wireless Password</span>
                    <input type="text" bind:value={wireless_password} class="input" />
                </label>
            </div>
        {/if}
    </section>

    <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={() => (sections_open.tickets = !sections_open.tickets)}>
            <span>Tickets</span>
            {#if sections_open.tickets}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
        </button>
        {#if sections_open.tickets}
            <div class="border-surface-200-800 space-y-3 border-t px-4 py-3">
                <label class="label">
                    <span>Ticket 1 Text (HTML allowed)</span>
                    <textarea bind:value={ticket_1_text} class="textarea" rows="2"></textarea>
                </label>
                <label class="label">
                    <span>Ticket 2 Text (HTML allowed)</span>
                    <textarea bind:value={ticket_2_text} class="textarea" rows="2"></textarea>
                </label>
                <label class="label">
                    <span>Ticket 3 Text (HTML allowed)</span>
                    <textarea bind:value={ticket_3_text} class="textarea" rows="2"></textarea>
                </label>
            </div>
        {/if}
    </section>

    <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={() => (advanced_open = !advanced_open)}>
            <span>Advanced (cfg_json)</span>
            {#if advanced_open}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
        </button>
        {#if advanced_open}
            <div class="border-surface-200-800 space-y-4 border-t px-4 py-3">

                <!-- Visibility -->
                <div>
                    <p class="text-xs font-semibold text-surface-500 uppercase tracking-wide mb-1">Visibility</p>
                    <div class="grid grid-cols-2 gap-2">
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" bind:checked={cfg_hide_badge_header} class="checkbox" />
                            <span>Hide badge header</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" bind:checked={cfg_hide_badge_footer} class="checkbox" />
                            <span>Hide badge footer</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" bind:checked={cfg_hide_title} class="checkbox" />
                            <span>Hide Title</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" bind:checked={cfg_hide_affiliations} class="checkbox" />
                            <span>Hide Affiliations</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" bind:checked={cfg_hide_location} class="checkbox" />
                            <span>Hide Location</span>
                        </label>
                    </div>
                </div>

                <!-- Alignment -->
                <div>
                    <p class="text-xs font-semibold text-surface-500 uppercase tracking-wide mb-1">Alignment</p>
                    <div class="grid grid-cols-2 gap-2">
                        <label class="label">
                            <span>Name</span>
                            <select bind:value={cfg_align_name} class="input">
                                <option value="left">Left</option>
                                <option value="center">Center</option>
                                <option value="right">Right</option>
                                <option value="justify">Justify</option>
                            </select>
                        </label>
                        <label class="label">
                            <span>Title</span>
                            <select bind:value={cfg_align_title} class="input">
                                <option value="left">Left</option>
                                <option value="center">Center</option>
                                <option value="right">Right</option>
                                <option value="justify">Justify</option>
                            </select>
                        </label>
                        <label class="label">
                            <span>Affiliations</span>
                            <select bind:value={cfg_align_affiliations} class="input">
                                <option value="left">Left</option>
                                <option value="center">Center</option>
                                <option value="right">Right</option>
                                <option value="justify">Justify</option>
                            </select>
                        </label>
                        <label class="label">
                            <span>Location</span>
                            <select bind:value={cfg_align_location} class="input">
                                <option value="left">Left</option>
                                <option value="center">Center</option>
                                <option value="right">Right</option>
                                <option value="justify">Justify</option>
                            </select>
                        </label>
                        <label class="label">
                            <span>QR (Front)</span>
                            <select bind:value={cfg_qr_alignment_front} class="input">
                                <option value="left">Left</option>
                                <option value="center">Center</option>
                                <option value="right">Right</option>
                                <option value="justify">Justify</option>
                            </select>
                        </label>
                        <label class="label">
                            <span>QR (Back)</span>
                            <select bind:value={cfg_qr_alignment_back} class="input">
                                <option value="left">Left</option>
                                <option value="center">Center</option>
                                <option value="right">Right</option>
                                <option value="justify">Justify</option>
                            </select>
                        </label>
                    </div>
                </div>

                <!-- Appearance -->
                <div>
                    <p class="text-xs font-semibold text-surface-500 uppercase tracking-wide mb-1">Appearance</p>
                    <label class="label">
                        <span>Body Text Color (hex)</span>
                        <div class="flex items-center gap-2">
                            <input type="color" bind:value={cfg_body_text_color} class="w-10 h-8 p-0" />
                            <input type="text" bind:value={cfg_body_text_color} class="input w-32" placeholder="#rrggbb" />
                        </div>
                        <p class="text-xs text-surface-400 italic">
                            Pick a hex color (e.g. #112233). The renderer will use this inline color.
                        </p>
                    </label>
                    <label class="label mt-3">
                        <span>Background Image Bleed</span>
                        <input type="text" bind:value={cfg_bleed} class="input" placeholder="e.g. 0.125in or 3mm" />
                        <p class="text-xs text-surface-400 italic">
                            Extends the background image past the card edge on all four sides — prevents a white border
                            if the printer clips slightly inside the physical card boundary. Any CSS length works
                            (<code>0.125in</code>, <code>3mm</code>, <code>9px</code>). Leave blank for no bleed.
                        </p>
                    </label>
                </div>
                <div class="border-t pt-2">
                    <h4 class="font-semibold">Controls Menu Toggles</h4>
                    <p class="text-xs text-surface-400 italic">Controls which fields appear in the print controls panel and which fields authenticated users may edit.</p>
                    <div class="grid grid-cols-2 gap-2 mt-2">
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_shown.includes('name')} onchange={() => toggle_cfg_controls_shown('name')} />
                            <span>Show Full Name</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_shown.includes('title')} onchange={() => toggle_cfg_controls_shown('title')} />
                            <span>Show Title</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_shown.includes('affiliations')} onchange={() => toggle_cfg_controls_shown('affiliations')} />
                            <span>Show Affiliations</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_shown.includes('location')} onchange={() => toggle_cfg_controls_shown('location')} />
                            <span>Show Location</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_shown.includes('pronouns')} onchange={() => toggle_cfg_controls_shown('pronouns')} />
                            <span>Show Pronouns</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_shown.includes('allow_tracking')} onchange={() => toggle_cfg_controls_shown('allow_tracking')} />
                            <span>Show Lead Scanning</span>
                        </label>
                    </div>

                    <p class="text-xs text-surface-400 italic mt-2">Authenticated users may edit:</p>
                    <div class="grid grid-cols-2 gap-2 mt-2">
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_auth_editable.includes('title')} onchange={() => toggle_cfg_controls_auth_editable('title')} />
                            <span>Title</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_auth_editable.includes('affiliations')} onchange={() => toggle_cfg_controls_auth_editable('affiliations')} />
                            <span>Affiliations</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_auth_editable.includes('location')} onchange={() => toggle_cfg_controls_auth_editable('location')} />
                            <span>Location</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_auth_editable.includes('allow_tracking')} onchange={() => toggle_cfg_controls_auth_editable('allow_tracking')} />
                            <span>Lead Scanning</span>
                        </label>
                        <label class="label flex items-center gap-2">
                            <input type="checkbox" class="checkbox" checked={cfg_controls_auth_editable.includes('pronouns')} onchange={() => toggle_cfg_controls_auth_editable('pronouns')} />
                            <span>Pronouns</span>
                        </label>
                    </div>

                    <p class="text-xs text-surface-400 italic">
                        These values are saved into <code>cfg_json</code>. Existing cfg_json keys are preserved.
                    </p>
                </div>
            </div>
        {/if}
    </section>

    <div class="flex justify-end gap-2">
        <button
            type="button"
            class="btn preset-tonal-surface"
            onclick={handle_cancel}
            disabled={submit_status === 'loading'}>Cancel</button>
        <button
            type="submit"
            class="btn preset-filled-primary-500"
            disabled={submit_status === 'loading'}>
            {#if submit_status === 'loading'}
                <Loader2 size="1em" class="animate-spin" aria-hidden="true" />
            {/if}
            {template_id ? 'Save Changes' : 'Create Template'}
        </button>
    </div>
</form>

{#if submit_status === 'success'}
    <p class="text-green-500">Template saved successfully!</p>
{:else if submit_status === 'error'}
    <p class="text-red-500">Error saving template. Please try again.</p>
{/if}
