import { useState, useMemo, useRef, useEffect } from "react";
import { toast } from "sonner";
import { trpc } from "@/lib/trpc";
import { topologicalSortPhases, type DependencyEdge } from "@codewalk-district/shared";
import {
  ExecutionProvider,
  PhaseActions,
  PlanSection,
  type PhaseData,
} from "@/components/execution";
import { PhaseGraph } from "@/components/execution/PhaseGraph";
import {
  PhaseDetailPanel,
  PhaseDetailEmpty,
} from "@/components/execution/PhaseDetailPanel";
import { TaskSlideOver } from "@/components/execution/TaskSlideOver";
import { ChatSlideOver, type ChatTarget } from "@/components/chat/ChatSlideOver";
import { Skeleton } from "@/components/Skeleton";

interface ExecutionTabProps {
  initiativeId: string;
  phases: PhaseData[];
  phasesLoading: boolean;
  phasesLoaded: boolean;
  dependencyEdges: DependencyEdge[];
  branch?: string | null;
}

export function ExecutionTab({
  initiativeId,
  phases,
  phasesLoading,
  phasesLoaded,
  dependencyEdges,
  branch,
}: ExecutionTabProps) {
  // Topological sort
  const sortedPhases = useMemo(
    () => topologicalSortPhases(phases, dependencyEdges),
    [phases, dependencyEdges],
  );

  // Detail agent tracking: map phaseId → most recent active detail agent
  const agentsQuery = trpc.listAgents.useQuery();
  const allAgents = agentsQuery.data ?? [];

  // Default to first incomplete phase
  const firstIncompleteId = useMemo(() => {
    const found = sortedPhases.find((p) => p.status !== "completed");
    return found?.id ?? sortedPhases[0]?.id ?? null;
  }, [sortedPhases]);

  const [selectedPhaseId, setSelectedPhaseId] = useState<string | null>(null);
  const [isAddingPhase, setIsAddingPhase] = useState(false);
  const [chatTarget, setChatTarget] = useState<ChatTarget | null>(null);

  const deletePhase = trpc.deletePhase.useMutation({
    onSuccess: () => {
      setSelectedPhaseId(null);
      toast.success("Phase deleted");
    },
    onError: () => {
      toast.error("Failed to delete phase");
    },
  });

  const createPhase = trpc.createPhase.useMutation({
    onSuccess: () => {
      setIsAddingPhase(false);
      toast.success("Phase created");
    },
    onError: () => {
      toast.error("Failed to create phase");
    },
  });

  function handleStartAdd() {
    setIsAddingPhase(true);
  }

  function handleConfirmAdd(name: string) {
    const trimmed = name.trim();
    if (!trimmed) {
      setIsAddingPhase(false);
      return;
    }
    createPhase.mutate({ initiativeId, name: trimmed });
  }

  function handleCancelAdd() {
    setIsAddingPhase(false);
  }

  // Resolve actual selected ID (use default if none explicitly selected)
  const activePhaseId = selectedPhaseId ?? firstIncompleteId;
  const activePhase = sortedPhases.find((p) => p.id === activePhaseId) ?? null;
  const activeDisplayIndex = activePhase
    ? sortedPhases.indexOf(activePhase) + 1
    : 0;

  // Fetch all tasks for the initiative in one query (for sidebar counts)
  const allTasksQuery = trpc.listInitiativeTasks.useQuery(
    { initiativeId },
    { enabled: phasesLoaded && sortedPhases.length > 0 },
  );
  const allTasks = allTasksQuery.data ?? [];

  // Filter out detail tasks for display (counts/grouping), keep allTasks unfiltered for detailAgentByPhase
  const displayTasks = useMemo(
    () => allTasks.filter((t) => t.category !== "detail"),
    [allTasks],
  );

  // Group tasks and counts by phaseId
  const { taskCountsByPhase, tasksByPhase } = useMemo(() => {
    const counts: Record<string, { complete: number; total: number }> = {};
    const grouped: Record<string, typeof displayTasks> = {};
    for (const task of displayTasks) {
      const pid = task.phaseId;
      if (!pid) continue;
      if (!counts[pid]) counts[pid] = { complete: 0, total: 0 };
      counts[pid].total++;
      if (task.status === "completed") counts[pid].complete++;
      if (!grouped[pid]) grouped[pid] = [];
      grouped[pid].push(task);
    }
    return { taskCountsByPhase: counts, tasksByPhase: grouped };
  }, [displayTasks]);

  // Map phaseId → most recent active detail agent
  const detailAgentByPhase = useMemo(() => {
    const map = new Map<string, (typeof allAgents)[number]>();
    // Build taskId → phaseId lookup from allTasks
    const taskPhaseMap = new Map<string, string>();
    for (const t of allTasks) {
      if (t.phaseId) taskPhaseMap.set(t.id, t.phaseId);
    }
    const candidates = allAgents.filter(
      (a) =>
        a.mode === "detail" &&
        a.initiativeId === initiativeId &&
        ["running", "waiting_for_input", "idle"].includes(a.status) &&
        !a.userDismissedAt,
    );
    for (const agent of candidates) {
      const phaseId = taskPhaseMap.get(agent.taskId ?? "");
      if (!phaseId) continue;
      const existing = map.get(phaseId);
      if (
        !existing ||
        new Date(agent.createdAt).getTime() >
          new Date(existing.createdAt).getTime()
      ) {
        map.set(phaseId, agent);
      }
    }
    return map;
  }, [allAgents, allTasks, initiativeId]);

  // Phase IDs that have zero tasks (eligible for detailing)
  const phasesWithoutTasks = useMemo(
    () =>
      sortedPhases
        .filter((p) => !taskCountsByPhase[p.id]?.total)
        .map((p) => p.id),
    [sortedPhases, taskCountsByPhase],
  );

  // Build display indices map for PhaseDetailPanel
  const allDisplayIndices = useMemo(
    () => new Map(sortedPhases.map((p, i) => [p.id, i + 1])),
    [sortedPhases],
  );

  // No phases yet and not adding — show plan section
  if (phasesLoaded && sortedPhases.length === 0 && !isAddingPhase) {
    return (
      <ExecutionProvider>
        <PlanSection
          initiativeId={initiativeId}
          phasesLoaded={phasesLoaded}
          phases={sortedPhases}
          onAddPhase={handleStartAdd}
        />
        <TaskSlideOver onOpenChat={(target) => setChatTarget(target)} />
        <ChatSlideOver
          target={chatTarget}
          initiativeId={initiativeId}
          onClose={() => setChatTarget(null)}
        />
      </ExecutionProvider>
    );
  }

  const nextNumber = sortedPhases.length + 1;

  return (
    <ExecutionProvider>
      <div className="grid grid-cols-1 gap-6 lg:grid-cols-[260px_1fr]">
        {/* Left: Phase sidebar */}
        <div className="space-y-0">
          <div className="flex items-center justify-between border-b border-border pb-3">
            <h2 className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
              Phases
            </h2>
            <PhaseActions
              initiativeId={initiativeId}
              phases={sortedPhases}
              onAddPhase={handleStartAdd}
              phasesWithoutTasks={phasesWithoutTasks}
              detailAgentByPhase={detailAgentByPhase}
            />
          </div>

          {phasesLoading ? (
            <div className="space-y-1 pt-2">
              {Array.from({ length: 3 }).map((_, i) => (
                <Skeleton key={i} className="h-14 w-full" />
              ))}
            </div>
          ) : (
            <div className="pt-2">
              <PhaseGraph
                phases={sortedPhases}
                dependencyEdges={dependencyEdges}
                taskCountsByPhase={taskCountsByPhase}
                activePhaseId={activePhaseId}
                onSelectPhase={setSelectedPhaseId}
                detailAgentByPhase={detailAgentByPhase}
                allDisplayIndices={allDisplayIndices}
              />
              {isAddingPhase && (
                <NewPhaseEntry
                  number={nextNumber}
                  onConfirm={handleConfirmAdd}
                  onCancel={handleCancelAdd}
                />
              )}
            </div>
          )}
        </div>

        {/* Right: Phase detail */}
        <div className="min-h-[400px]">
          {activePhase ? (
            <PhaseDetailPanel
              key={activePhase.id}
              phase={activePhase}
              phases={sortedPhases}
              displayIndex={activeDisplayIndex}
              allDisplayIndices={allDisplayIndices}
              initiativeId={initiativeId}
              tasks={tasksByPhase[activePhase.id] ?? []}
              tasksLoading={allTasksQuery.isLoading}
              onDelete={() => deletePhase.mutate({ id: activePhase.id })}
              detailAgent={detailAgentByPhase.get(activePhase.id) ?? null}
              branch={branch}
              onOpenChat={(target) => setChatTarget(target)}
            />
          ) : (
            <PhaseDetailEmpty />
          )}
        </div>
      </div>
      <TaskSlideOver onOpenChat={(target) => setChatTarget(target)} />
      <ChatSlideOver
        target={chatTarget}
        initiativeId={initiativeId}
        onClose={() => setChatTarget(null)}
      />
    </ExecutionProvider>
  );
}

