<!-- #region TaskDrawer [C:4] [TYPE Component] [SEMANTICS task, drawer, logs, websocket, detail] -->
<!-- @ingroup Layout -->
<!-- @BRIEF Global task drawer for monitoring background operations via WebSocket logs, task summaries, and detail views. -->
<!-- @LAYER UI -->
<!-- @RELATION BINDS_TO -> [EXT:frontend:taskDrawerStore] -->
<!-- @RELATION BINDS_TO -> [EXT:frontend:assistantChatStore] -->
<!-- @RELATION DEPENDS_ON -> [TaskLogViewer] -->
<!-- @RELATION DEPENDS_ON -> [PasswordPrompt] -->
<!-- @UX_STATE Closed -> Drawer hidden, no active task. -->
<!-- @UX_STATE Open/ListMode -> Recent tasks list displayed. -->
<!-- @UX_STATE Open/TaskDetail -> Task logs and summary shown for selected task. -->
<!-- @UX_STATE InputRequired -> Password/interactive form rendered in drawer. -->
<!-- @UX_FEEDBACK Close/Back buttons allow navigation. -->
<!-- @UX_FEEDBACK WebSocket provides real-time log streaming. -->
<!-- @UX_RECOVERY Click outside or Escape closes drawer. -->
<script lang="ts">
  /**
   * @PURPOSE: Global task drawer for monitoring background operations
   * @LAYER UI
   * @RELATION BINDS_TO -> [EXT:frontend:taskDrawer]
   * @SEMANTICS: TaskLogViewer
   * @PRE: Task drawer store and optional websocket task context are available before detail mode is requested.
   * @POST: Drawer stays closed, shows the recent-task list, or renders a selected task detail without losing task context.
   * @SIDE_EFFECT: Opens websocket streams, loads recent tasks, and mutates drawer selection state.
   * @DATA_CONTRACT: TaskDrawerState -> RecentTaskList | ActiveTaskDetail
    * @INVARIANT: Drawer shows logs for active task or remains closed
   * @UX_REACTIVITY: Uses $state for local drawer UI and $derived or store subscriptions for active task synchronization.
    *
    * @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 { log } from "$lib/cot-logger";
  import { taskDrawerStore, closeDrawer } from "$lib/stores/taskDrawer.svelte.js";
  import { assistantChatStore } from "$lib/stores/assistantChat.svelte.js";
  import TaskLogViewer from "$lib/components/tasks/TaskLogViewer.svelte";
  import { getReportTypeProfile } from "../reports/reportTypeProfiles.js";
  import { t } from "$lib/i18n/index.svelte.js";
  import { ROUTES } from "$lib/routes";
  import { api, getWsUrl } from "$lib/api.js";
  import Icon from "$lib/ui/Icon.svelte";
  import { addToast } from "$lib/toasts.svelte.js";
  import { gitService } from "../../../services/gitService.js";

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

  let isOpen = $derived(Boolean(taskDrawerStore.value?.isOpen));
  let activeTaskId = $derived(taskDrawerStore.value?.activeTaskId || null);
  let isAssistantOpen = $derived(Boolean(assistantChatStore.value?.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() {
    log("TaskDrawer", "REASON", "Close drawer");
    closeDrawer();
  }

  function goToReportsPage() {
    closeDrawer();
    window.location.href = ROUTES.reports.list();
  }

  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;
    // Check for ValidationRun aggregate counts (v2) first
    const result = task?.result || {};
    if (typeof result.fail_count === "number" && result.fail_count > 0)
      return { label: "FAIL", tone: "fail", icon: "!" };
    if (typeof result.warn_count === "number" && result.warn_count > 0)
      return { label: "WARN", tone: "warn", icon: "!" };
    if (typeof result.pass_count === "number" && result.pass_count > 0)
      return { label: "PASS", tone: "pass", icon: "OK" };
    // Fall back to legacy result.status from plugin output
    const raw = String(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-destructive bg-destructive-light ring-1 ring-destructive-ring";
    if (tone === "warn")
      return "text-warning bg-warning-light ring-1 ring-warning-ring";
    if (tone === "pass")
      return "text-success bg-success-light ring-1 ring-success-ring";
    return "text-text bg-surface-muted ring-1 ring-secondary-ring";
  }

  function getStatusClass(status) {
    const s = status?.toLowerCase();
    if (s === "success" || s === "completed")
      return "bg-success-light text-success ring-1 ring-success-ring";
    if (s === "failed" || s === "error")
      return "bg-destructive-light text-destructive ring-1 ring-destructive-ring";
    if (s === "running" || s === "in_progress")
      return "bg-primary-light text-primary ring-1 ring-primary-ring";
    if (s === "partial" || s === "partial_success")
      return "bg-warning-light text-warning ring-1 ring-warning-ring";
    return "bg-surface-muted text-text ring-1 ring-secondary-ring";
  }

  async function loadEnvironmentOptions() {
    try {
      const response = await api.getEnvironments();
      environmentOptions = Array.isArray(response) ? response : [];
    } catch (err) {
      log("TaskDrawer", "EXPLORE", "loadEnvironmentOptions failed", {}, err instanceof Error ? err.message : "Unknown");
      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) {
    let baseUrl = String(rawUrl || "").trim().replace(/\/+$/, "");
    if (!baseUrl) return null;
    if (baseUrl.endsWith("/api/v1")) {
      baseUrl = baseUrl.slice(0, -"/api/v1".length);
    }
    // Auto-prepend https:// if no scheme is present
    if (baseUrl && !/^https?:\/\//i.test(baseUrl)) {
      baseUrl = `https://${baseUrl}`;
    }
    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))}/`;
  }

  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,
      );
      if (typeof diffPayload === "string") {
        diffText = diffPayload;
      } else if (diffPayload && typeof diffPayload === "object") {
        diffText =
          diffPayload.diff || JSON.stringify(diffPayload, null, 2);
      } else {
        diffText = "";
      }
    } 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;
    }
    // Prefer direct v2 ValidationRun URL when policy_id and run_id are available
    const params = activeTaskDetails?.params || {};
    const policyId = params.policy_id;
    const runId = params.run_id;
    if (policyId && runId) {
      window.open(
        `/validation-tasks/${encodeURIComponent(policyId)}/runs/${encodeURIComponent(runId)}`,
        "_blank",
        "noopener,noreferrer",
      );
      return;
    }
    // Fall back to legacy /reports/llm/{taskId} — API returns 302 redirect
    window.open(
      `/reports/llm/${encodeURIComponent(taskId)}`,
      "_blank",
      "noopener,noreferrer",
    );
  }

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

    const taskId = normalizeTaskId(activeTaskId);
    const wsUrl = getWsUrl(taskId);

    log("TaskDrawer", "REASON", "Connecting to WebSocket", { wsUrl });

    ws = new WebSocket(wsUrl);

    ws.onopen = () => {
      log("TaskDrawer", "REFLECT", "WebSocket connected");
    };

    ws.onmessage = (event) => {
      const data = JSON.parse(event.data);

      // ── Task status update from WebSocket ──
      if (data.type === "task_status") {
        const taskData = data.task;
        log("TaskDrawer", "REFLECT", "WebSocket status update", { status: taskData.status });
        activeTaskDetails = taskData;
        taskStatus = taskData.status;
        return;
      }

      // ── Log entry (backward compatible, no type field) ──
      log("TaskDrawer", "REFLECT", "WebSocket log received", { message: 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) => {
      log("TaskDrawer", "EXPLORE", "WebSocket error", {}, error instanceof Error ? error.message : "Unknown websocket error");
    };

    ws.onclose = (event) => {
      // event.code 1000 = normal closure (task finished) — stop reconnecting
      // event.code 1006 = abnormal close (network issue) — reconnect
      const isNormalClosure = event.code === 1000;
      const isTerminal = taskStatus === "SUCCESS" || taskStatus === "FAILED";

      if (isNormalClosure || isTerminal) {
        log("TaskDrawer", "REFLECT", "WebSocket closed normally - stream ended", { code: event.code });
      } else {
        log("TaskDrawer", "REASON", "WebSocket disconnected, reconnecting in 10s", { code: event.code });
        ws = null;
        wsReconnectTimer = setTimeout(() => {
          if (activeTaskId) connectWebSocket();
        }, 10000);
      }
    };
  }

  // #region disconnectWebSocket:Function [TYPE Function]
// @ingroup Layout
// @UX_STATE: Loading -> Default
// @RELATION USES -> [EXT:frontend:App]
  /**
   * @PURPOSE: Disconnects the active WebSocket connection
   * @PRE: ws may or may not be initialized
   * @POST: ws is closed and set to null
   */
  function disconnectWebSocket() {
    log("TaskDrawer", "REASON", "Disconnecting WebSocket");
    if (wsReconnectTimer) {
      clearTimeout(wsReconnectTimer);
      wsReconnectTimer = null;
    }
    if (ws) {
      ws.onclose = null; // prevent reconnect
      ws.close();
      ws = null;
    }
  }
  // #endregion disconnectWebSocket:Function

  // #region loadRecentTasks:Function [TYPE Function]
