<!-- [DEF:TaskDrawer:Component] -->
<script>
  /**
   * @TIER: CRITICAL
   * @PURPOSE: Global task drawer for monitoring background operations
   * @LAYER: UI
   * @RELATION: BINDS_TO -> taskDrawerStore, assistantChatStore, WebSocket
   * @SEMANTICS: TaskLogViewer
   * @INVARIANT: Drawer shows logs for active task or remains closed
   *
   * @UX_STATE: Closed -> Drawer hidden, no active task
   * @UX_STATE: Open/ListMode -> Drawer visible, showing recent tasks list
   * @UX_STATE: Open/TaskDetail -> Drawer visible, showing logs for selected task
   * @UX_STATE: InputRequired -> Interactive form rendered in drawer
   * @UX_FEEDBACK: Close button allows task to continue running
   * @UX_FEEDBACK: Back button returns to task list
   * @UX_RECOVERY: Click outside or X button closes drawer
   * @UX_RECOVERY: Back button shows task list when viewing task details
   * @TEST_DATA: llm_task_success_with_fail_result -> {"activeTaskDetails":{"plugin_id":"llm_dashboard_validation","status":"SUCCESS","result":{"status":"FAIL"}}}
   * @TEST_DATA: llm_task_success_with_pass_result -> {"activeTaskDetails":{"plugin_id":"llm_dashboard_validation","status":"SUCCESS","result":{"status":"PASS"}}}
   *
   * @TEST_CONTRACT Component_TaskDrawer ->
   * {
   *   required_props: {},
   *   optional_props: {},
   *   invariants: [
   *       "Binds successfully to taskDrawerStore",
   *       "Renders list mode when no activeTaskId is set",
   *       "Renders detail mode and websocket stream when activeTaskId is set",
   *       "Closes properly on handleClose"
   *   ]
   * }
   * @TEST_FIXTURE init_state -> {}
   * @TEST_EDGE empty_task_list -> displays \"No recent tasks\"
   * @TEST_INVARIANT default_rendering -> verifies: [init_state]
   */

  import { onDestroy } from "svelte";
  import { fromStore } from "svelte/store";
  import { taskDrawerStore, closeDrawer } from "$lib/stores/taskDrawer.js";
  import { assistantChatStore } from "$lib/stores/assistantChat.js";
  import TaskLogViewer from "../../../components/TaskLogViewer.svelte";
  import PasswordPrompt from "../../../components/PasswordPrompt.svelte";
  import { t } from "$lib/i18n";
  import { api } from "$lib/api.js";
  import Icon from "$lib/ui/Icon.svelte";
  import { addToast } from "$lib/toasts.js";
  import { gitService } from "../../../services/gitService.js";

  let ws = null;
  let realTimeLogs = $state([]);
  let taskStatus = $state(null);
  let recentTasks = $state([]);
  let loadingTasks = $state(false);
  let activeTaskDetails = $state(null);
  let environmentOptions = [];
  let taskDetailsPollInterval = null;
  let diffText = $state("");
  let showDiff = $state(false);
  let isDiffLoading = $state(false);

  const taskDrawerState = fromStore(taskDrawerStore);
  const assistantChatState = fromStore(assistantChatStore);

  let isOpen = $derived(Boolean(taskDrawerState.current?.isOpen));
  let activeTaskId = $derived(taskDrawerState.current?.activeTaskId || null);
  let isAssistantOpen = $derived(Boolean(assistantChatState.current?.isOpen));
  let assistantOffset = $derived(
    isAssistantOpen ? "min(100vw, 28rem)" : "0px",
  );

  // Derive short task ID for display
  let shortTaskId = $derived(
    activeTaskId
      ? typeof activeTaskId === "string"
        ? activeTaskId.substring(0, 8)
        : (activeTaskId?.id || activeTaskId?.task_id || "")
            .toString()
            .substring(0, 8)
      : "",
  );

  // Close drawer
  function handleClose() {
    console.log("[TaskDrawer][ui][Close_drawer]");
    closeDrawer();
  }

  function goToReportsPage() {
    closeDrawer();
    window.location.href = "/reports";
  }

  function handleGlobalKeydown(event) {
    if (!isOpen) return;
    if (event.key === "Escape") {
      handleClose();
    }
  }

  function normalizeTaskId(rawTaskId) {
    if (!rawTaskId) return "";
    if (typeof rawTaskId === "string") {
      const match = rawTaskId.match(
        /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/i,
      );
      return match ? match[0] : rawTaskId;
    }
    return rawTaskId?.id || rawTaskId?.task_id || "";
  }

  function isTaskFinished(status) {
    return (
      status === "SUCCESS" ||
      status === "FAILED" ||
      status === "ERROR" ||
      status === "PARTIAL_SUCCESS"
    );
  }

  function resolveLlmValidationStatus(task) {
    if (task?.plugin_id !== "llm_dashboard_validation") return null;
    const raw = String(task?.result?.status || "").toUpperCase();
    if (raw === "FAIL") return { label: "FAIL", tone: "fail", icon: "!" };
    if (raw === "WARN") return { label: "WARN", tone: "warn", icon: "!" };
    if (raw === "PASS") return { label: "PASS", tone: "pass", icon: "OK" };
    return { label: "UNKNOWN", tone: "unknown", icon: "?" };
  }

  function llmValidationBadgeClass(tone) {
    if (tone === "fail")
      return "text-rose-700 bg-rose-100 border border-rose-200";
    if (tone === "warn")
      return "text-amber-700 bg-amber-100 border border-amber-200";
    if (tone === "pass")
      return "text-emerald-700 bg-emerald-100 border border-emerald-200";
    return "text-slate-700 bg-slate-100 border border-slate-200";
  }

  function stopTaskDetailsPolling() {
    if (taskDetailsPollInterval) {
      clearInterval(taskDetailsPollInterval);
      taskDetailsPollInterval = null;
    }
  }

  async function loadEnvironmentOptions() {
    try {
      const response = await api.getEnvironments();
      environmentOptions = Array.isArray(response) ? response : [];
    } catch (err) {
      console.warn("[TaskDrawer][loadEnvironmentOptions][FAILED]", err);
      environmentOptions = [];
    }
  }

  function resolveEnvironmentName(envId, fallbackName = null) {
    if (fallbackName) return fallbackName;
    const env = environmentOptions.find((item) => item.id === envId);
    return env?.name || envId || $t.common?.not_available || "N/A";
  }

  function resolveEnvironmentId(rawEnvIdOrName) {
    if (!rawEnvIdOrName) return null;
    const byId = environmentOptions.find((item) => item.id === rawEnvIdOrName);
    if (byId) return byId.id;
    const byName = environmentOptions.find(
      (item) => item.name === rawEnvIdOrName,
    );
    return byName?.id || rawEnvIdOrName;
  }

  function normalizeSupersetBaseUrl(rawUrl) {
    const baseUrl = String(rawUrl || "").trim().replace(/\/+$/, "");
    if (!baseUrl) return null;
    if (baseUrl.endsWith("/api/v1")) {
      return baseUrl.slice(0, -"/api/v1".length);
    }
    return baseUrl;
  }

  function resolveSupersetDashboardUrl(envId, dashboardId) {
    if (!envId || !dashboardId) return null;
    const env = environmentOptions.find((item) => item.id === envId);
    const baseUrl = normalizeSupersetBaseUrl(env?.url);
    if (!baseUrl) return null;
    return `${baseUrl}/superset/dashboard/${encodeURIComponent(String(dashboardId))}/`;
  }

  async function loadActiveTaskDetails() {
    const taskId = normalizeTaskId(activeTaskId);
    if (!taskId) return;
    try {
      const task = await api.getTask(taskId);
      activeTaskDetails = task;
      taskStatus = task?.status || taskStatus;
      if (isTaskFinished(task?.status)) {
        stopTaskDetailsPolling();
      }
    } catch (err) {
      console.error("[TaskDrawer][loadActiveTaskDetails][FAILED]", err);
    }
  }

  function extractPrimaryDashboardId(task) {
    const result = task?.result || {};
    const params = task?.params || {};
    if (
      Array.isArray(result?.migrated_dashboards) &&
      result.migrated_dashboards[0]?.id
    ) {
      return result.migrated_dashboards[0].id;
    }
    if (Array.isArray(result?.dashboards) && result.dashboards[0]?.id) {
      return result.dashboards[0].id;
    }
    if (Array.isArray(params?.dashboard_ids) && params.dashboard_ids[0]) {
      return params.dashboard_ids[0];
    }
    if (params?.dashboard_id) return params.dashboard_id;
    return null;
  }

  function buildTaskSummary(task) {
    if (!task || !isTaskFinished(task?.status)) return null;
    const result = task?.result || {};
    const params = task?.params || {};
    const summary = {
      headline: result?.summary || null,
      lines: [],
      warnings: [],
      primaryDashboardId: extractPrimaryDashboardId(task),
      targetEnvId: null,
      targetEnvName: null,
    };

    if (task.plugin_id === "superset-migration") {
      const migrated = Array.isArray(result?.migrated_dashboards)
        ? result.migrated_dashboards.length
        : 0;
      const failed = Array.isArray(result?.failed_dashboards)
        ? result.failed_dashboards.length
        : 0;
      const selected = result?.selected_dashboards ?? migrated + failed;
      const mappings = result?.mapping_count ?? 0;
      summary.lines.push(
        `${$t.tasks?.selected || "Selected"}: ${selected}, ${$t.tasks?.successful || "Successful"}: ${migrated}, ${$t.tasks?.with_errors || "With errors"}: ${failed}, ${$t.tasks?.mappings || "Mappings"}: ${mappings}`,
      );
      summary.targetEnvId = resolveEnvironmentId(params?.target_env_id || null);
      summary.targetEnvName = resolveEnvironmentName(
        summary.targetEnvId,
        result?.target_environment || null,
      );
      if (failed > 0) {
        summary.warnings = (result.failed_dashboards || [])
          .slice(0, 3)
          .map(
            (item) =>
              `${item?.title || item?.id}: ${item?.error || $t.common?.unknown || "Unknown error"}`,
          );
      }
      return summary;
    }

    if (task.plugin_id === "superset-backup") {
      const total = result?.total_dashboards ?? 0;
      const ok = result?.backed_up_dashboards ?? 0;
      const failed = result?.failed_dashboards ?? 0;
      summary.lines.push(
        `${$t.tasks?.total || "Total"}: ${total}, ${$t.tasks?.successful || "Successful"}: ${ok}, ${$t.tasks?.failed || "Failed"}: ${failed}`,
      );
      summary.targetEnvId = resolveEnvironmentId(
        params?.environment_id || params?.env || null,
      );
      summary.targetEnvName = resolveEnvironmentName(
        summary.targetEnvId,
        result?.environment || null,
      );
      if (Array.isArray(result?.failures) && result.failures.length > 0) {
        summary.warnings = result.failures
          .slice(0, 3)
          .map(
            (item) =>
              `${item?.title || item?.id}: ${item?.error || $t.common?.unknown || "Unknown error"}`,
          );
      }
      return summary;
    }

    if (task.plugin_id === "llm_dashboard_validation") {
      summary.targetEnvId = resolveEnvironmentId(
        params?.environment_id || null,
      );
      summary.targetEnvName = resolveEnvironmentName(summary.targetEnvId, null);
      if (result?.summary) {
        summary.lines.push(result.summary);
      }
      return summary;
    }

    if (result?.summary) {
      summary.lines.push(result.summary);
      return summary;
    }
    return null;
  }

  async function handleOpenDashboardDeepLink() {
    if (!derivedTaskSummary?.primaryDashboardId || !derivedTaskSummary?.targetEnvId) {
      addToast(
        $t.tasks?.summary_link_unavailable || "Deep link unavailable",
        "error",
      );
      return;
    }
    const href = resolveSupersetDashboardUrl(
      derivedTaskSummary.targetEnvId,
      derivedTaskSummary.primaryDashboardId,
    );
    if (!href) {
      addToast(
        $t.tasks?.summary_link_unavailable || "Deep link unavailable",
        "error",
      );
      return;
    }
    window.open(href, "_blank", "noopener,noreferrer");
  }

  async function handleShowDiff() {
    if (!derivedTaskSummary?.primaryDashboardId) {
      addToast(
        $t.tasks?.summary_link_unavailable || "Diff unavailable",
        "error",
      );
      return;
    }
    showDiff = true;
    isDiffLoading = true;
    diffText = "";
    try {
      const diffPayload = await gitService.getDiff(
        derivedTaskSummary.primaryDashboardId,
      );
      diffText =
        typeof diffPayload === "string"
          ? diffPayload
          : diffPayload?.diff || JSON.stringify(diffPayload, null, 2);
    } catch (err) {
      addToast(err?.message || "Failed to load diff", "error");
      diffText = "";
    } finally {
      isDiffLoading = false;
    }
  }

  function handleOpenLlmReport() {
    const taskId = normalizeTaskId(activeTaskId);
    if (!taskId) {
      addToast(
        $t.tasks?.summary_link_unavailable || "Report unavailable",
        "error",
      );
      return;
    }
    window.open(
      `/reports/llm/${encodeURIComponent(taskId)}`,
      "_blank",
      "noopener,noreferrer",
    );
  }

  // Connect to WebSocket for real-time logs
  function connectWebSocket() {
    if (!activeTaskId) return;

    const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
    const host = window.location.host;
    const taskId = normalizeTaskId(activeTaskId);
    const wsUrl = `${protocol}//${host}/ws/logs/${taskId}`;

    console.log(`[TaskDrawer][Action] Connecting to WebSocket: ${wsUrl}`);

    ws = new WebSocket(wsUrl);

    ws.onopen = () => {
      console.log("[TaskDrawer][Coherence:OK] WebSocket connected");
    };

    ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      console.log(`[TaskDrawer][WebSocket][Message_Received] ${data.message}`);

      realTimeLogs = [...realTimeLogs, data];

      if (data.message?.includes("Task completed successfully")) {
        taskStatus = "SUCCESS";
      } else if (data.message?.includes("Task failed")) {
        taskStatus = "FAILED";
      }
    };

    ws.onerror = (error) => {
      console.error("[TaskDrawer][Coherence:Failed] WebSocket error:", error);
    };

    ws.onclose = () => {
      console.log("[TaskDrawer][WebSocket] Connection closed");
    };
  }

  // [DEF:disconnectWebSocket:Function]
  /**
   * @PURPOSE: Disconnects the active WebSocket connection
   * @PRE: ws may or may not be initialized
   * @POST: ws is closed and set to null
   * @TIER: STANDARD
   */
  function disconnectWebSocket() {
    console.log("[TaskDrawer][WebSocket][disconnectWebSocket:START]");
    if (ws) {
      ws.close();
      ws = null;
    }
  }
  // [/DEF:disconnectWebSocket:Function]

  // [DEF:loadRecentTasks:Function]
  /**
   * @PURPOSE: Load recent tasks for list mode display
   * @PRE: User is on task drawer or api is ready.
   * @POST: recentTasks array populated with task list
   */
  async function loadRecentTasks() {
    loadingTasks = true;
    try {
      console.log("[TaskDrawer][API][loadRecentTasks:STARTED]");
      // API returns List[Task] directly, not {tasks: [...]}
      const response = await api.getTasks();
      recentTasks = Array.isArray(response) ? response : response.tasks || [];
      console.log(
        `[TaskDrawer][API][loadRecentTasks:SUCCESS] loaded ${recentTasks.length} tasks`,
      );
    } catch (err) {
      console.error("[TaskDrawer][API][loadRecentTasks:FAILED]", err);
      recentTasks = [];
    } finally {
      loadingTasks = false;
    }
  }
  // [/DEF:loadRecentTasks:Function]

  // [DEF:selectTask:Function]
  /**
   * @PURPOSE: Select a task from list to view details
   * @PRE: task is a valid task object
   * @POST: drawer state updated to show task details
   */
  function selectTask(task) {
    console.log("[TaskDrawer][UI][selectTask:START]");
    taskDrawerStore.update((state) => ({
      ...state,
      activeTaskId: task.id,
    }));
  }
  // [/DEF:selectTask:Function]

  // [DEF:goBackToList:Function]
  /**
   * @PURPOSE: Return to task list view from task details
   * @PRE: Drawer is open and activeTaskId is set
   * @POST: Drawer switches to list view and reloads tasks
   * @TIER: STANDARD
   */
  function goBackToList() {
    console.log("[TaskDrawer][UI][goBackToList:START]");
    taskDrawerStore.update((state) => ({
      ...state,
      activeTaskId: null,
    }));
    // Reload the task list
    loadRecentTasks();
    console.log("[TaskDrawer][UI][goBackToList:SUCCESS]");
  }
  // [/DEF:goBackToList:Function]

  // Reconnect when active task changes
  $effect(() => {
    if (isOpen) {
      if (activeTaskId) {
        disconnectWebSocket();
        realTimeLogs = [];
        showDiff = false;
        diffText = "";
        taskStatus = "RUNNING";
        connectWebSocket();
        void loadEnvironmentOptions();
        void loadActiveTaskDetails();
        stopTaskDetailsPolling();
        taskDetailsPollInterval = setInterval(loadActiveTaskDetails, 4000);
      } else {
        stopTaskDetailsPolling();
        activeTaskDetails = null;
        void loadRecentTasks();
      }
    } else {
      stopTaskDetailsPolling();
      activeTaskDetails = null;
    }
  });

  let derivedTaskSummary = $derived(buildTaskSummary(activeTaskDetails));
  let derivedActiveTaskValidation = $derived(
    resolveLlmValidationStatus(activeTaskDetails),
  );

  // Cleanup on destroy
  onDestroy(() => {
    stopTaskDetailsPolling();
    disconnectWebSocket();
  });