/** Editable placeholder entry that looks like a PhaseSidebarItem */
function NewPhaseEntry({
  number,
  onConfirm,
  onCancel,
}: {
  number: number;
  onConfirm: (name: string) => void;
  onCancel: () => void;
}) {
  const [name, setName] = useState("");
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    inputRef.current?.focus();
  }, []);

  function handleBlur() {
    const trimmed = name.trim();
    if (trimmed) {
      onConfirm(trimmed);
    } else {
      onCancel();
    }
  }

  return (
    <div className="flex w-full flex-col gap-0.5 rounded-md border-l-2 border-primary bg-accent px-3 py-2">
      <div className="flex items-center gap-1">
        <span className="shrink-0 text-sm font-medium">Phase {number}:</span>
        <input
          ref={inputRef}
          className="min-w-0 flex-1 bg-transparent text-sm font-medium outline-none placeholder:text-muted-foreground"
          placeholder="Phase name"
          value={name}
          onChange={(e) => setName(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter") {
              e.preventDefault();
              const trimmed = name.trim();
              if (trimmed) onConfirm(trimmed);
              else onCancel();
            }
            if (e.key === "Escape") onCancel();
          }}
          onBlur={handleBlur}
        />
      </div>
      <div className="text-xs text-muted-foreground">0/0 tasks</div>
    </div>
  );
}
