"use client";

import { useEffect, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@turbostarter/ui-web/dialog";
import { Button } from "@turbostarter/ui-web/button";
import { Input } from "@turbostarter/ui-web/input";
import { Icons } from "@turbostarter/ui-web/icons";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@turbostarter/ui-web/select";
import { toast } from "sonner";
import { api } from "~/lib/api/client";
import { pathsConfig } from "~/config/paths";
import { diagramTypeConfig } from "./DiagramCard";

import type { ReactNode } from "react";

const diagramTypes = ["bpmn", "er", "orgchart", "architecture", "sequence", "flowchart"] as const;
type DiagramType = (typeof diagramTypes)[number];

function deriveTitleFromDescription(description: string): string {
  const trimmed = description.trim();
  if (trimmed.length <= 50) return trimmed;
  const truncated = trimmed.slice(0, 50);
  const lastSpace = truncated.lastIndexOf(" ");
  return lastSpace > 20 ? truncated.slice(0, lastSpace) : truncated;
}

interface CreateDiagramDialogProps {
  children: ReactNode;
}

export function CreateDiagramDialog({ children }: CreateDiagramDialogProps) {
  const [open, setOpen] = useState(false);
  const [description, setDescription] = useState("");
  const [title, setTitle] = useState("");
  const [selectedType, setSelectedType] = useState<DiagramType>("flowchart");
  const [aiInferredType, setAiInferredType] = useState<DiagramType | null>(null);
  const [isInferring, setIsInferring] = useState(false);
  const userOverrodeRef = useRef(false);
  const [selectedProjectId, setSelectedProjectId] = useState<string | undefined>(undefined);
  const router = useRouter();
  const queryClient = useQueryClient();

  const derivedTitle = description.trim() ? deriveTitleFromDescription(description) : "";

  const { data: projectsData } = useQuery({
    queryKey: ["projects"],
    queryFn: async () => {
      const res = await api.projects.$get();
      return await res.json();
    },
  });

  const projects = projectsData?.data ?? [];

  // Debounced AI type inference
  useEffect(() => {
    if (description.trim().length < 10) {
      setAiInferredType(null);
      return;
    }

    const timeout = setTimeout(async () => {
      setIsInferring(true);
      try {
        const res = await api.ai.copilot["infer-type"].$post({
          json: { description: description.trim() },
        });
        const data = await res.json();
        setAiInferredType(data.type as DiagramType);
        if (!userOverrodeRef.current) {
          setSelectedType(data.type as DiagramType);
        }
      } catch {
        // Silently fail — user can always manually select
      } finally {
        setIsInferring(false);
      }
    }, 500);

    return () => clearTimeout(timeout);
  }, [description]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleTypeSelect = (type: DiagramType) => {
    setSelectedType(type);
    userOverrodeRef.current = true;
  };

  const handleDescriptionChange = (value: string) => {
    setDescription(value);
    userOverrodeRef.current = false;
  };

  const createMutation = useMutation({
    mutationFn: async (input: {
      title: string;
      type: DiagramType;
      description?: string;
      projectId?: string;
    }) => {
      const res = await api.diagrams.$post({ json: input });
      return await res.json();
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({ queryKey: ["diagrams"] });
      const desc = description.trim();
      setOpen(false);
      setDescription("");
      setTitle("");
      setSelectedType("flowchart");
      setAiInferredType(null);
      userOverrodeRef.current = false;
      setSelectedProjectId(undefined);
      if (data.data) {
        const url = desc
          ? `${pathsConfig.dashboard.user.diagram(data.data.id)}?desc=${encodeURIComponent(desc)}`
          : pathsConfig.dashboard.user.diagram(data.data.id);
        router.push(url);
      }
    },
    onError: () => {
      toast.error("Failed to create diagram. Please try again.");
    },
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const finalTitle = title.trim() || derivedTitle;
    if (!finalTitle) return;
    createMutation.mutate({
      title: finalTitle,
      type: selectedType,
      description: description.trim() || undefined,
      projectId: selectedProjectId,
    });
  };

  const effectiveTitle = title.trim() || derivedTitle;

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>{children}</DialogTrigger>
      <DialogContent className="sm:max-w-xl">
        <DialogHeader>
          <DialogTitle>Create New Diagram</DialogTitle>
        </DialogHeader>
        <form onSubmit={handleSubmit} className="space-y-6">
          <div className="space-y-2">
            <label htmlFor="diagram-description" className="text-sm font-medium">
              What are you designing?
            </label>
            <textarea
              id="diagram-description"
              placeholder="e.g. database schema for our user management system..."
              value={description}
              onChange={(e) => handleDescriptionChange(e.target.value)}
              autoFocus
              rows={3}
              maxLength={500}
              className="flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 resize-none"
            />
          </div>

          <div className="space-y-2">
            <label htmlFor="diagram-title" className="text-sm font-medium">
              Title {description.trim() && <span className="text-muted-foreground font-normal">(optional — auto-generated)</span>}
            </label>
            <Input
              id="diagram-title"
              placeholder={derivedTitle || "My diagram"}
              value={title}
              onChange={(e) => setTitle(e.target.value)}
            />
          </div>

          <div className="space-y-2">
            <label className="text-sm font-medium">Project</label>
            <Select
              value={selectedProjectId ?? "none"}
              onValueChange={(v) => setSelectedProjectId(v === "none" ? undefined : v)}
            >
              <SelectTrigger className="w-full">
                <SelectValue placeholder="No project (Unorganized)" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="none">No project (Unorganized)</SelectItem>
                {projects.map((p) => (
                  <SelectItem key={p.id} value={p.id}>{p.name}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div className="space-y-2">
            <div className="flex items-center gap-2">
              <label className="text-sm font-medium">Diagram Type</label>
              {isInferring && (
                <Icons.Loader2 className="h-3.5 w-3.5 animate-spin text-muted-foreground" />
              )}
            </div>
            <div className="grid grid-cols-3 gap-2">
              {diagramTypes.map((type) => {
                const config = diagramTypeConfig[type];
                const TypeIcon = config.icon;
                const isSelected = selectedType === type;
                const isAiSuggested = aiInferredType === type;
                return (
                  <button
                    key={type}
                    type="button"
                    onClick={() => handleTypeSelect(type)}
                    className={`relative flex flex-col items-center gap-1.5 rounded-lg border-2 p-3 text-sm transition-all duration-200 ${
                      isSelected
                        ? "border-primary bg-primary/5 scale-[1.02]"
                        : "border-transparent bg-muted/50 hover:bg-muted"
                    }`}
                  >
                    <TypeIcon className={`h-5 w-5 ${config.color}`} />
                    <span className="font-medium">{config.label}</span>
                    {isAiSuggested && (
                      <span className="flex items-center gap-0.5 text-[10px] text-primary">
                        <Icons.Sparkles className="h-3 w-3" />
                        AI suggested
                      </span>
                    )}
                  </button>
                );
              })}
            </div>
          </div>

          <div className="flex justify-end gap-2">
            <Button
              type="button"
              variant="outline"
              onClick={() => setOpen(false)}
            >
              Cancel
            </Button>
            <Button
              type="submit"
              disabled={!effectiveTitle || createMutation.isPending}
            >
              {createMutation.isPending && (
                <Icons.Loader2 className="mr-2 h-4 w-4 animate-spin" />
              )}
              Create
            </Button>
          </div>
        </form>
      </DialogContent>
    </Dialog>
  );
}
