import { useEffect, useState, useRef, useMemo, useCallback } from "react";
import { GitBranch, Loader2, MoreHorizontal, Plus, Sparkles, Trash2, X } from "lucide-react";
import { toast } from "sonner";
import { trpc } from "@/lib/trpc";
import { StatusBadge } from "@/components/StatusBadge";
import { TaskRow, type SerializedTask } from "@/components/TaskRow";
import { PhaseContentEditor } from "@/components/editor/PhaseContentEditor";
import { ChangeSetBanner } from "@/components/ChangeSetBanner";
import { Skeleton } from "@/components/Skeleton";
import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { sortByPriorityAndQueueTime } from "@codewalk-district/shared";
import { useExecutionContext, type FlatTaskEntry } from "./ExecutionContext";

interface PhaseDetailPanelProps {
  phase: {
    id: string;
    initiativeId: string;
    name: string;
    content: string | null;
    status: string;
  };
  phases: Array<{
    id: string;
    name: string;
    status: string;
  }>;
  displayIndex: number;
  allDisplayIndices: Map<string, number>;
  initiativeId: string;
  tasks: SerializedTask[];
  tasksLoading: boolean;
  onDelete?: () => void;
  branch?: string | null;
  detailAgent: {
    id: string;
    status: string;
    createdAt: string | Date;
  } | null;
}

