<script lang="ts">
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
import { events_func } from '$lib/ae_events/ae_events_functions';
import { launcher_loc } from '$lib/stores/ae_events_stores__launcher.svelte';
import * as native from '$lib/electron/electron_relay';
import Launcher_Cfg_Section from './launcher_cfg_section.svelte';
import { FlaskConical, Image, RotateCcw, Save, Zap } from '@lucide/svelte';

interface Props {
    on_expand?: () => void;
}

let { on_expand }: Props = $props();

type NativeDeviceLike = {
    event_device_id?: string;
    id?: string;
    other_json?: string | Record<string, unknown> | null;
    [key: string]: unknown;
};

const PRIMARY_PRESETS = [
    { label: 'OSIT Default', value: 'https://static.oneskyit.com/images/site_background.webp' },
] as const;

const EXTERNAL_PRESETS = [
    { label: 'CMSC', value: 'https://static.oneskyit.com/c/CMSC/images/CMSC_AE_Launcher_bg_secondary.png' },
    { label: 'LCI', value: 'https://static.oneskyit.com/c/LCI/images/LCI_AE_Launcher_bg_secondary.png' },
    { label: 'LCI Alt', value: 'https://static.oneskyit.com/c/LCI/images/LCI_AE_Launcher_bg_secondary_bak.jpg' },
    { label: 'BGH', value: 'https://static.oneskyit.com/c/BGH/images/BGH_AE_Launcher_bg_secondary.png' },
] as const;

let url_input = $state('');
let url_external_input = $state('');
let status = $state('');
let last_device_id: string | null = null;

let linux_test_popup_open = $state(false);
let linux_test_popup_data = $state<Record<string, unknown> | null>(null);

function get_native_device(): NativeDeviceLike | null {
    const store_loc = $ae_loc as { native_device?: NativeDeviceLike };
    return store_loc.native_device ?? null;
}

function get_device_id(): string | null {
    const native_device = get_native_device();
    return native_device?.event_device_id ?? native_device?.id ?? null;
}

function parse_other_json(raw_json: unknown): Record<string, unknown> {
    if (!raw_json) return {};
    if (typeof raw_json === 'object') return { ...(raw_json as Record<string, unknown>) };
    if (typeof raw_json !== 'string') return {};
    try {
        const parsed = JSON.parse(raw_json);
        return parsed && typeof parsed === 'object' ? { ...parsed } : {};
    } catch {
        return {};
    }
}

function get_configured_wallpaper(): { url?: string; url_external?: string } {
    const native_device = get_native_device();
    const other_json = parse_other_json(native_device?.other_json);
    const launcher_cfg = (other_json.launcher as Record<string, unknown> | undefined) ?? {};
    return (launcher_cfg.wallpaper as { url?: string; url_external?: string } | undefined) ?? {};
}

function sync_from_device() {
    const device_id = get_device_id();
    if (device_id === last_device_id) return;
    last_device_id = device_id;
    const configured = get_configured_wallpaper();
    url_input = configured.url ?? '';
    url_external_input = configured.url_external ?? '';
}

sync_from_device();

$effect(() => {
    sync_from_device();
});

function set_status(msg: string, duration = 4000) {
    status = msg;
    if (msg) setTimeout(() => { if (status === msg) status = ''; }, duration);
}

async function handle_save(): Promise<boolean> {
    const device_id = get_device_id();
    if (!device_id) return false;

    const native_device = get_native_device();
    const other_json_obj = parse_other_json(native_device?.other_json);
    const launcher_cfg: Record<string, unknown> = {
        ...((other_json_obj.launcher as Record<string, unknown> | undefined) ?? {})
    };

    const wallpaper: Record<string, string> = {};
    if (url_input.trim()) wallpaper.url = url_input.trim();
    if (url_external_input.trim()) wallpaper.url_external = url_external_input.trim();

    if (Object.keys(wallpaper).length > 0) {
        launcher_cfg.wallpaper = wallpaper;
    } else {
        delete launcher_cfg.wallpaper;
    }

    if (Object.keys(launcher_cfg).length > 0) {
        other_json_obj.launcher = launcher_cfg;
    } else {
        delete other_json_obj.launcher;
    }

    const other_json = JSON.stringify(other_json_obj);

    const result = await events_func.update_ae_obj__event_device({
        api_cfg: $ae_api,
        event_device_id: device_id,
        data_kv: { other_json },
        log_lvl: 0
    });

    if (!result) return false;

    const store_loc = $ae_loc as { native_device?: NativeDeviceLike };
    store_loc.native_device = { ...get_native_device(), ...result, other_json };
    return true;
}

