import { createContext, useContext, useState, useCallback, type ReactNode } from "react";
import { PanelRightClose, Copy, Check } from "lucide-react";

export interface CodePreviewPayload {
  id: string;
  code: string;
  language: string;
  title?: string;
  subtitle?: string;
  kind?: "code" | "subagent";
  status?: "pending" | "ok" | "error" | "stopped";
  onStop?: () => void;
}

interface CodePreviewContextValue {
  activeCode: CodePreviewPayload | null;
  openCodePreview: (payload: CodePreviewPayload) => void;
  closeCodePreview: () => void;
  updateCodePreview: (updates: Partial<CodePreviewPayload>) => void;
}

const CodePreviewContext = createContext<CodePreviewContextValue | null>(null);

export function CodePreviewProvider({ children }: { children: ReactNode }) {
  const [activeCode, setActiveCode] = useState<CodePreviewPayload | null>(null);

  const openCodePreview = useCallback((payload: CodePreviewPayload) => {
    setActiveCode(payload);
  }, []);

  const closeCodePreview = useCallback(() => {
    setActiveCode(null);
  }, []);

  const updateCodePreview = useCallback((updates: Partial<CodePreviewPayload>) => {
    setActiveCode((prev) => (prev ? { ...prev, ...updates } : null));
  }, []);

  return (
    <CodePreviewContext.Provider
      value={{ activeCode, openCodePreview, closeCodePreview, updateCodePreview }}
    >
      {children}
    </CodePreviewContext.Provider>
  );
}

export function useCodePreview() {
  const ctx = useContext(CodePreviewContext);
  return ctx;
}

export function CodePreviewPanel() {
  const { activeCode, closeCodePreview, updateCodePreview } = useCodePreview() || {};
  const [copied, setCopied] = useState(false);

  if (!activeCode) return null;

  const lines = activeCode.code.replace(/\n$/, "").split("\n");
  const isSubAgent = activeCode.kind === "subagent";

  const handleCopy = () => {
    navigator.clipboard.writeText(activeCode.code).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };

  const handleStop = () => {
    activeCode.onStop?.();
    updateCodePreview?.({ status: "stopped" });
  };

  return (
    <aside
      className="flex h-full w-[min(50vw,600px)] shrink-0 flex-col border-l border-border bg-background transition-all duration-300"
      style={{
        animation: "slideInRight 0.3s ease-out",
      }}
    >
      {/* Header */}
      <div className="flex h-12 shrink-0 items-center justify-between border-b border-border px-4">
        <div className="min-w-0 flex-1">
          <div className="truncate text-sm font-medium text-foreground">
            {activeCode.title || activeCode.language || "Code"}
          </div>
          <div className="truncate text-xs text-muted-foreground">
            {activeCode.subtitle || `${lines.length} lines`}
          </div>
        </div>
        <div className="flex items-center gap-1">
          {isSubAgent && activeCode.status === "pending" && (
            <button
              onClick={handleStop}
              className="flex items-center gap-1 rounded px-2 py-1 text-xs text-destructive transition-colors hover:bg-destructive/10"
            >
              Stop
            </button>
          )}
          <button
            onClick={handleCopy}
            className="flex items-center gap-1 rounded px-2 py-1 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
          >
            {copied ? <Check className="size-3" /> : <Copy className="size-3" />}
            {copied ? "Copied" : "Copy"}
          </button>
          <button
            onClick={closeCodePreview}
            className="rounded p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
          >
            <PanelRightClose className="size-4" />
          </button>
        </div>
      </div>

      {/* Code content */}
      <div className="min-h-0 flex-1 overflow-auto">
        <div className="grid min-w-max grid-cols-[auto_1fr] text-[13px] leading-[1.6]">
          {/* Line numbers */}
          <div
            className="select-none border-r border-border px-3 py-4 text-right font-mono text-xs tabular-nums text-muted-foreground"
            aria-hidden="true"
          >
            {lines.map((_, index) => (
              <div key={index}>{index + 1}</div>
            ))}
          </div>
          {/* Code */}
          <pre className="m-0 min-h-full overflow-x-auto px-4 py-4 font-mono text-sm text-foreground">
            <code>{activeCode.code || (activeCode.status === "pending" ? "Waiting for output..." : "")}</code>
          </pre>
        </div>
      </div>
    </aside>
  );
}
