import { useEffect, useState, useRef, useMemo, useCallback } from "react";
import { GitBranch, Loader2, MessageCircle, MoreHorizontal, Plus, Sparkles, Trash2, X } from "lucide-react";
import type { ChatTarget } from "@/components/chat/ChatSlideOver";
import { toast } from "sonner";
import { trpc } from "@/lib/trpc";
import { StatusBadge } from "@/components/StatusBadge";
import { mapEntityStatus } from "@/components/StatusDot";
import { PhaseNumberBadge } from "@/components/DependencyChip";
import { type SerializedTask } from "@/components/TaskRow";
import { TaskGraph } from "./TaskGraph";
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 { useExecutionContext, type FlatTaskEntry } from "./ExecutionContext";
import { cn } from "@/lib/utils";

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;
  onOpenChat?: (target: ChatTarget) => void;
  detailAgent: {
    id: string;
    status: string;
    createdAt: string | Date;
  } | null;
}

export function PhaseDetailPanel({
  phase,
  phases,
  displayIndex,
  allDisplayIndices,
  initiativeId,
  tasks,
  tasksLoading,
  onDelete,
  branch,
  onOpenChat,
  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();
  const utils = trpc.useUtils();
  const deleteTask = trpc.deleteTask.useMutation({
    onSuccess: () => {
      utils.listInitiativeTasks.invalidate({ initiativeId });
      toast.success("Task deleted");
    },
    onError: () => toast.error("Failed to delete task"),
  });

  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 ?? [];

  // Task-level dependencies
  const taskDepsQuery = trpc.listPhaseTaskDependencies.useQuery({ phaseId: phase.id });
  const { taskDepsMap, blockedByCountMap } = useMemo(() => {
    const map = new Map<string, Array<{ name: string; status: string }>>();
    const countMap = new Map<string, number>();
    const edges = taskDepsQuery.data ?? [];
    for (const edge of edges) {
      const blockers = edge.dependsOn
        .map((depId) => {
          const t = tasks.find((tk) => tk.id === depId);
          return t ? { name: t.name, status: t.status } : null;
        })
        .filter(Boolean) as Array<{ name: string; status: string }>;
      if (blockers.length > 0) map.set(edge.taskId, blockers);
      const incomplete = blockers.filter((b) => b.status !== "completed").length;
      if (incomplete > 0) countMap.set(edge.taskId, incomplete);
    }
    return { taskDepsMap: map, blockedByCountMap: countMap };
  }, [taskDepsQuery.data, tasks]);

  // 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: taskDepsMap.get(task.id) ?? [],
      dependents: [],
    }));
    handleRegisterTasks(phase.id, entries);
  }, [tasks, phase.id, displayIndex, phase.name, handleTaskCounts, handleRegisterTasks, taskDepsMap]);

  // --- 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 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>
        )}

        {/* Chat button */}
        <Button
          variant="outline"
          size="sm"
          onClick={() => onOpenChat?.({ type: 'phase', id: phase.id, name: phase.name })}
          className="gap-1.5"
        >
          <MessageCircle className="h-3.5 w-3.5" />
          Chat
        </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-status-warning-border bg-status-warning-bg px-4 py-3">
          <p className="text-sm font-medium text-status-warning-fg">
            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>
          {resolvedDeps.length > 0 && (
            <span className="text-xs text-muted-foreground">
              {resolvedDeps.filter((d) => d.status === "completed").length}/{resolvedDeps.length} resolved
            </span>
          )}
          {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="overflow-hidden rounded-md border border-border">
            {resolvedDeps.map((dep, idx) => {
              const variant = mapEntityStatus(dep.status);
              const borderColor = {
                active:  "border-l-status-active-dot",
                success: "border-l-status-success-dot",
                warning: "border-l-status-warning-dot",
                error:   "border-l-status-error-dot",
                neutral: "border-l-border",
                urgent:  "border-l-status-urgent-dot",
              }[variant];

              return (
                <div
                  key={dep.id}
                  className={cn(
                    "group flex items-center gap-2.5 border-l-[3px] px-3 py-2 text-sm transition-colors hover:bg-accent/30",
                    borderColor,
                    idx < resolvedDeps.length - 1 && "border-b border-b-border/50",
                  )}
                >
                  <PhaseNumberBadge
                    index={allDisplayIndices.get(dep.id) ?? 0}
                    status={dep.status}
                  />
                  <span className="min-w-0 flex-1 truncate">
                    {dep.name}
                  </span>
                  <StatusBadge status={dep.status} className="shrink-0 text-[10px]" />
                  <button
                    className="shrink-0 rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:text-destructive group-hover:opacity-100"
                    onClick={() =>
                      removeDependency.mutate({
                        phaseId: phase.id,
                        dependsOnPhaseId: dep.id,
                      })
                    }
                    title="Remove dependency (Shift+click to skip confirmation)"
                  >
                    <X className="h-3.5 w-3.5" />
                  </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>
        ) : tasks.length === 0 ? (
          <p className="text-sm text-muted-foreground">No tasks yet</p>
        ) : (
          <TaskGraph
            tasks={tasks}
            taskDepsRaw={taskDepsQuery.data ?? []}
            blockedByCountMap={blockedByCountMap}
            agentNameMap={new Map()}
            onClickTask={setSelectedTaskId}
            onDeleteTask={(id) => deleteTask.mutate({ id })}
          />
        )}
      </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>
  );
}