</script>

<svelte:window onkeydown={handleGlobalKeydown} />

{#if isOpen}
  <div
    class="fixed top-0 z-[72] flex h-full w-full max-w-[560px] flex-col border-l border-slate-200 bg-white shadow-[-8px_0_30px_rgba(15,23,42,0.15)] transition-[right] duration-300 ease-out"
    style={`right: ${assistantOffset};`}
    role="dialog"
    aria-modal="false"
    aria-label={$t.tasks?.drawer}
  >
    <!-- Header -->
    <div
      class="flex items-center justify-between border-b border-slate-200 bg-white px-5 py-3.5"
    >
      <div class="flex items-center gap-2.5">
        {#if !activeTaskId && recentTasks.length > 0}
          <span
            class="flex items-center justify-center p-1.5 mr-1 text-cyan-400"
          >
            <Icon name="list" size={16} strokeWidth={2} />
          </span>
        {:else if activeTaskId}
          <button
            class="flex items-center justify-center p-1.5 rounded-md text-slate-500 bg-transparent border-none cursor-pointer transition-all hover:text-slate-100 hover:bg-slate-800"
            onclick={goBackToList}
            aria-label={$t.tasks?.back_to_list}
          >
            <Icon name="back" size={16} strokeWidth={2} />
          </button>
        {/if}
        <h2 class="text-sm font-semibold tracking-tight text-slate-900">
          {activeTaskId ? $t.tasks?.details_logs : $t.tasks?.recent}
        </h2>
        {#if shortTaskId}
          <span
            class="text-xs font-mono text-slate-500 bg-slate-800 px-2 py-0.5 rounded"
            >{shortTaskId}…</span
          >
        {/if}
        {#if taskStatus}
          <span
            class="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-full {taskStatus.toLowerCase() ===
            'running'
              ? 'text-cyan-400 bg-cyan-400/10 border border-cyan-400/20'
              : taskStatus.toLowerCase() === 'success'
                ? 'text-green-400 bg-green-400/10 border border-green-400/20'
                : 'text-red-400 bg-red-400/10 border border-red-400/20'}"
            >{taskStatus}</span
          >
        {/if}
        {#if derivedActiveTaskValidation}
          <span
            class={`text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-full inline-flex items-center gap-1 ${llmValidationBadgeClass(derivedActiveTaskValidation.tone)}`}
            title="Dashboard validation result"
          >
            <span
              class="inline-flex min-w-[18px] items-center justify-center rounded-full bg-white/70 px-1 text-[10px] font-bold"
            >
              {derivedActiveTaskValidation.icon}
            </span>
            {derivedActiveTaskValidation.label}
          </span>
        {/if}
      </div>
      <div class="flex items-center gap-2">
        <button
          class="rounded-md border border-slate-300 bg-slate-50 px-2.5 py-1 text-xs font-semibold text-slate-700 transition-colors hover:bg-slate-100"
          onclick={goToReportsPage}
        >
          {$t.nav?.reports}
        </button>
        <button
          class="p-1.5 rounded-md text-slate-500 bg-transparent border-none cursor-pointer transition-all hover:text-slate-100 hover:bg-slate-800"
          onclick={handleClose}
          aria-label={$t.tasks?.close_drawer}
        >
          <Icon name="close" size={18} strokeWidth={2} />
        </button>
      </div>
    </div>

    <!-- Content -->
    <div class="flex-1 overflow-hidden flex flex-col">
      {#if activeTaskId}
        {#if derivedTaskSummary}
          <div
            class="mx-4 mt-4 rounded-lg border border-slate-200 bg-slate-50 p-3"
          >
            <div class="mb-2 flex items-center justify-between gap-2">
              <h3 class="text-sm font-semibold text-slate-900">
                {$t.tasks?.summary_report || "Summary report"}
              </h3>
              <span
                class="rounded-full bg-green-100 px-2 py-0.5 text-[11px] font-semibold text-green-700"
              >
                {taskStatus}
              </span>
            </div>
            {#if derivedTaskSummary.headline}
              <p class="mb-2 text-sm text-slate-700">{derivedTaskSummary.headline}</p>
            {/if}
            {#if derivedTaskSummary.lines.length > 0}
              <ul class="mb-2 space-y-1 text-xs text-slate-700">
                {#each derivedTaskSummary.lines as line}
                  <li>{line}</li>
                {/each}
              </ul>
            {/if}
            {#if derivedTaskSummary.warnings.length > 0}
              <div
                class="mb-2 rounded-md border border-amber-200 bg-amber-50 p-2 text-xs text-amber-800"
              >
                <p class="mb-1 font-semibold">
                  {$t.tasks?.observability_warnings || "Warnings"}
                </p>
                <ul class="space-y-1">
                  {#each derivedTaskSummary.warnings as warning}
                    <li>{warning}</li>
                  {/each}
                </ul>
              </div>
            {/if}
            <div class="flex flex-wrap gap-2">
              <button
                class="rounded-md border border-slate-300 bg-white px-2.5 py-1.5 text-xs font-semibold text-slate-700 transition-colors hover:bg-slate-100 disabled:cursor-not-allowed disabled:opacity-50"
                onclick={handleOpenDashboardDeepLink}
                disabled={!derivedTaskSummary?.primaryDashboardId ||
                  !derivedTaskSummary?.targetEnvId}
              >
                {#if derivedTaskSummary?.targetEnvName}
                  {(
                    $t.tasks?.open_dashboard_target || "Open dashboard in {env}"
                  ).replace("{env}", derivedTaskSummary.targetEnvName)}
                {:else}
                  {$t.tasks?.open_dashboard_target_fallback || "Open dashboard"}
                {/if}
              </button>
              <button
                class="rounded-md border border-slate-300 bg-white px-2.5 py-1.5 text-xs font-semibold text-slate-700 transition-colors hover:bg-slate-100 disabled:cursor-not-allowed disabled:opacity-50"
                onclick={handleShowDiff}
                disabled={!derivedTaskSummary?.primaryDashboardId}
              >
                {$t.tasks?.show_diff || "Show diff"}
              </button>
              {#if activeTaskDetails?.plugin_id === "llm_dashboard_validation"}
                <button
                  class="rounded-md border border-indigo-300 bg-indigo-50 px-2.5 py-1.5 text-xs font-semibold text-indigo-700 transition-colors hover:bg-indigo-100"
                  onclick={handleOpenLlmReport}
                >
                  {$t.tasks?.open_llm_report || "Open LLM report"}
                </button>
              {/if}
            </div>
            {#if showDiff}
              <div class="mt-3 rounded-md border border-slate-200 bg-white p-2">
                <p
                  class="mb-2 text-xs font-semibold uppercase tracking-wide text-slate-500"
                >
                  {$t.tasks?.diff_preview || "Diff preview"}
                </p>
                {#if isDiffLoading}
                  <p class="text-xs text-slate-500">
                    {$t.git?.loading_diff || "Loading diff..."}
                  </p>
                {:else if diffText}
                  <pre
                    class="max-h-40 overflow-auto rounded bg-slate-900 p-2 text-[11px] text-slate-100">{diffText}</pre>
                {:else}
                  <p class="text-xs text-slate-500">
                    {$t.tasks?.no_diff_available || "No diff available"}
                  </p>
                {/if}
              </div>
            {/if}
          </div>
        {/if}
        <TaskLogViewer
          inline={true}
          taskId={activeTaskId}
          {taskStatus}
          {realTimeLogs}
        />
      {:else if loadingTasks}
        <div
          class="flex flex-col items-center justify-center p-12 text-slate-500"
        >
          <div
            class="mb-4 h-8 w-8 animate-spin rounded-full border-2 border-slate-200 border-t-blue-500"
          ></div>
          <p>{$t.tasks?.loading}</p>
        </div>
      {:else if recentTasks.length > 0}
        <div class="p-4">
          <h3
            class="text-sm font-semibold text-slate-100 mb-4 pb-2 border-b border-slate-800"
          >
            {$t.tasks?.recent}
          </h3>
          {#each recentTasks as task}
            {@const taskValidation = resolveLlmValidationStatus(task)}
            <button
              class="flex items-center gap-3 w-full p-3 mb-2 bg-slate-800 border border-slate-700 rounded-lg cursor-pointer transition-all hover:bg-slate-700 hover:border-slate-600 text-left"
              onclick={() => selectTask(task)}
            >
              <span class="font-mono text-xs text-slate-500"
                >{task.id?.substring(0, 8) ||
                  $t.common?.not_available ||
                  "N/A"}...</span
              >
              <span class="flex-1 text-sm text-slate-100 font-medium"
                >{task.plugin_id || $t.common?.unknown}</span
              >
              <span
                class="text-xs font-semibold uppercase px-2 py-1 rounded-full {task.status?.toLowerCase() ===
                  'running' || task.status?.toLowerCase() === 'pending'
                  ? 'bg-cyan-500/15 text-cyan-400'
                  : task.status?.toLowerCase() === 'completed' ||
                      task.status?.toLowerCase() === 'success'
                    ? 'bg-green-500/15 text-green-400'
                    : task.status?.toLowerCase() === 'failed' ||
                        task.status?.toLowerCase() === 'error'
                      ? 'bg-red-500/15 text-red-400'
                      : 'bg-slate-500/15 text-slate-400'}"
                >{task.status || $t.common?.unknown}</span
              >
              {#if taskValidation}
                <span
                  class={`text-[10px] font-semibold uppercase px-2 py-1 rounded-full inline-flex items-center gap-1 ${llmValidationBadgeClass(taskValidation.tone)}`}
                  title="Dashboard validation result"
                >
                  <span
                    class="inline-flex min-w-[16px] items-center justify-center rounded-full bg-white/70 px-1 text-[9px] font-bold"
                  >
                    {taskValidation.icon}
                  </span>
                  {taskValidation.label}
                </span>
              {/if}
            </button>
          {/each}
        </div>
      {:else}
        <div
          class="flex flex-col items-center justify-center h-full text-slate-500"
        >
          <Icon
            name="clipboard"
            size={48}
            strokeWidth={1.6}
            className="mb-3 text-slate-700"
          />
          <p>{$t.tasks?.select_task}</p>
        </div>
      {/if}
    </div>

    <!-- Footer -->
    <div
      class="flex items-center gap-2 justify-center px-4 py-2.5 border-t border-slate-800 bg-slate-900"
    >
      <div class="w-1.5 h-1.5 rounded-full bg-cyan-400 animate-pulse"></div>
      <p class="text-xs text-slate-500">
        {$t.tasks?.footer_text}
      </p>
    </div>
  </div>
  <!-- [/DEF:TaskDrawer:Component] -->
{/if}
