import { useCallback, useEffect, useRef, useMemo } from "react";
import { motion, AnimatePresence } from "motion/react";
import { X, Trash2, MessageCircle, RotateCw } from "lucide-react";
import type { ChatTarget } from "@/components/chat/ChatSlideOver";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { StatusBadge } from "@/components/StatusBadge";
import { StatusDot } from "@/components/StatusDot";
import { TiptapEditor } from "@/components/editor/TiptapEditor";
import { getCategoryConfig } from "@/lib/category";
import { markdownToTiptapJson } from "@/lib/markdown-to-tiptap";
import { useExecutionContext } from "./ExecutionContext";
import { trpc } from "@/lib/trpc";
import { cn } from "@/lib/utils";

interface TaskSlideOverProps {
  onOpenChat?: (target: ChatTarget) => void;
}

export function TaskSlideOver({ onOpenChat }: TaskSlideOverProps) {
  const { selectedEntry, setSelectedTaskId } = useExecutionContext();
  const queueTaskMutation = trpc.queueTask.useMutation();
  const retryBlockedTaskMutation = trpc.retryBlockedTask.useMutation();
  const deleteTaskMutation = trpc.deleteTask.useMutation();
  const updateTaskMutation = trpc.updateTask.useMutation();

  const close = useCallback(() => setSelectedTaskId(null), [setSelectedTaskId]);

  // Escape key closes
  useEffect(() => {
    if (!selectedEntry) return;
    function onKeyDown(e: KeyboardEvent) {
      if (e.key === "Escape") close();
    }
    document.addEventListener("keydown", onKeyDown);
    return () => document.removeEventListener("keydown", onKeyDown);
  }, [selectedEntry, close]);

  // Debounced description save
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const pendingRef = useRef<{ id: string; description: string } | null>(null);

  const flushDescription = useCallback(() => {
    if (timerRef.current) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
    if (pendingRef.current) {
      const data = pendingRef.current;
      pendingRef.current = null;
      updateTaskMutation.mutate(data);
    }
  }, [updateTaskMutation]);

  const handleDescriptionUpdate = useCallback(
    (json: string) => {
      const task = selectedEntry?.task;
      if (!task) return;
      pendingRef.current = { id: task.id, description: json };
      if (timerRef.current) clearTimeout(timerRef.current);
      timerRef.current = setTimeout(flushDescription, 1000);
    },
    [selectedEntry?.task, flushDescription],
  );

  // Flush on close / unmount
  useEffect(() => {
    return () => {
      if (timerRef.current) clearTimeout(timerRef.current);
      if (pendingRef.current) {
        const data = pendingRef.current;
        pendingRef.current = null;
        updateTaskMutation.mutate(data);
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const task = selectedEntry?.task ?? null;
  const dependencies = selectedEntry?.blockedBy ?? [];
  const dependents = selectedEntry?.dependents ?? [];
  const allDepsComplete =
    dependencies.length === 0 ||
    dependencies.every((d) => d.status === "completed");
  const canQueue = task !== null && task.status === "pending" && allDepsComplete;

  // Convert existing markdown description to tiptap JSON for the editor.
  // If it's already valid tiptap JSON, use as-is.
  const editorContent = useMemo(() => {
    if (!task?.description) return null;
    try {
      const parsed = JSON.parse(task.description);
      if (parsed?.type === "doc") return task.description;
    } catch {
      // Not JSON — treat as markdown
    }
    try {
      return JSON.stringify(markdownToTiptapJson(task.description));
    } catch {
      return null;
    }
  }, [task?.description]);

  return (
    <AnimatePresence>
      {selectedEntry && task && (
        <>
          {/* Backdrop */}
          <motion.div
            className="fixed inset-0 z-40 bg-background/60 backdrop-blur-[2px]"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
            onClick={() => {
              flushDescription();
              close();
            }}
          />

          {/* Panel */}
          <motion.div
            className="fixed inset-y-0 right-0 z-50 flex w-full max-w-2xl flex-col border-l border-border bg-background shadow-xl"
            initial={{ x: "100%" }}
            animate={{ x: 0 }}
            exit={{ x: "100%" }}
            transition={{ duration: 0.25, ease: [0, 0, 0.2, 1] }}
          >
            {/* Header */}
            <div className="flex items-start gap-3 border-b border-border px-5 py-4">
              <div className="min-w-0 flex-1">
                <h3 className="text-base font-semibold leading-snug">
                  {task.name}
                </h3>
                <p className="mt-0.5 text-xs text-muted-foreground">
                  {selectedEntry.phaseName}
                </p>
              </div>
              {updateTaskMutation.isPending && (
                <span className="shrink-0 text-[10px] text-muted-foreground">
                  Saving...
                </span>
              )}
              <button
                className="shrink-0 rounded-md p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
                onClick={() => {
                  flushDescription();
                  close();
                }}
              >
                <X className="h-4 w-4" />
              </button>
            </div>

            {/* Content */}
            <div className="flex-1 overflow-y-auto px-5 py-4 space-y-5">
              {/* Metadata grid */}
              <div className="grid grid-cols-2 gap-3 text-sm">
                <MetaField label="Status">
                  <StatusBadge status={task.status} />
                </MetaField>
                <MetaField label="Category">
                  <CategoryBadge category={task.category} />
                </MetaField>
                <MetaField label="Priority">
                  <PriorityText priority={task.priority} />
                </MetaField>
                <MetaField label="Type">
                  <span className="font-medium">{task.type}</span>
                </MetaField>
                <MetaField label="Agent" span={2}>
                  <span className="font-medium">
                    {selectedEntry.agentName ?? "Unassigned"}
                  </span>
                </MetaField>
              </div>

              {/* Description — editable tiptap */}
              <Section title="Description">
                <TiptapEditor
                  entityId={task.id}
                  content={editorContent}
                  onUpdate={handleDescriptionUpdate}
                  enablePageLinks={false}
                />
              </Section>

              {/* Dependencies */}
              <Section title="Blocked By">
                {dependencies.length === 0 ? (
                  <p className="text-sm text-muted-foreground">None</p>
                ) : (
                  <ul className="space-y-1.5">
                    {dependencies.map((dep) => (
                      <li
                        key={dep.name}
                        className="flex items-center gap-2 text-sm"
                      >
                        <StatusDot status={dep.status} size="sm" />
                        <span className="min-w-0 flex-1 truncate">
                          {dep.name}
                        </span>
                      </li>
                    ))}
                  </ul>
                )}
              </Section>

              {/* Blocks */}
              <Section title="Blocks">
                {dependents.length === 0 ? (
                  <p className="text-sm text-muted-foreground">None</p>
                ) : (
                  <ul className="space-y-1.5">
                    {dependents.map((dep) => (
                      <li
                        key={dep.name}
                        className="flex items-center gap-2 text-sm"
                      >
                        <StatusDot status={dep.status} size="sm" />
                        <span className="min-w-0 flex-1 truncate">
                          {dep.name}
                        </span>
                      </li>
                    ))}
                  </ul>
                )}
              </Section>
            </div>

            {/* Footer */}
            <div className="flex items-center gap-2 border-t border-border px-5 py-3">
              {task.status === "blocked" ? (
                <Button
                  variant="outline"
                  size="sm"
                  className="gap-1.5"
                  onClick={() => {
                    retryBlockedTaskMutation.mutate({ taskId: task.id });
                    close();
                  }}
                >
                  <RotateCw className="h-3.5 w-3.5" />
                  Retry
                </Button>
              ) : (
                <Button
                  variant="outline"
                  size="sm"
                  disabled={!canQueue}
                  onClick={() => {
                    queueTaskMutation.mutate({ taskId: task.id });
                    close();
                  }}
                >
                  Queue Task
                </Button>
              )}
              <Button
                variant="outline"
                size="sm"
                className="gap-1.5"
                onClick={() => {
                  onOpenChat?.({ type: 'task', id: task.id, name: task.name });
                  close();
                }}
              >
                <MessageCircle className="h-3.5 w-3.5" />
                Chat
              </Button>
              <Button
                variant="destructive"
                size="sm"
                className="gap-1.5"
                onClick={(e) => {
                  if (
                    e.shiftKey ||
                    window.confirm(`Delete "${task.name}"?`)
                  ) {
                    deleteTaskMutation.mutate({ id: task.id });
                    close();
                  }
                }}
              >
                <Trash2 className="h-3.5 w-3.5" />
                Delete
              </Button>
            </div>
          </motion.div>
        </>
      )}
    </AnimatePresence>
  );
}

// ---------------------------------------------------------------------------
// Small helpers
// ---------------------------------------------------------------------------

function MetaField({
  label,
  span,
  children,
}: {
  label: string;
  span?: number;
  children: React.ReactNode;
}) {
  return (
    <div className={span === 2 ? "col-span-2" : undefined}>
      <span className="text-xs text-muted-foreground">{label}</span>
      <div className="mt-1">{children}</div>
    </div>
  );
}

function Section({
  title,
  children,
}: {
  title: string;
  children: React.ReactNode;
}) {
  return (
    <div>
      <h4 className="mb-1.5 text-sm font-medium">{title}</h4>
      {children}
    </div>
  );
}

function CategoryBadge({ category }: { category: string }) {
  const config = getCategoryConfig(category);
  return (
    <Badge variant={config.variant} size="xs">
      {config.label}
    </Badge>
  );
}

function PriorityText({ priority }: { priority: string }) {
  const color =
    priority === "high"
      ? "text-status-error-fg"
      : priority === "medium"
        ? "text-status-warning-fg"
        : "text-muted-foreground";
  return (
    <span className={cn("font-medium capitalize", color)}>{priority}</span>
  );
}
