<!-- #region TaskLogViewer [C:3] [TYPE Component] [SEMANTICS task, log, viewer, realtime, websocket] -->
<!-- @BRIEF Component component: components/TaskLogViewer.svelte -->
<!-- @LAYER UI -->
<!--
@UX_STATE: Loading -> Default

@SEMANTICS: task, log, viewer, inline, realtime
@PURPOSE: Displays task logs inline (in drawer) or as modal. Merges real-time WebSocket logs with polled historical logs.
@LAYER UI
@RELATION USES -> [EXT:frontend:taskService]
@RELATION USES -> [TaskLogPanel]
@INVARIANT: Real-time logs are always appended without duplicates.
-->
<script lang="ts">
    import { getTaskLogs } from "../services/taskService.js";
    import { t } from '$lib/i18n/index.svelte.js';
    import TaskLogPanel from "./tasks/TaskLogPanel.svelte";
    import Icon from "../lib/ui/Icon.svelte";

    let {
        show = $bindable(false),
        inline = false,
        taskId = null,
        taskStatus = null,
        realTimeLogs = [],
        onclose = () => {},
    } = $props();

    let logs = $state([]);
    let loading = $state(false);
    let error = $state("");
    let autoScroll = $state(true);

    let shouldShow = $derived(inline || show);

    $effect(() => {
        if (realTimeLogs && realTimeLogs.length > 0) {
            const lastLog = realTimeLogs[realTimeLogs.length - 1];
            const exists = logs.some(
                (l) =>
                    l.timestamp === lastLog.timestamp &&
                    l.message === lastLog.message,
            );
            if (!exists) {
                logs = [...logs, lastLog];
            }
        }
    });

    async function fetchLogs() {
        if (!taskId) return;
        try {
            console.log(`[TaskLogViewer][API][fetchLogs:STARTED] id=${taskId}`);
            logs = await getTaskLogs(taskId);
            console.log(`[TaskLogViewer][API][fetchLogs:SUCCESS] id=${taskId}`);
        } catch (e) {
            console.error(
                `[TaskLogViewer][API][fetchLogs:FAILED] id=${taskId}`,
                e,
            );
            error = e.message;
        } finally {
            loading = false;
        }
    }

    function handleRefresh() {
        fetchLogs();
    }

    $effect(() => {
        if (shouldShow && taskId) {
            logs = [];
            loading = true;
            error = "";
            // Load historical logs once on open — real-time logs come via realTimeLogs prop from WebSocket
            fetchLogs();
        }
    });
</script>

{#if shouldShow}
    {#if inline}
        <!-- ═══ INLINE MODE ═══ -->
        <div class="flex flex-col h-full w-full">
            {#if loading && logs.length === 0}
                <div class="flex items-center justify-center gap-3 h-full text-gray-400 text-sm">
                    <div class="w-5 h-5 border-2 border-gray-200 border-t-primary rounded-full animate-spin"></div>
                    <span class="font-medium">{$t.tasks?.loading}</span>
                </div>
            {:else if error}
                <div class="flex flex-col items-center justify-center gap-3 h-full text-gray-500 text-sm p-4 text-center">
                    <div class="w-10 h-10 rounded-full bg-red-50 flex items-center justify-center text-red-500 text-lg">⚠</div>
                    <span class="font-medium text-red-600">{error}</span>
                    <button
                        class="bg-white text-gray-700 border border-gray-200 rounded-md px-4 py-1.5 text-xs font-semibold cursor-pointer transition-all hover:bg-gray-50 hover:border-gray-300"
                        onclick={handleRefresh}>{$t.common?.retry}</button>
                </div>
            {:else}
                <TaskLogPanel {taskId} {logs} {autoScroll} />
            {/if}
        </div>
    {:else}
        <!-- ═══ MODAL MODE ═══ -->
        <div class="fixed inset-0 z-50 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
            <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
                <!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
                <div
                    class="fixed inset-0 bg-slate-900/30 backdrop-blur-[2px] transition-opacity"
                    aria-hidden="true"
                    onclick={() => { show = false; onclose(); }}
                    role="presentation"
                ></div>

                <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>

                <div class="inline-block align-bottom bg-white rounded-xl text-left overflow-hidden shadow-2xl border border-gray-200 transform transition-all sm:my-8 sm:align-middle sm:max-w-4xl sm:w-full">
                    <div class="p-6">
                        <div class="flex justify-between items-center mb-5 pb-4 border-b border-gray-100">
                            <h3 class="text-lg font-bold tracking-tight text-gray-900" id="modal-title">
                                {$t.tasks?.logs_title}
                            </h3>
                            <button
                                class="p-1.5 rounded-md text-gray-400 bg-transparent border-none cursor-pointer transition-all hover:text-gray-900 hover:bg-gray-100"
                                onclick={() => { show = false; onclose(); }}
                                aria-label={$t.common?.close}
                            >
                                <Icon name="close" size={20} strokeWidth={2.5} />
                            </button>
                        </div>
                        <div class="h-[550px] overflow-hidden">
                            {#if loading && logs.length === 0}
                                <div class="flex flex-col items-center justify-center h-full space-y-4 text-gray-400">
                                    <div class="w-10 h-10 border-4 border-gray-200 border-t-primary rounded-full animate-spin"></div>
                                    <p class="text-sm font-semibold tracking-wide uppercase">{$t.tasks?.loading}</p>
                                </div>
                            {:else if error}
                                <div class="flex flex-col items-center justify-center h-full p-8 text-center space-y-4">
                                    <div class="w-14 h-14 rounded-full bg-red-50 flex items-center justify-center text-red-500 shadow-inner">
                                        <span class="text-3xl">⚠</span>
                                    </div>
                                    <p class="text-red-600 font-semibold text-lg">{error}</p>
                                    <button
                                        class="mt-2 rounded-lg border border-gray-200 bg-white px-5 py-2.5 text-sm font-bold text-gray-700 hover:bg-gray-50 hover:border-gray-300 transition-all shadow-sm"
                                        onclick={handleRefresh}>
                                        {$t.common?.retry}
                                    </button>
                                </div>
                            {:else}
                                <TaskLogPanel {taskId} {logs} {autoScroll} />
                            {/if}
                        </div>
                    </div>
                </div>
            </div>
        </div>
    {/if}
{/if}
<!-- #endregion TaskLogViewer -->