export function PhaseDetailPanel({
  phase,
  phases,
  displayIndex,
  allDisplayIndices,
  initiativeId,
  tasks,
  tasksLoading,
  onDelete,
  branch,
  detailAgent,
}: PhaseDetailPanelProps) {
  const { setSelectedTaskId, handleTaskCounts, handleRegisterTasks } =
    useExecutionContext();
  const [isEditingTitle, setIsEditingTitle] = useState(false);
  const [editName, setEditName] = useState(phase.name);
  const inputRef = useRef<HTMLInputElement>(null);

  const updatePhase = trpc.updatePhase.useMutation();

  function startEditing() {
    setEditName(phase.name);
    setIsEditingTitle(true);
    setTimeout(() => inputRef.current?.select(), 0);
  }

  function saveTitle() {
    const trimmed = editName.trim();
    if (!trimmed || trimmed === phase.name) {
      setEditName(phase.name);
      setIsEditingTitle(false);
      return;
    }
    updatePhase.mutate(
      { id: phase.id, name: trimmed },
      {
        onSuccess: () => {
          setIsEditingTitle(false);
          toast.success("Phase renamed");
        },
        onError: () => {
          setEditName(phase.name);
          setIsEditingTitle(false);
          toast.error("Failed to rename phase");
        },
      },
    );
  }

  function cancelEditing() {
    setEditName(phase.name);
    setIsEditingTitle(false);
  }

  const addDependency = trpc.createPhaseDependency.useMutation({
    onSuccess: () => toast.success("Dependency added"),
    onError: () => toast.error("Failed to add dependency"),
  });

  const removeDependency = trpc.removePhaseDependency.useMutation({
    onSuccess: () => toast.success("Dependency removed"),
    onError: () => toast.error("Failed to remove dependency"),
  });

  const depsQuery = trpc.getPhaseDependencies.useQuery({ phaseId: phase.id });
  const dependencyIds = depsQuery.data?.dependencies ?? [];

  // Resolve dependency IDs to phase objects
  const resolvedDeps = dependencyIds
    .map((depId) => phases.find((p) => p.id === depId))
    .filter(Boolean) as Array<{ id: string; name: string; status: string }>;

  // Phases available to add as dependencies (exclude self + already-added)
  const availableDeps = useMemo(
    () => phases.filter((p) => p.id !== phase.id && !dependencyIds.includes(p.id)),
    [phases, phase.id, dependencyIds],
  );

  // Propagate task counts and entries to ExecutionContext
  useEffect(() => {
    const complete = tasks.filter((t) => t.status === "completed").length;
    handleTaskCounts(phase.id, { complete, total: tasks.length });

    const entries: FlatTaskEntry[] = tasks.map((task) => ({
      task,
      phaseName: `Phase ${displayIndex}: ${phase.name}`,
      agentName: null,
      blockedBy: [],
      dependents: [],
    }));
    handleRegisterTasks(phase.id, entries);
  }, [tasks, phase.id, displayIndex, phase.name, handleTaskCounts, handleRegisterTasks]);

  // --- Change sets for detail agent ---
  const changeSetsQuery = trpc.listChangeSets.useQuery(
    { agentId: detailAgent?.id ?? "" },
    { enabled: !!detailAgent && detailAgent.status === "idle" },
  );
  const latestChangeSet = useMemo(
    () => (changeSetsQuery.data ?? []).find((cs) => cs.status === "applied") ?? null,
    [changeSetsQuery.data],
  );

  // --- Detail spawn ---
  const detailMutation = trpc.spawnArchitectDetail.useMutation();

  const handleDetail = useCallback(() => {
    detailMutation.mutate({ phaseId: phase.id });
  }, [phase.id, detailMutation]);

  // --- Dismiss handler for detail agent ---
  const dismissMutation = trpc.dismissAgent.useMutation();
  const handleDismissDetail = useCallback(() => {
    if (!detailAgent) return;
    dismissMutation.mutate({ id: detailAgent.id });
  }, [detailAgent, dismissMutation]);

  // Compute phase branch name if initiative has a merge target
  const phaseBranch = branch
    ? `${branch}-phase-${phase.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}`
    : null;

  const isPendingReview = phase.status === "pending_review";

  const sortedTasks = sortByPriorityAndQueueTime(tasks);
  const hasTasks = tasks.length > 0;
  const isDetailRunning =
    detailAgent?.status === "running" ||
    detailAgent?.status === "waiting_for_input";
  const showDetailButton =
    !detailAgent && !hasTasks;
  const showChangeSet =
    detailAgent?.status === "idle" && !!latestChangeSet;

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-center gap-3">
        {isEditingTitle ? (
          <div className="flex items-center gap-1">
            <span className="text-lg font-semibold">Phase {displayIndex}:</span>
            <input
              ref={inputRef}
              className="border-b border-border bg-transparent text-lg font-semibold outline-none focus:border-primary"
              value={editName}
              onChange={(e) => setEditName(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === "Enter") saveTitle();
                if (e.key === "Escape") cancelEditing();
              }}
              onBlur={saveTitle}
            />
          </div>
        ) : (
          <h3
            className="cursor-pointer text-lg font-semibold hover:text-primary"
            onClick={startEditing}
            title="Click to rename"
          >
            Phase {displayIndex}: {phase.name}
          </h3>
        )}
        <StatusBadge status={phase.status} />
        {phaseBranch && ["in_progress", "completed", "pending_review"].includes(phase.status) && (
          <span className="inline-flex items-center gap-1 rounded-md border border-border px-2 py-0.5 text-[10px] font-mono text-muted-foreground">
            <GitBranch className="h-3 w-3" />
            {phaseBranch}
          </span>
        )}

        {/* Detail button in header */}
        {showDetailButton && (
          <Button
            variant="outline"
            size="sm"
            onClick={handleDetail}
            disabled={detailMutation.isPending}
            className="gap-1.5"
          >
            <Sparkles className="h-3.5 w-3.5" />
            {detailMutation.isPending ? "Starting..." : "Detail Tasks"}
          </Button>
        )}

        {/* Running indicator in header */}
        {isDetailRunning && (
          <div className="flex items-center gap-1.5 text-xs text-muted-foreground">
            <Loader2 className="h-3 w-3 animate-spin" />
            Detailing...
          </div>
        )}

        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="ghost" size="icon" className="ml-auto h-7 w-7">
              <MoreHorizontal className="h-4 w-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            <DropdownMenuItem
              className="text-destructive"
              onClick={() => {
                if (window.confirm(`Delete "${phase.name}"? All tasks in this phase will also be deleted.`)) {
                  onDelete?.();
                }
              }}
            >
              <Trash2 className="mr-2 h-4 w-4" />
              Delete Phase
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </div>

      {/* Pending review banner */}
      {isPendingReview && (
        <div className="rounded-md border border-amber-200 bg-amber-50 px-4 py-3 dark:border-amber-800 dark:bg-amber-950">
          <p className="text-sm font-medium text-amber-800 dark:text-amber-200">
            This phase is pending review. Switch to the{" "}
            <span className="font-semibold">Review</span> tab to view the diff and approve.
          </p>
        </div>
      )}

      {/* Tiptap Editor */}
      <PhaseContentEditor phaseId={phase.id} initiativeId={initiativeId} />

      {/* Dependencies */}
      <div>
        <div className="mb-2 flex items-center gap-2">
          <h4 className="text-sm font-medium text-muted-foreground">
            Dependencies
          </h4>
          {availableDeps.length > 0 && (
            <DropdownMenu>
              <DropdownMenuTrigger asChild>
                <Button variant="ghost" size="icon" className="h-5 w-5">
                  <Plus className="h-3 w-3" />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent align="start">
                {availableDeps.map((p) => (
                  <DropdownMenuItem
                    key={p.id}
                    onClick={() =>
                      addDependency.mutate({
                        phaseId: phase.id,
                        dependsOnPhaseId: p.id,
                      })
                    }
                  >
                    Phase {allDisplayIndices.get(p.id) ?? "?"}: {p.name}
                  </DropdownMenuItem>
                ))}
              </DropdownMenuContent>
            </DropdownMenu>
          )}
        </div>
        {resolvedDeps.length === 0 ? (
          <p className="text-xs text-muted-foreground">No dependencies</p>
        ) : (
          <div className="space-y-1">
            {resolvedDeps.map((dep) => (
              <div
                key={dep.id}
                className="flex items-center gap-2 text-sm"
              >
                <span
                  className={
                    dep.status === "completed"
                      ? "text-green-600"
                      : "text-muted-foreground"
                  }
                >
                  {dep.status === "completed" ? "\u25CF" : "\u25CB"}
                </span>
                <span>
                  Phase {allDisplayIndices.get(dep.id) ?? "?"}: {dep.name}
                </span>
                <StatusBadge status={dep.status} className="text-[10px]" />
                <button
                  className="ml-1 text-muted-foreground hover:text-destructive"
                  onClick={() =>
                    removeDependency.mutate({
                      phaseId: phase.id,
                      dependsOnPhaseId: dep.id,
                    })
                  }
                  title="Remove dependency"
                >
                  <X className="h-3 w-3" />
                </button>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* Detail change set */}
      {showChangeSet && (
        <ChangeSetBanner
          changeSet={latestChangeSet!}
          onDismiss={handleDismissDetail}
        />
      )}

      {/* Tasks */}
      <div>
        <h4 className="mb-2 text-sm font-medium text-muted-foreground">
          Tasks ({tasks.filter((t) => t.status === "completed").length}/
          {tasks.length})
        </h4>
        {tasksLoading ? (
          <div className="space-y-1">
            {Array.from({ length: 3 }).map((_, i) => (
              <Skeleton key={i} className="h-8 w-full" />
            ))}
          </div>
        ) : sortedTasks.length === 0 ? (
          <p className="text-sm text-muted-foreground">No tasks yet</p>
        ) : (
          <div>
            {sortedTasks.map((task, idx) => (
              <TaskRow
                key={task.id}
                task={task}
                agentName={null}
                blockedBy={[]}
                isLast={idx === sortedTasks.length - 1}
                onClick={() => setSelectedTaskId(task.id)}
              />
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

export function PhaseDetailEmpty() {
  return (
    <div className="flex h-full items-center justify-center text-muted-foreground">
      <p>Select a phase to view details</p>
    </div>
  );
}