// @ingroup Layout
  /**
   * @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 {
      log("TaskDrawer", "REASON", "Load recent tasks");
      // API returns List[Task] directly, not {tasks: [...]}
      const response = await api.getTasks();
      recentTasks = Array.isArray(response) ? response : response.tasks || [];
      log("TaskDrawer", "REFLECT", "Recent tasks loaded", { count: recentTasks.length });
    } catch (err) {
      log("TaskDrawer", "EXPLORE", "Load recent tasks failed", {}, err instanceof Error ? err.message : "Unknown");
      recentTasks = [];
    } finally {
      loadingTasks = false;
    }
  }
  // #endregion loadRecentTasks:Function

  // #region selectTask:Function [TYPE Function]
// @ingroup Layout
  /**
   * @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) {
    log("TaskDrawer", "REASON", "Select task");
    taskDrawerStore.update((state) => ({
      ...state,
      activeTaskId: task.id,
    }));
  }
  // #endregion selectTask:Function

  // #region goBackToList:Function [TYPE Function]
// @ingroup Layout
// @UX_STATE: Loading -> Default
// @RELATION USES -> [EXT:frontend:App]
  /**
   * @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
   */
  function goBackToList() {
    log("TaskDrawer", "REASON", "Go back to task list");
    taskDrawerStore.update((state) => ({
      ...state,
      activeTaskId: null,
    }));
    // Reload the task list
    loadRecentTasks();
    log("TaskDrawer", "REFLECT", "Back to task list");
  }
  // #endregion goBackToList:Function

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

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

  // Cleanup on destroy
  onDestroy(() => {
    if (wsReconnectTimer) {
      clearTimeout(wsReconnectTimer);
    }
    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-border bg-surface-card shadow-[-12px_0_40px_rgba(15,23,42,0.1)] 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-border bg-surface-card 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-info"
          >
            <Icon name="list" size={16} strokeWidth={2} />
          </span>
        {:else if activeTaskId}
          <button
            class="flex items-center justify-center p-1.5 rounded-md text-text-muted bg-transparent border-none cursor-pointer transition-all hover:text-text hover:bg-surface-muted"
            onclick={goBackToList}
            aria-label={$t.tasks?.back_to_list}
          >
            <Icon name="back" size={16} strokeWidth={2} />
          </button>
        {/if}
        <h2 class="text-sm font-bold tracking-tight text-text">
          {activeTaskId ? $t.tasks?.details_logs : $t.tasks?.recent}
        </h2>
        {#if shortTaskId}
          <span
            class="text-[10px] font-mono font-medium text-text-muted bg-surface-page border border-border px-2 py-0.5 rounded"
            >{shortTaskId}…</span
          >
        {/if}
        {#if taskStatus}
          <span
            class="text-[10px] font-bold uppercase tracking-wider px-2 py-0.5 rounded {getStatusClass(taskStatus)}"
          >
            {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-surface-card/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-border-strong bg-surface-page px-2.5 py-1 text-xs font-semibold text-text transition-colors hover:bg-surface-muted"
          onclick={goToReportsPage}
        >
          {$t.nav?.reports}
        </button>
        <button
          class="p-1.5 rounded-md text-text-muted bg-transparent border-none cursor-pointer transition-all hover:text-text hover:bg-surface-muted"
          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-xl border border-border bg-surface-card p-4 shadow-sm"
          >
            <div class="mb-3 flex items-center justify-between gap-2">
              <div class="flex items-center gap-2">
                <div class="p-1.5 bg-primary-light text-primary rounded-lg">
                  <Icon name="list" size={14} />
                </div>
                <h3 class="text-sm font-bold text-text">
                  {$t.tasks?.summary_report || "Summary report"}
                </h3>
              </div>
              <span
                class="rounded-full px-2.5 py-0.5 text-[10px] font-bold uppercase tracking-wider {getStatusClass(taskStatus)}"
              >
                {taskStatus}
              </span>
            </div>
            {#if derivedTaskSummary.headline}
              <p class="mb-2 text-sm text-text">{derivedTaskSummary.headline}</p>
            {/if}
            {#if derivedTaskSummary.lines.length > 0}
              <ul class="mb-2 space-y-1 text-xs text-text">
                {#each derivedTaskSummary.lines as line}
                  <li>{line}</li>
                {/each}
              </ul>
            {/if}
            {#if derivedTaskSummary.warnings.length > 0}
              <div
                class="mb-2 rounded-md border border-warning bg-warning-light p-2 text-xs text-warning"
              >
                <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 mt-4">
              <button
                class="flex-1 min-w-[120px] rounded-lg border border-border bg-surface-card px-3 py-2 text-xs font-bold text-text shadow-sm transition-all hover:border-border-strong hover:bg-surface-page 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="flex-1 min-w-[100px] rounded-lg border border-border bg-surface-card px-3 py-2 text-xs font-bold text-text shadow-sm transition-all hover:border-border-strong hover:bg-surface-page 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="flex-1 min-w-[120px] rounded-lg border border-primary-ring bg-primary-light px-3 py-2 text-xs font-bold text-primary shadow-sm transition-all hover:border-primary-ring hover:bg-primary-light"
                  onclick={handleOpenLlmReport}
                >
                  {$t.tasks?.open_llm_report || "Open LLM report"}
                </button>
              {/if}
            </div>
            {#if showDiff}
              <div class="mt-3 rounded-md border border-border bg-surface-card p-2">
                <p
                  class="mb-2 text-xs font-semibold uppercase tracking-wide text-text-muted"
                >
                  {$t.tasks?.diff_preview || "Diff preview"}
                </p>
                {#if isDiffLoading}
                  <p class="text-xs text-text-muted">
                    {$t.git?.loading_diff || "Loading diff..."}
                  </p>
                {:else if diffText}
                  <pre
                    class="max-h-40 overflow-auto rounded bg-terminal-bg p-2 text-[11px] text-text-subtle">{diffText}</pre>
                {:else}
                  <p class="text-xs text-text-muted">
                    {$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-text-muted"
        >
          <div
            class="mb-4 h-8 w-8 animate-spin rounded-full border-2 border-border border-t-blue-500"
          ></div>
          <p>{$t.tasks?.loading}</p>
        </div>
      {:else if recentTasks.length > 0}
        <div class="p-5 space-y-4">
          <div class="flex items-center justify-between">
            <h3 class="text-[11px] font-bold uppercase tracking-widest text-text-subtle">
              {$t.tasks?.recent}
            </h3>
            {#if loadingTasks}
               <div class="h-3 w-3 animate-spin rounded-full border border-border border-t-blue-500"></div>
            {/if}
          </div>
          <div class="grid gap-4">
            {#each recentTasks as task}
              {@const taskValidation = resolveLlmValidationStatus(task)}
              {@const profile = getReportTypeProfile(
                {
                  "llm_dashboard_validation": "llm_verification",
                  "superset-backup": "backup",
                  "superset-migration": "migration",
                  "documentation": "documentation",
                }[task.plugin_id] || task.plugin_id,
              )}
              <button
                class="group flex flex-col w-full p-4 bg-surface-card border border-border rounded-xl shadow-sm transition-all hover:border-primary-ring hover:bg-surface-page/50 hover:shadow-md text-left"
                onclick={() => selectTask(task)}
              >
                <div class="flex items-center justify-between gap-2 mb-3">
                  <span
                    class="rounded px-2 py-0.5 text-xs font-semibold {profile?.variant ||
                      'bg-surface-muted text-text'}"
                  >
                    {profile?.label
                      ? typeof profile.label === 'function'
                        ? profile.label()
                        : profile.label
                      : task.plugin_id || $t.common?.unknown}
                  </span>
                  <div class="flex items-center gap-2">
                    {#if taskValidation}
                      <span
                        class={`text-[10px] font-bold uppercase px-2 py-0.5 rounded-full inline-flex items-center gap-1 ${llmValidationBadgeClass(
                          taskValidation.tone,
                        )}`}
                      >
                        {taskValidation.label}
                      </span>
                    {/if}
                    <span
                      class="text-[10px] font-bold uppercase px-2 py-0.5 rounded-full {getStatusClass(
                        task.status,
                      )}"
                    >
                      {task.status || $t.common?.unknown}
                    </span>
                  </div>
                </div>

                <div class="flex flex-col gap-1">
                  <p class="text-sm font-semibold text-text line-clamp-1">
                    {task.params?.dashboard_id ||
                      (task.plugin_id === 'superset-migration' ? $t.nav?.migration : task.plugin_id) ||
                      $t.common?.not_available}
                  </p>
                  <p class="text-xs text-text-muted line-clamp-1 opacity-70">
                     {task.result?.summary || task.id}
                  </p>
                </div>

                <div
                  class="mt-4 flex items-center justify-between border-t border-border pt-3 text-[10px] text-text-subtle"
                >
                  <div class="flex items-center gap-1.5">
                    <Icon name="hash" size={10} />
                    <span class="font-mono tracking-tighter"
                      >{task.id?.substring(0, 8) || 'N/A'}</span
                    >
                  </div>
                  <div class="flex items-center gap-1.5">
                    <Icon name="clock" size={10} />
                    <span>{task.updated_at ? new Date(task.updated_at).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) : ''}</span>
                  </div>
                </div>
              </button>
            {/each}
          </div>
        </div>
      {:else}
        <div
          class="flex flex-col items-center justify-center h-full text-text-muted"
        >
          <Icon
            name="clipboard"
            size={48}
            strokeWidth={1.6}
            className="mb-3 text-text"
          />
          <p>{$t.tasks?.select_task}</p>
        </div>
      {/if}
    </div>

    <!-- Footer -->
    <div
      class="flex items-center gap-2 justify-center px-4 py-3 border-t border-border bg-surface-page"
    >
      <div class="w-1.5 h-1.5 rounded-full bg-primary-ring animate-pulse"></div>
      <p class="text-[11px] font-medium text-text-muted">
        {$t.tasks?.footer_text}
      </p>
    </div>
  </div>
  <!-- #endregion TaskDrawer -->
{/if}
