"use client";

import * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { useRouter } from "next/navigation";
import {
  CheckSquare,
  ClipboardList,
  FileStack,
  FileText,
  LayoutGrid,
  Presentation,
  X,
} from "lucide-react";

import { TemplatePicker, type PickerTemplate } from "@/components/templates";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { api } from "@/lib/trpc";
import { useWorkspaceStore } from "@/lib/stores/workspace-store";
import { cn } from "@/lib/utils";

const CREATE_TYPES = ["task", "document", "space", "whiteboard", "form"] as const;
type CreateObjectType = (typeof CREATE_TYPES)[number];

const TYPE_OPTIONS: {
  value: CreateObjectType;
  label: string;
  icon: React.ComponentType<{ className?: string }>;
}[] = [
  { value: "task", label: "Task", icon: CheckSquare },
  { value: "document", label: "Document", icon: FileText },
  { value: "space", label: "Space", icon: LayoutGrid },
  { value: "whiteboard", label: "Whiteboard", icon: Presentation },
  { value: "form", label: "Form", icon: ClipboardList },
];

const TASK_STATUSES = [
  { value: "open", label: "Open" },
  { value: "in_progress", label: "In Progress" },
  { value: "done", label: "Done" },
] as const;

const selectFieldClass =
  "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50";

function normalizeDefaultType(raw?: string): CreateObjectType {
  if (!raw) return "task";
  const v = raw.toLowerCase().trim().replace(/\s+/g, "_");
  if (v === "doc") return "document";
  if (v === "white_board") return "whiteboard";
  if (v === "list") return "task";
  if (v === "form") return "form";
  if ((CREATE_TYPES as readonly string[]).includes(v)) {
    return v as CreateObjectType;
  }
  return "task";
}

export interface CreateObjectDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  defaultType?: string;
  defaultParentId?: string;
  workspaceId?: string;
}

