"use client";

import { useEffect, useRef, useState, useCallback } from "react";
import {
  ArrowRight,
  CheckCircle,
  XCircle,
  Clock,
  Loader2,
  RefreshCw,
  ChevronDown,
  ChevronRight,
  AlertTriangle,
  Inbox,
  List,
} from "lucide-react";

// Known agents for the per-agent view (order determines tab order)
const KNOWN_AGENTS = [
  "teletraan-x",
  "perceptor",
  "red-alert",
  "prowl",
  "laserbeak",
  "soundwave",
  "grapple",
];

// ─── Types ───────────────────────────────────────────────────────────────────

type TaskStatus = "pending" | "in_progress" | "complete" | "failed" | "timed_out";

interface Task {
  id: string;
  from_agent: string;
  to_agent: string;
  task: string;
  context?: string;
  conversation_id?: string;
  status: TaskStatus;
  result?: string;
  created_at: number;
  updated_at: number;
  completed_at?: number;
}

// ─── Status Badge ────────────────────────────────────────────────────────────

function StatusBadge({ status }: { status: TaskStatus }) {
  const configs: Record<TaskStatus, { label: string; className: string; icon: React.ReactNode }> = {
    pending: {
      label: "Pending",
      className: "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400",
      icon: <Clock size={11} />,
    },
    in_progress: {
      label: "In Progress",
      className: "bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400",
      icon: <Loader2 size={11} className="animate-spin" />,
    },
    complete: {
      label: "Complete",
      className: "bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400",
      icon: <CheckCircle size={11} />,
    },
    failed: {
      label: "Failed",
      className: "bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400",
      icon: <XCircle size={11} />,
    },
    timed_out: {
      label: "Timed Out",
      className: "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400",
      icon: <AlertTriangle size={11} />,
    },
  };

  const { label, className, icon } = configs[status] ?? configs.pending;

  return (
    <span className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium ${className}`}>
      {icon}
      {label}
    </span>
  );
}

// ─── Task Row ────────────────────────────────────────────────────────────────

function TaskRow({ task }: { task: Task }) {
  const [expanded, setExpanded] = useState(false);

  const elapsed =
    task.completed_at != null
      ? formatDuration(task.completed_at - task.created_at)
      : formatDuration(Date.now() - task.created_at);

  return (
    <div className="border border-zinc-200 dark:border-zinc-800 rounded-lg overflow-hidden">
      {/* Header row */}
      <button
        onClick={() => setExpanded((e) => !e)}
        className="w-full flex items-start gap-3 px-4 py-3 text-left hover:bg-zinc-50 dark:hover:bg-zinc-900/50 transition-colors"
      >
        <span className="mt-0.5 text-zinc-400 dark:text-zinc-500 flex-shrink-0">
          {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
        </span>

        {/* Agent flow */}
        <span className="flex items-center gap-1.5 flex-shrink-0">
          <span className="text-xs font-mono font-medium text-zinc-700 dark:text-zinc-300">
            {task.from_agent}
          </span>
          <ArrowRight size={12} className="text-zinc-400" />
          <span className="text-xs font-mono font-medium text-zinc-700 dark:text-zinc-300">
            {task.to_agent}
          </span>
        </span>

        {/* Task summary */}
        <span className="flex-1 text-xs text-zinc-600 dark:text-zinc-400 truncate min-w-0">
          {task.task.length > 120 ? task.task.slice(0, 120) + "…" : task.task}
        </span>

        {/* Status + time */}
        <span className="flex items-center gap-2 flex-shrink-0 ml-2">
          <StatusBadge status={task.status} />
          <span className="text-xs text-zinc-400 dark:text-zinc-500 whitespace-nowrap">{elapsed}</span>
        </span>
      </button>

      {/* Expanded detail */}
      {expanded && (
        <div className="border-t border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/30 px-4 py-3 space-y-3">
          <div>
            <p className="text-xs font-semibold text-zinc-500 dark:text-zinc-500 uppercase tracking-wide mb-1">
              Task
            </p>
            <p className="text-sm text-zinc-700 dark:text-zinc-300 whitespace-pre-wrap">{task.task}</p>
          </div>

          {task.context && (
            <div>
              <p className="text-xs font-semibold text-zinc-500 dark:text-zinc-500 uppercase tracking-wide mb-1">
                Context
              </p>
              <p className="text-sm text-zinc-600 dark:text-zinc-400 whitespace-pre-wrap">{task.context}</p>
            </div>
          )}

          {task.result && (
            <div>
              <p className="text-xs font-semibold text-zinc-500 dark:text-zinc-500 uppercase tracking-wide mb-1">
                Result
              </p>
              <p className="text-sm text-zinc-700 dark:text-zinc-300 whitespace-pre-wrap">{task.result}</p>
            </div>
          )}

          <div className="flex flex-wrap gap-4 text-xs text-zinc-400 dark:text-zinc-500">
            <span>ID: <span className="font-mono">{task.id.slice(0, 8)}…</span></span>
            <span>Created: {new Date(task.created_at).toLocaleString()}</span>
            {task.completed_at && (
              <span>Completed: {new Date(task.completed_at).toLocaleString()}</span>
            )}
            {task.conversation_id && (
              <span>Conv: <span className="font-mono">{task.conversation_id.slice(0, 8)}…</span></span>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

// ─── Conversation Group ───────────────────────────────────────────────────────

function ConversationGroup({ convId, tasks }: { convId: string; tasks: Task[] }) {
  const label = convId === "__ungrouped__" ? "No Conversation" : `Conversation: ${convId.slice(0, 8)}…`;
  const activeCount = tasks.filter((t) => t.status === "pending" || t.status === "in_progress").length;

  return (
    <div className="space-y-2">
      <div className="flex items-center gap-2">
        <span className="text-xs font-semibold text-zinc-500 dark:text-zinc-500 uppercase tracking-wide">
          {label}
        </span>
        {activeCount > 0 && (
          <span className="text-xs bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400 rounded-full px-2 py-0.5">
            {activeCount} active
          </span>
        )}
      </div>
      <div className="space-y-1.5">
        {tasks.map((t) => (
          <TaskRow key={t.id} task={t} />
        ))}
      </div>
    </div>
  );
}

// ─── Agent Inbox View ─────────────────────────────────────────────��───────────

function AgentInboxView({ agentName }: { agentName: string }) {
  const [tasks, setTasks] = useState<Task[]>([]);
  const [loading, setLoading] = useState(true);
  const [connected, setConnected] = useState(false);
  const esRef = useRef<EventSource | null>(null);

  const applyUpdate = useCallback((updated: Task) => {
    setTasks((prev) => {
      const idx = prev.findIndex((t) => t.id === updated.id);
      if (idx === -1) return [updated, ...prev];
      const next = [...prev];
      next[idx] = updated;
      return next;
    });
  }, []);

  useEffect(() => {
    setLoading(true);
    fetch(`/api/tasks/agent/${encodeURIComponent(agentName)}`)
      .then((r) => r.json())
      .then((d) => {
        setTasks(d.tasks ?? []);
        setLoading(false);
      })
      .catch(() => setLoading(false));

    const es = new EventSource(`/api/tasks/agent/${encodeURIComponent(agentName)}/stream`);
    esRef.current = es;
    es.onopen = () => setConnected(true);
    es.onerror = () => setConnected(false);
    es.onmessage = (event) => {
      try {
        const msg = JSON.parse(event.data);
        if (msg.type === "task_snapshot") {
          setTasks(msg.tasks ?? []);
        } else if (msg.type === "task_update" && msg.task) {
          applyUpdate(msg.task);
        }
      } catch {
        // ignore
      }
    };
    return () => {
      es.close();
      esRef.current = null;
    };
  }, [agentName, applyUpdate]);

  const active = tasks.filter((t) => t.status === "pending" || t.status === "in_progress");
  const done = tasks.filter((t) => t.status !== "pending" && t.status !== "in_progress");

  if (loading) {
    return (
      <div className="flex items-center justify-center h-32">
        <Loader2 size={20} className="animate-spin text-zinc-400" />
      </div>
    );
  }

  if (tasks.length === 0) {
    return (
      <div className="flex flex-col items-center justify-center h-48 text-center">
        <div className="w-12 h-12 rounded-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center mb-3">
          <Inbox size={20} className="text-zinc-400" />
        </div>
        <p className="text-sm font-medium text-zinc-600 dark:text-zinc-400">No tasks for {agentName}</p>
        <p className="text-xs text-zinc-400 dark:text-zinc-500 mt-1">
          Tasks dispatched to or from this agent appear here
        </p>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      {active.length > 0 && (
        <div className="space-y-2">
          <div className="flex items-center gap-2">
            <span className="text-xs font-semibold text-zinc-500 dark:text-zinc-500 uppercase tracking-wide">
              Active
            </span>
            <span className="text-xs bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400 rounded-full px-2 py-0.5">
              {active.length}
            </span>
            <span className={`w-2 h-2 rounded-full ml-1 ${connected ? "bg-green-500 animate-pulse" : "bg-zinc-400"}`} />
          </div>
          <div className="space-y-1.5">
            {active.map((t) => <TaskRow key={t.id} task={t} />)}
          </div>
        </div>
      )}
      {done.length > 0 && (
        <div className="space-y-2">
          <span className="text-xs font-semibold text-zinc-500 dark:text-zinc-500 uppercase tracking-wide">
            Completed
          </span>
          <div className="space-y-1.5">
            {done.map((t) => <TaskRow key={t.id} task={t} />)}
          </div>
        </div>
      )}
    </div>
  );
}

// ─── Main Panel ───────────────────────────────────────────────────────────────

export function TaskFlowPanel() {
  const [view, setView] = useState<"all" | "agent">("all");
  const [selectedAgent, setSelectedAgent] = useState<string>(
    process.env.NEXT_PUBLIC_PRIMARY_AGENT || KNOWN_AGENTS[0]
  );
  const [tasks, setTasks] = useState<Task[]>([]);
  const [loading, setLoading] = useState(true);
  const [connected, setConnected] = useState(false);
  const [lastUpdate, setLastUpdate] = useState<Date | null>(null);
  const esRef = useRef<EventSource | null>(null);

  const applyUpdate = useCallback((updated: Task) => {
    setTasks((prev) => {
      const idx = prev.findIndex((t) => t.id === updated.id);
      if (idx === -1) return [updated, ...prev];
      const next = [...prev];
      next[idx] = updated;
      return next;
    });
    setLastUpdate(new Date());
  }, []);

  const loadTasks = useCallback(async () => {
    try {
      const res = await fetch("/api/tasks");
      if (res.ok) {
        const data = await res.json();
        setTasks(data.tasks ?? []);
      }
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    loadTasks();

    const es = new EventSource("/api/tasks/stream");
    esRef.current = es;

    es.onopen = () => setConnected(true);
    es.onerror = () => setConnected(false);

    es.onmessage = (event) => {
      try {
        const msg = JSON.parse(event.data);
        if (msg.type === "task_snapshot") {
          setTasks(msg.tasks ?? []);
          setLastUpdate(new Date());
        } else if (msg.type === "task_update" && msg.task) {
          applyUpdate(msg.task);
        }
      } catch {
        // ignore parse errors
      }
    };

    return () => {
      es.close();
      esRef.current = null;
    };
  }, [loadTasks, applyUpdate]);

  // Group tasks by conversation_id
  const groups = new Map<string, Task[]>();
  for (const task of tasks) {
    const key = task.conversation_id ?? "__ungrouped__";
    if (!groups.has(key)) groups.set(key, []);
    groups.get(key)!.push(task);
  }

  // Sort groups: ungrouped last, others by most recent task
  const sortedGroups = Array.from(groups.entries()).sort(([keyA, tasksA], [keyB, tasksB]) => {
    if (keyA === "__ungrouped__") return 1;
    if (keyB === "__ungrouped__") return -1;
    const latestA = Math.max(...tasksA.map((t) => t.created_at));
    const latestB = Math.max(...tasksB.map((t) => t.created_at));
    return latestB - latestA;
  });

  const activeCount = tasks.filter((t) => t.status === "pending" || t.status === "in_progress").length;
  const totalCount = tasks.length;

  return (
    <div className="flex flex-col h-full overflow-hidden">
      {/* Header */}
      <div className="flex items-center justify-between px-6 py-4 border-b border-zinc-200 dark:border-zinc-800 flex-shrink-0">
        <div>
          <h1 className="text-lg font-semibold text-zinc-900 dark:text-zinc-100">Task Ledger</h1>
          <p className="text-sm text-zinc-500 dark:text-zinc-400 mt-0.5">
            {loading
              ? "Loading…"
              : `${totalCount} task${totalCount !== 1 ? "s" : ""} · ${activeCount} active`}
          </p>
        </div>
        <div className="flex items-center gap-3">
          {/* Live indicator */}
          <div className="flex items-center gap-1.5">
            <span
              className={`w-2 h-2 rounded-full ${
                connected ? "bg-green-500 animate-pulse" : "bg-zinc-400"
              }`}
            />
            <span className="text-xs text-zinc-500 dark:text-zinc-400">
              {connected ? "Live" : "Disconnected"}
            </span>
          </div>
          {lastUpdate && (
            <span className="text-xs text-zinc-400 dark:text-zinc-500">
              Updated {lastUpdate.toLocaleTimeString()}
            </span>
          )}
          <button
            onClick={loadTasks}
            className="flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 border border-zinc-200 dark:border-zinc-700 rounded-md hover:bg-zinc-50 dark:hover:bg-zinc-800 transition-colors"
          >
            <RefreshCw size={12} />
            Refresh
          </button>
        </div>
      </div>

      {/* Content */}
      <div className="flex-1 overflow-y-auto px-6 py-4">
        {loading ? (
          <div className="flex items-center justify-center h-32">
            <Loader2 size={20} className="animate-spin text-zinc-400" />
          </div>
        ) : tasks.length === 0 ? (
          <div className="flex flex-col items-center justify-center h-48 text-center">
            <div className="w-12 h-12 rounded-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center mb-3">
              <ArrowRight size={20} className="text-zinc-400" />
            </div>
            <p className="text-sm font-medium text-zinc-600 dark:text-zinc-400">No tasks yet</p>
            <p className="text-xs text-zinc-400 dark:text-zinc-500 mt-1">
              Tasks dispatched between agents will appear here
            </p>
          </div>
        ) : (
          <div className="space-y-6">
            {sortedGroups.map(([convId, groupTasks]) => (
              <ConversationGroup key={convId} convId={convId} tasks={groupTasks} />
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Helpers ─────────────────────────────────────────────────────────────────

function formatDuration(ms: number): string {
  if (ms < 1000) return "<1s";
  const secs = Math.floor(ms / 1000);
  if (secs < 60) return `${secs}s`;
  const mins = Math.floor(secs / 60);
  if (mins < 60) return `${mins}m ${secs % 60}s`;
  const hours = Math.floor(mins / 60);
  return `${hours}h ${mins % 60}m`;
}