async function handle_apply(): Promise<{ success: boolean; linux_test?: boolean }> {
    const url = url_input.trim();
    const url_ext = url_external_input.trim();
    if (!url && !url_ext) return { success: false };

    // If only external is set, target only that display so the built-in stays unchanged.
    const display = !url && url_ext ? 'external' : 'all';

    const result = await native.set_wallpaper({
        url: url || undefined,
        url_external: url_ext || undefined,
        display,
        api_key: $ae_api.api_secret_key,
        account_id: String($ae_api.account_id ?? '')
    });

    if (result?.success && (result as { linux_test_mode?: boolean }).linux_test_mode) {
        linux_test_popup_data = result as Record<string, unknown>;
        linux_test_popup_open = true;
        return { success: true, linux_test: true };
    } else if (result?.success) {
        launcher_loc.current.wallpaper_applied_url = url || null;
        launcher_loc.current.wallpaper_applied_url_external = url_ext || null;
        return { success: true };
    }
    return { success: false };
}

async function handle_save_and_apply() {
    const device_id = get_device_id();
    if (!device_id) { set_status('No device loaded'); return; }

    set_status('Saving...');
    const saved = await handle_save();
    if (!saved) { set_status('Save failed'); return; }

    set_status('Applying...');
    const { success, linux_test } = await handle_apply();
    if (!success) {
        set_status('Saved — apply failed');
    } else if (linux_test) {
        set_status('Linux dev mode — see popup');
    } else {
        set_status('Saved & Applied ✓');
    }
}

async function handle_restore_default() {
    set_status('Restoring...');
    const result = await native.restore_macos_default_wallpaper('all');
    if (result?.success) {
        // Clear tracked applied URL so the next config URL re-applies correctly.
        launcher_loc.current.wallpaper_applied_url = null;
        launcher_loc.current.wallpaper_applied_url_external = null;
        set_status('Restored ✓');
    } else {
        set_status(`Restore failed: ${(result as { error?: string })?.error ?? 'Unknown'}`);
    }
}

const configured_url = $derived(get_configured_wallpaper().url ?? '');
const is_applied = $derived(
    !!url_input.trim() &&
    launcher_loc.current.wallpaper_applied_url === url_input.trim()
);
const section_description = $derived(
    configured_url
        ? is_applied
            ? 'Configured • Applied ✓'
            : 'Configured • Pending'
        : 'Not configured'
);
</script>

