import { useEffect, useMemo } from "react";
import { CheckCircle2, CircleDashed, Loader2, Play } from "lucide-react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { trpc } from "@/lib/trpc";
import {
  groupPhasesByDependencyLevel,
  type DependencyEdge,
} from "@codewalk-district/shared";
import {
  ExecutionProvider,
  useExecutionContext,
  PlanSection,
  type PhaseData,
  type FlatTaskEntry,
} from "@/components/execution";
import { TaskSlideOver } from "@/components/execution/TaskSlideOver";
import type { SerializedTask } from "@/components/TaskRow";
import { PipelineGraph } from "./PipelineGraph";
import type { DetailAgentInfo } from "./PipelinePhaseGroup";

interface PipelineTabProps {
  initiativeId: string;
  phases: PhaseData[];
  phasesLoading: boolean;
}

export function PipelineTab({ initiativeId, phases, phasesLoading }: PipelineTabProps) {
  return (
    <ExecutionProvider>
      <PipelineTabInner
        initiativeId={initiativeId}
        phases={phases}
        phasesLoading={phasesLoading}
      />
      <TaskSlideOver />
    </ExecutionProvider>
  );
}

function PipelineTabInner({ initiativeId, phases, phasesLoading }: PipelineTabProps) {
  const { handleRegisterTasks, handleTaskCounts } = useExecutionContext();

  // Fetch all tasks for the initiative
  const tasksQuery = trpc.listInitiativeTasks.useQuery(
    { initiativeId },
    { enabled: phases.length > 0 },
  );
  const allTasks = (tasksQuery.data ?? []) as SerializedTask[];

  // Fetch dependency edges (phase-level)
  const depsQuery = trpc.listInitiativePhaseDependencies.useQuery(
    { initiativeId },
    { enabled: phases.length > 0 },
  );
  const dependencyEdges: DependencyEdge[] = depsQuery.data ?? [];

  // Fetch task-level dependency edges
  const taskDepsQuery = trpc.listInitiativeTaskDependencies.useQuery(
    { initiativeId },
    { enabled: phases.length > 0 },
  );
  const taskDepsRaw = taskDepsQuery.data ?? [];

  // Fetch agents for detail agent tracking
  const agentsQuery = trpc.listAgents.useQuery();
  const allAgents = agentsQuery.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 display tasks by phaseId
  const tasksByPhase = useMemo(() => {
    const map: Record<string, SerializedTask[]> = {};
    for (const task of displayTasks) {
      if (task.phaseId) {
        if (!map[task.phaseId]) map[task.phaseId] = [];
        map[task.phaseId].push(task);
      }
    }
    return map;
  }, [displayTasks]);

  // Group task dependency edges by phaseId
  const taskDepsByPhase = useMemo(() => {
    const taskPhaseMap = new Map<string, string>();
    for (const t of allTasks) {
      if (t.phaseId) taskPhaseMap.set(t.id, t.phaseId);
    }
    const map: Record<string, Array<{ taskId: string; dependsOn: string[] }>> = {};
    for (const edge of taskDepsRaw) {
      const phaseId = taskPhaseMap.get(edge.taskId);
      if (phaseId) {
        if (!map[phaseId]) map[phaseId] = [];
        map[phaseId].push(edge);
      }
    }
    return map;
  }, [allTasks, taskDepsRaw]);

  // Map phaseId → most recent active detail agent
  const detailAgentByPhase = useMemo(() => {
    const map = new Map<string, DetailAgentInfo>();
    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, { status: agent.status, createdAt: agent.createdAt });
      }
    }
    return map;
  }, [allAgents, allTasks, initiativeId]);

  // Compute pipeline columns
  const columns = useMemo(
    () => groupPhasesByDependencyLevel(phases, dependencyEdges),
    [phases, dependencyEdges],
  );

  // Count phases that can be executed: approved OR pending with non-detail tasks
  const { actionableCount, pendingPhaseIds } = useMemo(() => {
    const pending: string[] = [];
    let count = 0;
    for (const p of phases) {
      if (p.status === "approved") {
        count++;
      } else if (p.status === "pending") {
        const phaseTasks = tasksByPhase[p.id] ?? [];
        if (phaseTasks.length > 0) {
          count++;
          pending.push(p.id);
        }
      }
    }
    return { actionableCount: count, pendingPhaseIds: pending };
  }, [phases, tasksByPhase]);

  const approvePhase = trpc.approvePhase.useMutation();
  const queueAll = trpc.queueAllPhases.useMutation();

  // Register tasks with ExecutionContext for TaskSlideOver
  useEffect(() => {
    for (const phase of phases) {
      const phaseTasks = tasksByPhase[phase.id] ?? [];
      const entries: FlatTaskEntry[] = phaseTasks.map((task) => ({
        task,
        phaseName: phase.name,
        agentName: null,
        blockedBy: [],
        dependents: [],
      }));
      handleRegisterTasks(phase.id, entries);
      handleTaskCounts(phase.id, {
        complete: phaseTasks.filter((t) => t.status === "completed").length,
        total: phaseTasks.length,
      });
    }
  }, [phases, tasksByPhase, handleRegisterTasks, handleTaskCounts]);

  // Empty state
  if (!phasesLoading && phases.length === 0) {
    return (
      <PlanSection
        initiativeId={initiativeId}
        phasesLoaded={!phasesLoading}
        phases={phases}
      />
    );
  }

  // Loading
  if (phasesLoading || tasksQuery.isLoading) {
    return (
      <div className="flex items-center justify-center py-12 text-muted-foreground">
        <Loader2 className="mr-2 h-4 w-4 animate-spin" />
        Loading pipeline...
      </div>
    );
  }

  const totalTasks = displayTasks.length;
  const completedTasks = displayTasks.filter((t) => t.status === "completed").length;
  const runningPhases = phases.filter((p) => p.status === "in_progress").length;
  const completedPhases = phases.filter((p) => p.status === "completed").length;
  const isMutating = approvePhase.isPending || queueAll.isPending;

  return (
    <div className="space-y-3">
      {/* Pipeline summary bar */}
      <div className="flex items-center gap-3 rounded-lg border border-border bg-card px-4 py-2.5">
        {/* Stats */}
        <div className="flex min-w-0 flex-1 items-center gap-4 text-xs text-muted-foreground">
          <span className="tabular-nums">
            <span className="font-medium text-foreground">{phases.length}</span> phase{phases.length === 1 ? "" : "s"}
          </span>
          <span className="tabular-nums">
            <span className="font-medium text-foreground">{totalTasks}</span> task{totalTasks === 1 ? "" : "s"}
          </span>
          {runningPhases > 0 && (
            <span className="flex items-center gap-1 text-status-active-fg">
              <Loader2 className="h-3 w-3 animate-spin" />
              {runningPhases} running
            </span>
          )}
          {completedPhases > 0 && (
            <span className={cn(
              "flex items-center gap-1",
              completedPhases === phases.length ? "text-status-success-fg" : "text-muted-foreground",
            )}>
              <CheckCircle2 className="h-3 w-3" />
              {completedPhases}/{phases.length} done
            </span>
          )}
          {completedPhases === 0 && runningPhases === 0 && actionableCount > 0 && (
            <span className="flex items-center gap-1">
              <CircleDashed className="h-3 w-3" />
              Ready
            </span>
          )}
        </div>

        {/* Execute action */}
        {actionableCount > 0 && (
          <Button
            size="sm"
            onClick={async () => {
              for (const phaseId of pendingPhaseIds) {
                await approvePhase.mutateAsync({ phaseId });
              }
              queueAll.mutate({ initiativeId });
            }}
            disabled={isMutating}
          >
            {isMutating ? (
              <Loader2 className="mr-1.5 h-3.5 w-3.5 animate-spin" />
            ) : (
              <Play className="mr-1.5 h-3.5 w-3.5" />
            )}
            Execute {actionableCount === 1 ? "1 phase" : `all ${actionableCount}`}
          </Button>
        )}
      </div>

      <PipelineGraph
        columns={columns}
        tasksByPhase={tasksByPhase}
        taskDepsByPhase={taskDepsByPhase}
        dependencyEdges={dependencyEdges}
        detailAgentByPhase={detailAgentByPhase}
      />
    </div>
  );
}
