"use client";

import * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { FileStack, Search, X } from "lucide-react";

import { api } from "@/lib/trpc";
import { cn } from "@/lib/utils";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";

export type TemplateSchemaJson = {
  properties?: {
    name: string;
    fieldType: string;
    defaultValue?: unknown;
  }[];
  defaultContent?: string;
};

export type PickerTemplate = {
  id: string;
  workspaceId: string;
  name: string;
  targetType: string;
  schema: TemplateSchemaJson | null;
  isBuiltin?: boolean;
};

/** Preset templates for UI / offline use; merge with API `templates.list` when available. */
export const BUILTIN_TEMPLATES: PickerTemplate[] = [
  {
    id: "00000000-0000-4000-8000-000000000001",
    workspaceId: "",
    name: "Bug Report",
    targetType: "task",
    isBuiltin: true,
    schema: {
      properties: [
        { name: "Priority", fieldType: "select", defaultValue: "medium" },
        { name: "Severity", fieldType: "select", defaultValue: "major" },
        {
          name: "Steps to Reproduce",
          fieldType: "textarea",
          defaultValue: "",
        },
        {
          name: "Expected Behavior",
          fieldType: "textarea",
          defaultValue: "",
        },
      ],
      defaultContent:
        "## Summary\n\n## Steps to reproduce\n\n1. \n\n## Expected behavior\n\n",
    },
  },
  {
    id: "00000000-0000-4000-8000-000000000002",
    workspaceId: "",
    name: "Meeting Notes",
    targetType: "document",
    isBuiltin: true,
    schema: {
      properties: [
        { name: "Date", fieldType: "date", defaultValue: "" },
        { name: "Attendees", fieldType: "text", defaultValue: "" },
        { name: "Agenda", fieldType: "textarea", defaultValue: "" },
        { name: "Action Items", fieldType: "textarea", defaultValue: "" },
      ],
      defaultContent: "# Meeting\n\n## Agenda\n\n## Notes\n\n## Action items\n\n",
    },
  },
  {
    id: "00000000-0000-4000-8000-000000000003",
    workspaceId: "",
    name: "Sprint",
    targetType: "project",
    isBuiltin: true,
    schema: {
      properties: [
        { name: "Sprint Goal", fieldType: "text", defaultValue: "" },
        { name: "Start Date", fieldType: "date", defaultValue: "" },
        { name: "End Date", fieldType: "date", defaultValue: "" },
        { name: "Velocity", fieldType: "number", defaultValue: null },
      ],
      defaultContent: "## Sprint goal\n\n## Commitments\n\n",
    },
  },
];

const CREATE_SENTINEL = "__create__";

function schemaPreview(schema: TemplateSchemaJson | null | undefined): string {
  const props = schema?.properties ?? [];
  if (props.length === 0) {
    return "No custom properties";
  }
  const names = props.slice(0, 6).map((p) => p.name);
  const extra = props.length > 6 ? ` +${props.length - 6} more` : "";
  return `${names.join(" · ")}${extra}`;
}

function propertyCount(schema: TemplateSchemaJson | null | undefined): number {
  return schema?.properties?.length ?? 0;
}

export type TemplatePickerProps = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  objectType: string;
  /** List templates for this workspace when no object exists yet (e.g. create dialog). */
  workspaceId?: string;
  /** Resolve workspace from an existing object; ignored when `workspaceId` is set. */
  objectId?: string;
  onSelect: (template: PickerTemplate) => void;
  /** Renders the footer; invoked when the user chooses “Create New Template”. */
  onCreateNew?: () => void;
};

