// ABOUTME: Slide panel for viewing and managing cloud agent tasks.
// ABOUTME: Shows task list with real-time streaming, run agent form, and task details.

import {
  type Component,
  createEffect,
  createMemo,
  createSignal,
  For,
  onCleanup,
  onMount,
  Show,
} from "solid-js";
import { getDefaultOrganizationId } from "@/lib/tauri-bridge";
import { getCloudAgentPublisherForProvider } from "@/services/agent-tasks";
import { allowsCloudAgentLaunch } from "@/services/organization-policy";
import {
  agentTasksState,
  cancelTask,
  followTask,
  getEventsForTask,
  loadTasks,
  resumeTask,
  runAgent,
  stopFollowing,
} from "@/stores/agent-tasks.store";
import { authStore } from "@/stores/auth.store";
import { providerStore } from "@/stores/provider.store";
import { threadStore } from "@/stores/thread.store";
import { AgentTaskItem } from "./AgentTaskItem";

// SlidePanel chrome owns Close + backdrop dismissal — no AgentTasksPanel props (#2354).
export const AgentTasksPanel: Component = () => {
  type RunMode = "cloud" | "local";
  const [runMode, setRunMode] = createSignal<RunMode>("cloud");
  const [publisherSlug, setPublisherSlug] = createSignal("");
  const [messageText, setMessageText] = createSignal("");
  const [isSubmitting, setIsSubmitting] = createSignal(false);
  const [submitError, setSubmitError] = createSignal<string | null>(null);
  const [orgId, setOrgId] = createSignal("");
  const cloudLaunchAllowed = createMemo(() =>
    allowsCloudAgentLaunch(authStore.privateChatPolicy),
  );
  const lockedPublisherSlug = createMemo(() =>
    threadStore.activeThreadKind === "chat"
      ? getCloudAgentPublisherForProvider(providerStore.activeProvider)
      : null,
  );

  createEffect(() => {
    const lockedSlug = lockedPublisherSlug();
    if (lockedSlug) {
      setPublisherSlug(lockedSlug);
    }
  });

  // Load org ID and tasks on mount
  onMount(async () => {
    const id = await getDefaultOrganizationId();
    if (id) {
      setOrgId(id);
      loadTasks(id);
    }
  });

  // Cleanup stream on unmount
  onCleanup(() => {
    stopFollowing();
  });

  const handleRunAgent = async (e: Event) => {
    e.preventDefault();
    const slug = publisherSlug().trim();
    const msg = messageText().trim();
    if (!cloudLaunchAllowed()) {
      setSubmitError(
        "Your organization has disabled cloud agent launch from Desktop.",
      );
      return;
    }
    if (!slug || !msg || !orgId()) return;

    setIsSubmitting(true);
    setSubmitError(null);
    try {
      let parsed: unknown;
      try {
        parsed = JSON.parse(msg);
      } catch {
        // Wrap plain text in a text message
        parsed = { text: msg };
      }
      await runAgent(orgId(), slug, parsed);
      setMessageText("");
    } catch (err) {
      setSubmitError(err instanceof Error ? err.message : String(err));
    } finally {
      setIsSubmitting(false);
    }
  };

  const handleSelectTask = (taskId: string) => {
    if (orgId()) {
      followTask(orgId(), taskId);
    }
  };

  const handleCancelTask = (taskId: string) => {
    if (orgId()) {
      cancelTask(orgId(), taskId);
    }
  };

  const handleResumeTask = async (taskId: string, input: unknown) => {
    if (!orgId()) return;
    await resumeTask(orgId(), taskId, input);
  };

  const activeTasks = () =>
    agentTasksState.tasks.filter(
      (t) => !["completed", "failed", "canceled"].includes(t.status),
    );

  const completedTasks = () =>
    agentTasksState.tasks.filter((t) =>
      ["completed", "failed", "canceled"].includes(t.status),
    );

  return (
    <div class="flex flex-col h-full bg-background">
      {/* Header */}
      <div class="flex items-center justify-between px-4 py-3 border-b border-border">
        <div class="flex items-center gap-2">
          <svg
            class="w-4 h-4 text-primary"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <title>Agent Tasks</title>
            <path
              stroke-linecap="round"
              stroke-linejoin="round"
              stroke-width="2"
              d="M13 10V3L4 14h7v7l9-11h-7z"
            />
          </svg>
          <h2 class="text-sm font-semibold text-foreground m-0">Agent Tasks</h2>
          <Show when={activeTasks().length > 0}>
            <span class="px-1.5 py-0.5 bg-primary/20 text-primary text-[10px] font-bold rounded-full min-w-[18px] text-center">
              {activeTasks().length}
            </span>
          </Show>
        </div>
      </div>

      {/* Run Agent Form */}
      <form
        class="px-4 py-3 border-b border-border/50 bg-surface-0"
        onSubmit={handleRunAgent}
      >
        {/* Backend Mode Toggle */}
        <div class="flex items-center gap-1 mb-2">
          <button
            type="button"
            class={`px-2 py-0.5 text-[11px] font-medium rounded transition-colors ${
              runMode() === "cloud"
                ? "bg-primary/20 text-primary"
                : "text-muted-foreground hover:text-foreground"
            }`}
            onClick={() => setRunMode("cloud")}
          >
            Cloud
          </button>
          <button
            type="button"
            class="px-2 py-0.5 text-[11px] font-medium rounded text-muted-foreground/40 cursor-not-allowed"
            disabled
            title="Local runner coming soon"
          >
            Local
          </button>
        </div>

        <div class="flex gap-2 mb-2">
          <Show
            when={lockedPublisherSlug()}
            fallback={
              <input
                type="text"
                placeholder="Publisher slug"
                value={publisherSlug()}
                onInput={(e) => setPublisherSlug(e.currentTarget.value)}
                class="flex-1 px-2.5 py-1.5 bg-surface-2 border border-border rounded text-[13px] text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:border-primary/50 transition-colors"
                disabled={!cloudLaunchAllowed()}
              />
            }
          >
            <div class="flex-1 px-2.5 py-1.5 bg-surface-2 border border-border rounded text-[13px] text-foreground">
              {lockedPublisherSlug()}
            </div>
          </Show>
          <button
            type="submit"
            disabled={
              isSubmitting() ||
              !cloudLaunchAllowed() ||
              !publisherSlug().trim() ||
              !messageText().trim()
            }
            class="px-3 py-1.5 bg-primary text-background text-[12px] font-semibold rounded hover:bg-primary/85 transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
          >
            {isSubmitting() ? "..." : "Run"}
          </button>
        </div>
        <Show when={lockedPublisherSlug()}>
          <div class="mb-2 text-[11px] text-muted-foreground">
            The current chat lane fixes the cloud publisher: Seren Agent uses
            `seren-models`, and Seren Agent (Private) uses
            `seren-private-models`.
          </div>
        </Show>
        <textarea
          placeholder="Message (JSON or plain text)"
          value={messageText()}
          onInput={(e) => setMessageText(e.currentTarget.value)}
          class="w-full px-2.5 py-2 bg-surface-2 border border-border rounded text-[12px] text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:border-primary/50 transition-colors resize-none font-mono leading-relaxed"
          rows={2}
          disabled={!cloudLaunchAllowed()}
        />
        <Show when={!cloudLaunchAllowed()}>
          <div class="mt-1.5 px-2 py-1 bg-amber-950/30 border border-amber-400/20 rounded text-[11px] text-amber-300">
            Cloud agent launch is disabled by your organization policy.
          </div>
        </Show>
        <Show when={submitError()}>
          <div class="mt-1.5 px-2 py-1 bg-red-950/30 border border-red-400/20 rounded text-[11px] text-red-400">
            {submitError()}
          </div>
        </Show>
      </form>

      {/* Task List */}
      <div class="flex-1 overflow-y-auto [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-surface-3 [&::-webkit-scrollbar-thumb]:rounded">
        <Show when={agentTasksState.isLoading}>
          <div class="flex items-center justify-center py-8">
            <div class="flex items-center gap-2 text-muted-foreground text-sm">
              <svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
                <title>Loading spinner</title>
                <circle
                  class="opacity-25"
                  cx="12"
                  cy="12"
                  r="10"
                  stroke="currentColor"
                  stroke-width="4"
                />
                <path
                  class="opacity-75"
                  fill="currentColor"
                  d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
                />
              </svg>
              Loading tasks...
            </div>
          </div>
        </Show>

        <Show when={agentTasksState.error}>
          <div class="mx-4 mt-3 px-3 py-2 bg-red-950/20 border border-red-400/20 rounded text-[12px] text-red-400">
            {agentTasksState.error}
          </div>
        </Show>

        <Show
          when={
            !agentTasksState.isLoading &&
            agentTasksState.tasks.length === 0 &&
            !agentTasksState.error
          }
        >
          <div class="flex flex-col items-center justify-center py-12 text-muted-foreground">
            <svg
              class="w-10 h-10 mb-3 opacity-30"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <title>No tasks</title>
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="1.5"
                d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
              />
            </svg>
            <p class="text-[13px] m-0">No tasks yet</p>
            <p class="text-[11px] mt-1 m-0 opacity-60">
              Run an agent above to create a task
            </p>
          </div>
        </Show>

        {/* Active Tasks */}
        <Show when={activeTasks().length > 0}>
          <div class="px-3 pt-3 pb-1">
            <div class="text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/70">
              Active
            </div>
          </div>
          <For each={activeTasks()}>
            {(task) => (
              <AgentTaskItem
                task={task}
                isActive={agentTasksState.activeTaskId === task.id}
                events={getEventsForTask(task.id)}
                onSelect={handleSelectTask}
                onCancel={handleCancelTask}
                onResume={handleResumeTask}
              />
            )}
          </For>
        </Show>

        {/* Completed Tasks */}
        <Show when={completedTasks().length > 0}>
          <div class="px-3 pt-3 pb-1">
            <div class="text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/70">
              History
            </div>
          </div>
          <For each={completedTasks()}>
            {(task) => (
              <AgentTaskItem
                task={task}
                isActive={agentTasksState.activeTaskId === task.id}
                events={getEventsForTask(task.id)}
                onSelect={handleSelectTask}
                onCancel={handleCancelTask}
                onResume={handleResumeTask}
              />
            )}
          </For>
        </Show>
      </div>
    </div>
  );
};