<Launcher_Cfg_Section
    title="Wallpaper"
    icon={Image}
    bind:state={launcher_loc.current.section_state__wallpaper}
    {on_expand}
    description={section_description}>

    {#if $ae_loc.edit_mode && !$ae_loc.is_native}
        <div
            class="bg-warning-500/10 border-warning-500/30 mb-2 flex items-center gap-2 rounded-lg border px-2 py-1.5">
            <FlaskConical size="0.75em" class="text-warning-500" />
            <span class="text-warning-500 text-[9px] font-bold tracking-wide uppercase">
                Dev Preview — Apply requires Electron; Save works from any device
            </span>
        </div>
    {/if}

    {#if !get_device_id()}
        <div
            class="bg-warning-500/10 border-warning-500/20 mb-2 rounded-lg border px-2 py-1.5 text-[9px] opacity-80">
            No device record loaded — Save requires a native device config.
        </div>
    {/if}

    <div class="flex flex-col gap-3">

        <!-- Primary display -->
        <div class="flex flex-col gap-1.5">
            <p class="text-[10px] font-bold uppercase opacity-50">Primary Display</p>
            <div class="flex flex-wrap gap-1.5">
                {#each PRIMARY_PRESETS as preset (preset.value)}
                    <button
                        type="button"
                        onclick={() => (url_input = preset.value)}
                        title={preset.value}
                        class="btn btn-sm h-8 px-3 text-xs border-2 {url_input === preset.value ? 'preset-filled-primary border-primary-500' : 'preset-tonal-surface border-surface-400'}">
                        {preset.label}
                    </button>
                {/each}
            </div>
            <input
                type="url"
                bind:value={url_input}
                placeholder="https://… or select a preset above"
                class="input input-sm preset-tonal-surface h-8 w-full text-[10px]" />
            {#if is_applied}
                <p class="text-success-500 pl-0.5 text-[10px]">Applied ✓</p>
            {/if}
        </div>

        <!-- External / projector display -->
        <div class="flex flex-col gap-1.5">
            <p class="text-[10px] font-bold uppercase opacity-50">
                External / Projector
                <span class="font-normal normal-case opacity-75">(optional)</span>
            </p>
            <div class="flex flex-wrap gap-1.5">
                {#each EXTERNAL_PRESETS as preset (preset.value)}
                    <button
                        type="button"
                        onclick={() => (url_external_input = preset.value)}
                        title={preset.value}
                        class="btn btn-sm h-8 px-3 text-xs border-2 {url_external_input === preset.value ? 'preset-filled-primary border-primary-500' : 'preset-tonal-surface border-surface-400'}">
                        {preset.label}
                    </button>
                {/each}
            </div>
            <input
                type="url"
                bind:value={url_external_input}
                placeholder="Blank = use primary on all displays"
                class="input input-sm preset-tonal-surface h-8 w-full text-[10px]" />
        </div>

        <!-- Actions: single Save & Apply + icon-only Restore -->
        <div class="flex gap-2">
            <button
                type="button"
                onclick={handle_save_and_apply}
                disabled={!get_device_id() || (!url_input.trim() && !url_external_input.trim())}
                class="btn preset-filled-primary border-2 border-primary-600 h-10 flex-1 text-sm font-bold disabled:opacity-60">
                <Save size={16} class="mr-1" />
                <Zap size={16} class="mr-0.5" />
                Save & Apply
            </button>
            {#if $ae_loc.is_native || $ae_loc.edit_mode}
                <button
                    type="button"
                    onclick={handle_restore_default}
                    title="Restore macOS default wallpaper"
                    class="btn preset-tonal-surface border-2 border-surface-400 h-10 w-10 opacity-75 hover:opacity-100">
                    <RotateCcw size={18} />
                </button>
            {/if}
        </div>

        {#if status}
            <div
                class="text-center text-[10px] italic"
                class:text-success-500={status.includes('✓')}
                class:text-primary-500={status.includes('Saving') || status.includes('Applying') || status.includes('dev')}
                class:text-error-500={status.includes('failed') || status.includes('No device') || status.includes('Restore failed')}>
                {status}
            </div>
        {/if}

    </div>
</Launcher_Cfg_Section>

<!-- Linux Dev Mode Popup — mirrors Native Test Mode style -->
<!-- Shows what WOULD have been applied; actual gsettings call is skipped to avoid
     resetting the dev workstation monitors on every test cycle. -->
{#if linux_test_popup_open && linux_test_popup_data}
    <div
        class="fixed inset-0 z-9999 flex items-center justify-center bg-black/70 p-4"
        role="presentation"
        onclick={() => (linux_test_popup_open = false)}
        onkeydown={(e) => e.key === 'Escape' && (linux_test_popup_open = false)}>
        <div
            class="bg-surface-50/95 dark:bg-surface-900/95 border-warning-500/40 relative flex max-h-[90vh] w-full max-w-lg flex-col gap-0 overflow-hidden rounded-xl border shadow-2xl"
            role="dialog"
            aria-modal="true"
            aria-label="Linux Dev Mode — Wallpaper not applied"
            tabindex="-1"
            onclick={(e) => e.stopPropagation()}
            onkeydown={(e) => e.stopPropagation()}>

            <div class="bg-warning-500/10 border-warning-500/30 flex items-center gap-2 border-b px-4 py-3">
                <span class="text-warning-600 dark:text-warning-400 font-mono text-xs font-bold uppercase tracking-wider">
                    🧪 Linux Dev Mode — Wallpaper not applied
                </span>
                <button
                    type="button"
                    onclick={() => (linux_test_popup_open = false)}
                    class="btn btn-xs preset-tonal-surface ml-auto">
                    Close
                </button>
            </div>

            <div class="flex flex-col gap-3 overflow-y-auto p-4 font-mono text-xs">
                <div class="flex flex-col gap-1">
                    <span class="text-[9px] font-bold uppercase opacity-50">Display Target</span>
                    <div class="bg-surface-500/10 rounded px-3 py-2">
                        {linux_test_popup_data.display ?? 'all'}
                    </div>
                </div>

                {#if linux_test_popup_data.url}
                    <div class="flex flex-col gap-1">
                        <span class="text-[9px] font-bold uppercase opacity-50">Primary URL</span>
                        <div class="text-primary-500 bg-surface-500/10 rounded px-3 py-2 break-all">
                            {linux_test_popup_data.url}
                        </div>
                    </div>
                {/if}

                {#if linux_test_popup_data.url_external}
                    <div class="flex flex-col gap-1">
                        <span class="text-[9px] font-bold uppercase opacity-50">External / Projector URL</span>
                        <div class="text-primary-500 bg-surface-500/10 rounded px-3 py-2 break-all">
                            {linux_test_popup_data.url_external}
                        </div>
                    </div>
                {/if}

                <div class="flex flex-col gap-1">
                    <span class="text-[9px] font-bold uppercase opacity-50">Would Have Run</span>
                    <div class="bg-surface-500/10 text-success-600 dark:text-success-400 rounded px-3 py-2 leading-relaxed whitespace-pre-wrap">
                        {#each (linux_test_popup_data.would_run as string[]) as cmd, i (i)}
                            <div class="mb-1">{cmd}</div>
                        {/each}
                    </div>
                </div>

                <p class="text-[9px] italic opacity-40">
                    gsettings is skipped on Linux to avoid resetting dev monitors. On macOS this applies via osascript.
                </p>
            </div>
        </div>
    </div>
{/if}