export function TemplatePicker({
  open,
  onOpenChange,
  objectType,
  workspaceId: workspaceIdProp,
  objectId,
  onSelect,
  onCreateNew,
}: TemplatePickerProps) {
  const [search, setSearch] = React.useState("");
  const [showAllTypes, setShowAllTypes] = React.useState(false);

  const objectQuery = api.objects.getById.useQuery(
    { id: objectId! },
    { enabled: open && Boolean(objectId) && !workspaceIdProp },
  );

  const objWorkspace = (objectQuery.data as unknown as { workspaceId?: string | null } | undefined)
    ?.workspaceId;
  const workspaceFromObject =
    typeof objWorkspace === "string" && objWorkspace.length > 0 ? objWorkspace : undefined;
  const resolvedWorkspaceId = workspaceIdProp ?? workspaceFromObject;

  const listQuery = api.templates.list.useQuery(
    {
      workspaceId: resolvedWorkspaceId!,
      targetType: showAllTypes ? undefined : objectType,
    },
    { enabled: open && Boolean(resolvedWorkspaceId) },
  );

  const merged = React.useMemo(() => {
    const fromApi = listQuery.data?.templates ?? [];
    const builtinFiltered = BUILTIN_TEMPLATES.filter(
      (b) => showAllTypes || b.targetType === objectType,
    );
    const seen = new Set<string>();
    const out: PickerTemplate[] = [];
    for (const t of [...builtinFiltered, ...fromApi]) {
      if (seen.has(t.id)) continue;
      seen.add(t.id);
      out.push({
        id: t.id,
        workspaceId: t.workspaceId,
        name: t.name,
        targetType: t.targetType,
        schema: (t.schema as TemplateSchemaJson | null) ?? null,
        isBuiltin: "isBuiltin" in t ? t.isBuiltin : false,
      });
    }
    return out;
  }, [listQuery.data?.templates, objectType, showAllTypes]);

  const filtered = React.useMemo(() => {
    const q = search.trim().toLowerCase();
    if (!q) return merged;
    return merged.filter((t) => t.name.toLowerCase().includes(q));
  }, [merged, search]);

  const grouped = React.useMemo(() => {
    if (!showAllTypes) {
      return new Map([[objectType, filtered]]);
    }
    const m = new Map<string, PickerTemplate[]>();
    const order = ["project", "task", "document", "whiteboard", "group", "workspace"];
    for (const t of filtered) {
      const k = t.targetType;
      if (!m.has(k)) m.set(k, []);
      m.get(k)!.push(t);
    }
    const keys = [...m.keys()].sort(
      (a, b) => order.indexOf(a) - order.indexOf(b) || a.localeCompare(b),
    );
    return new Map(keys.map((k) => [k, m.get(k)!]));
  }, [filtered, objectType, showAllTypes]);

  React.useEffect(() => {
    if (!open) {
      setSearch("");
      setShowAllTypes(false);
    }
  }, [open]);

  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-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-0 rounded-lg border bg-background p-0 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",
          )}
        >
          <div className="flex items-start justify-between gap-3 border-b px-4 py-3">
            <div className="min-w-0 space-y-1">
              <DialogPrimitive.Title className="text-lg font-semibold leading-none tracking-tight">
                Use a template
              </DialogPrimitive.Title>
              <DialogPrimitive.Description className="text-sm text-muted-foreground">
                Apply structure and default fields to this {objectType}.
              </DialogPrimitive.Description>
            </div>
            <DialogPrimitive.Close asChild>
              <Button variant="ghost" size="icon" className="h-8 w-8 shrink-0" aria-label="Close">
                <X className="h-4 w-4" />
              </Button>
            </DialogPrimitive.Close>
          </div>

          <div className="space-y-3 px-4 py-3">
            <div className="relative">
              <Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
              <Input
                placeholder="Search templates…"
                className="pl-9"
                value={search}
                onChange={(e) => setSearch(e.target.value)}
              />
            </div>
            <label className="flex cursor-pointer items-center gap-2 text-sm text-muted-foreground">
              <input
                type="checkbox"
                className="rounded border-input"
                checked={showAllTypes}
                onChange={(e) => setShowAllTypes(e.target.checked)}
              />
              Show all types
            </label>
          </div>

          <ScrollArea className="max-h-[min(420px,55vh)] px-4">
            <div className="space-y-4 pb-3 pr-3">
              {listQuery.isPending && resolvedWorkspaceId ? (
                <p className="text-sm text-muted-foreground">Loading templates…</p>
              ) : null}
              {!resolvedWorkspaceId && objectId && !workspaceIdProp && objectQuery.isPending ? (
                <p className="text-sm text-muted-foreground">Loading object…</p>
              ) : null}
              {!resolvedWorkspaceId && objectId && !workspaceIdProp && objectQuery.isError ? (
                <p className="text-sm text-destructive">Could not load workspace.</p>
              ) : null}

              {Array.from(grouped.entries()).map(([typeKey, items], gi) => (
                <React.Fragment key={typeKey}>
                  {gi > 0 && showAllTypes ? <Separator className="my-2" /> : null}
                  <div className="space-y-2">
                    {showAllTypes ? (
                      <div className="flex items-center gap-2 pt-1">
                        <span className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
                          {typeKey}
                        </span>
                        <Separator className="flex-1" />
                      </div>
                    ) : null}
                    {items.length === 0 ? (
                      <p className="text-sm text-muted-foreground">
                        No templates match this filter.
                      </p>
                    ) : (
                      items.map((t) => (
                        <div
                          key={t.id}
                          className="rounded-lg border bg-card p-3 shadow-sm transition-colors hover:bg-accent/40"
                        >
                          <div className="flex flex-wrap items-start justify-between gap-2">
                            <div className="min-w-0 space-y-1">
                              <div className="flex flex-wrap items-center gap-2">
                                <span className="font-medium leading-tight">{t.name}</span>
                                <Badge variant="secondary" className="text-[10px] uppercase">
                                  {t.targetType}
                                </Badge>
                                {t.isBuiltin ? (
                                  <Badge variant="outline" className="text-[10px]">
                                    Built-in
                                  </Badge>
                                ) : null}
                              </div>
                              <p className="text-xs text-muted-foreground">
                                {propertyCount(t.schema)} properties ·{" "}
                                <span className="line-clamp-2">{schemaPreview(t.schema)}</span>
                              </p>
                            </div>
                            <Button
                              size="sm"
                              className="shrink-0"
                              onClick={() => {
                                onSelect(t);
                                onOpenChange(false);
                              }}
                            >
                              Use Template
                            </Button>
                          </div>
                        </div>
                      ))
                    )}
                  </div>
                </React.Fragment>
              ))}
            </div>
          </ScrollArea>

          {onCreateNew ? (
            <div className="border-t px-4 py-3">
              <Button
                variant="outline"
                className="w-full gap-2"
                onClick={() => {
                  onCreateNew();
                  onOpenChange(false);
                }}
              >
                <FileStack className="h-4 w-4" />
                Create New Template
              </Button>
            </div>
          ) : null}
        </DialogPrimitive.Content>
      </DialogPrimitive.Portal>
    </DialogPrimitive.Root>
  );
}

export { CREATE_SENTINEL as TEMPLATE_PICKER_CREATE_SENTINEL };