export function CreateObjectDialog({
  open,
  onOpenChange,
  defaultType,
  defaultParentId,
  workspaceId: workspaceIdProp,
}: CreateObjectDialogProps) {
  const router = useRouter();
  const storeWorkspaceId = useWorkspaceStore((s) => s.currentWorkspace?.id);
  const resolvedWorkspaceId = workspaceIdProp ?? storeWorkspaceId ?? undefined;

  const utils = api.useUtils();
  const titleInputRef = React.useRef<HTMLInputElement>(null);
  const selectedTemplateRef = React.useRef<PickerTemplate | null>(null);

  const [objectType, setObjectType] = React.useState<CreateObjectType>(() =>
    normalizeDefaultType(defaultType),
  );
  const [title, setTitle] = React.useState("");
  const [titleError, setTitleError] = React.useState(false);
  const [parentId, setParentId] = React.useState("");
  const [taskStatus, setTaskStatus] = React.useState<
    (typeof TASK_STATUSES)[number]["value"]
  >("open");
  const [selectedTemplate, setSelectedTemplate] = React.useState<PickerTemplate | null>(
    null,
  );
  const [showTemplatePicker, setShowTemplatePicker] = React.useState(false);

  React.useEffect(() => {
    selectedTemplateRef.current = selectedTemplate;
  }, [selectedTemplate]);

  const showParentPicker =
    objectType === "task" || objectType === "document";

  const spacesQuery = api.objects.list.useQuery(
    {
      workspaceId: resolvedWorkspaceId!,
      type: "space",
      limit: 500,
    },
    { enabled: Boolean(open && resolvedWorkspaceId && showParentPicker) },
  );

  const spaces = spacesQuery.data?.objects ?? [];

  React.useEffect(() => {
    if (!open) return;
    setObjectType(normalizeDefaultType(defaultType));
    setTitle("");
    setTitleError(false);
    setParentId(defaultParentId ?? "");
    setTaskStatus("open");
    setSelectedTemplate(null);
    setShowTemplatePicker(false);
  }, [open, defaultType, defaultParentId]);

  React.useEffect(() => {
    if (!open) return;
    const t = window.setTimeout(() => titleInputRef.current?.focus(), 0);
    return () => window.clearTimeout(t);
  }, [open]);

  const applyTemplateMutation = api.templates.applyTemplate.useMutation();

  const createMutation = api.objects.create.useMutation({
    onSuccess: async (newObj) => {
      const t = selectedTemplateRef.current;
      if (t && newObj?.id) {
        try {
          await applyTemplateMutation.mutateAsync({
            templateId: t.id,
            objectId: newObj.id,
          });
        } catch {
          // Template application failure shouldn't block creation
        }
      }
      await utils.objects.list.invalidate();
      await utils.objects.getTree.invalidate();
      onOpenChange(false);
    },
  });

  const createFormMutation = api.forms.create.useMutation({
    onSuccess: (data) => {
      utils.objects.getTree.invalidate();
      const newId = (data as { id?: string }).id;
      if (newId && resolvedWorkspaceId) {
        router.push(`/${resolvedWorkspaceId}/forms/${newId}/edit`);
      }
      onOpenChange(false);
    },
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const trimmed = title.trim();
    if (!trimmed) {
      setTitleError(true);
      return;
    }
    if (!resolvedWorkspaceId) {
      return;
    }
    setTitleError(false);

    if (objectType === "form") {
      createFormMutation.mutate({
        workspaceId: resolvedWorkspaceId,
        title: trimmed,
      });
      return;
    }

    const parentForCreate =
      objectType === "task" || objectType === "document"
        ? parentId || null
        : null;

    createMutation.mutate({
      type: objectType,
      title: trimmed,
      workspaceId: resolvedWorkspaceId,
      parentId: parentForCreate,
      ...(objectType === "task" ? { status: taskStatus } : {}),
    });
  };

  const isSubmitting =
    createMutation.isPending ||
    createFormMutation.isPending ||
    applyTemplateMutation.isPending;

  return (
    <DialogPrimitive.Root open={open} onOpenChange={onOpenChange}>
      <DialogPrimitive.Portal>
        <DialogPrimitive.Overlay
          className={cn(
            "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
          )}
        />
        <DialogPrimitive.Content
          className={cn(
            "fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200",
            "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
            "rounded-lg",
          )}
          onOpenAutoFocus={(ev) => ev.preventDefault()}
        >
          <div className="flex flex-col gap-1.5 pr-8 text-left">
            <DialogPrimitive.Title className="text-lg font-semibold leading-none tracking-tight">
              Create object
            </DialogPrimitive.Title>
            <DialogPrimitive.Description className="sr-only">
              Choose a type, enter a title, and optional parent space or task
              status.
            </DialogPrimitive.Description>
          </div>

          <DialogPrimitive.Close
            className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none"
            aria-label="Close"
          >
            <X className="h-4 w-4" />
          </DialogPrimitive.Close>

          <form onSubmit={handleSubmit} className="flex flex-col gap-4">
            {!resolvedWorkspaceId ? (
              <p className="text-sm text-muted-foreground">
                Select a workspace to create objects.
              </p>
            ) : null}

            <div className="space-y-2">
              <span className="text-sm font-medium">Type</span>
              <div
                className="grid grid-cols-2 gap-2 sm:grid-cols-5"
                role="radiogroup"
                aria-label="Object type"
              >
                {TYPE_OPTIONS.map(({ value, label, icon: Icon }) => {
                  const selected = objectType === value;
                  return (
                    <button
                      key={value}
                      type="button"
                      role="radio"
                      aria-checked={selected}
                      onClick={() => setObjectType(value)}
                      className={cn(
                        "flex flex-col items-center gap-2 rounded-md border p-3 text-center transition-colors",
                        "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
                        selected
                          ? "border-primary bg-accent"
                          : "border-input bg-background hover:bg-accent/50",
                      )}
                    >
                      <Badge
                        variant={selected ? "default" : "outline"}
                        className="gap-1 px-2 py-1 font-normal"
                      >
                        <Icon className="size-4" />
                        <span>{label}</span>
                      </Badge>
                    </button>
                  );
                })}
              </div>
            </div>

            {(objectType === "task" || objectType === "document") && (
              <div className="space-y-2">
                <div className="flex items-center justify-between">
                  <span className="text-sm font-medium">Template</span>
                  {selectedTemplate ? (
                    <button
                      type="button"
                      className="text-xs text-muted-foreground hover:text-foreground"
                      onClick={() => setSelectedTemplate(null)}
                    >
                      Clear
                    </button>
                  ) : null}
                </div>
                {selectedTemplate ? (
                  <div className="flex items-center gap-2 rounded-md border bg-accent/50 px-3 py-2 text-sm">
                    <Badge variant="secondary" className="gap-1">
                      <FileStack className="size-3" />
                      {selectedTemplate.name}
                    </Badge>
                  </div>
                ) : (
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className="w-full gap-1.5"
                    onClick={() => setShowTemplatePicker(true)}
                  >
                    <FileStack className="size-4" />
                    Use Template
                  </Button>
                )}
              </div>
            )}

            <div className="space-y-2">
              <label htmlFor="create-object-title" className="text-sm font-medium">
                Title
              </label>
              <Input
                id="create-object-title"
                ref={titleInputRef}
                value={title}
                onChange={(ev) => {
                  setTitle(ev.target.value);
                  if (titleError) setTitleError(false);
                }}
                placeholder="Name"
                autoComplete="off"
                aria-invalid={titleError}
              />
              {titleError ? (
                <p className="text-sm text-destructive" role="alert">
                  Title is required
                </p>
              ) : null}
            </div>

            {showParentPicker ? (
              <div className="space-y-2">
                <label
                  htmlFor="create-object-parent"
                  className="text-sm font-medium"
                >
                  Parent space
                </label>
                <select
                  id="create-object-parent"
                  className={selectFieldClass}
                  value={parentId}
                  onChange={(e) => setParentId(e.target.value)}
                  disabled={spacesQuery.isLoading}
                >
                  <option value="">Workspace root</option>
                  {spaces.map((s) => (
                    <option key={s.id} value={s.id}>
                      {s.title}
                    </option>
                  ))}
                </select>
              </div>
            ) : null}

            {objectType === "task" ? (
              <div className="space-y-2">
                <label
                  htmlFor="create-object-status"
                  className="text-sm font-medium"
                >
                  Status
                </label>
                <select
                  id="create-object-status"
                  className={selectFieldClass}
                  value={taskStatus}
                  onChange={(e) =>
                    setTaskStatus(
                      e.target.value as (typeof TASK_STATUSES)[number]["value"],
                    )
                  }
                >
                  {TASK_STATUSES.map((s) => (
                    <option key={s.value} value={s.value}>
                      {s.label}
                    </option>
                  ))}
                </select>
              </div>
            ) : null}

            <div className="flex justify-end gap-2 pt-2">
              <Button
                type="button"
                variant="outline"
                onClick={() => onOpenChange(false)}
              >
                Cancel
              </Button>
              <Button
                type="submit"
                disabled={!resolvedWorkspaceId || isSubmitting}
              >
                {isSubmitting ? "Creating…" : "Create"}
              </Button>
            </div>
          </form>
        </DialogPrimitive.Content>
      </DialogPrimitive.Portal>

      {showTemplatePicker && resolvedWorkspaceId && (
        <TemplatePicker
          open={showTemplatePicker}
          onOpenChange={setShowTemplatePicker}
          workspaceId={resolvedWorkspaceId}
          objectType={objectType}
          onSelect={(template) => {
            setSelectedTemplate(template);
            setShowTemplatePicker(false);
          }}
        />
      )}
    </DialogPrimitive.Root>
  );
}
