/**
 * Half of the loop: library template → engagement artefact.
 *
 * The picker is a list rather than a grid of `TemplateCard`s, because the
 * question being answered here is not "what is in the library" but "which of
 * these four is the one for this stage" — so the rows are dense, the stage
 * filter opens pre-set to the deal's own stage, and usage is on every row.
 * Usage is the only quality signal the library has: a v3 used eleven times is
 * tested and a v1 used never is somebody's draft, and that distinction matters
 * more when copying into a live deal than when browsing.
 *
 * Instantiating copies the body and fields and increments the template's
 * usage count, which is what closes the template to in-place edits (§7a). That
 * is stated on the dialog rather than left to be discovered later by whoever
 * tries to fix a typo in it.
 */
import { useDeferredValue, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { AlertTriangle, Library, RefreshCw, Search } from 'lucide-react';
import { toast } from 'sonner';
import {
  DEMAND_STAGES,
  DEMAND_STAGE_LABELS,
  MOTION_KINDS,
  MOTION_KIND_LABELS,
  type DemandStage,
  type MotionKind,
} from '@pig/core';
import { get, post } from '@/lib/api';
import { Badge, Button, EmptyState, Input, Skeleton } from '@/components/ui';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { MotionKindBadge } from './MotionKindBadge';

/** `GET /api/motion/templates` — summaries, so no body and no fields. */
interface TemplateRow {
  id: string;
  kind: MotionKind;
  slug: string;
  version: number;
  title: string;
  summary: string;
  stage: DemandStage;
  visibility: 'private' | 'shared';
  isSystem: boolean;
  usageCount: number;
  updatedAt: string;
}

export function InstantiateDialog({
  engagementId,
  defaultStage = null,
  defaultKind = null,
  open,
  onOpenChange,
}: {
  engagementId: string;
  /** The deal's stage, so the list opens on the templates that serve it. */
  defaultStage?: DemandStage | null;
  /** Set when the caller is after one kind — a framework to score against. */
  defaultKind?: MotionKind | null;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}) {
  const queryClient = useQueryClient();
  const [kind, setKind] = useState<'all' | MotionKind>(defaultKind ?? 'all');
  const [stage, setStage] = useState<'all' | DemandStage>(defaultStage ?? 'all');
  const [query, setQuery] = useState('');
  const search = useDeferredValue(query.trim());

  const templates = useQuery({
    queryKey: ['motion', 'library', { kind, stage, search }],
    queryFn: () => {
      const params = new URLSearchParams();
      if (kind !== 'all') params.set('kind', kind);
      if (stage !== 'all') params.set('stage', stage);
      if (search) params.set('q', search);
      const suffix = params.toString();
      return get<{ templates: TemplateRow[]; truncated: boolean }>(
        `/api/motion/templates${suffix ? `?${suffix}` : ''}`,
      );
    },
    enabled: open,
  });

  const instantiate = useMutation({
    mutationFn: (templateId: string) =>
      post<{ artifact: { id: string } }>(`/api/motion/engagements/${engagementId}/artifacts`, {
        templateId,
      }),
    onSuccess: async () => {
      // The prefix invalidation is deliberate: instantiating moves the
      // template's usage count too, so the library and the OS home are stale
      // the moment this succeeds, not only the engagement.
      await queryClient.invalidateQueries({ queryKey: ['motion'] });
      toast.success('Artefact added to the engagement');
      onOpenChange(false);
    },
    onError: (error: Error) => toast.error(error.message),
  });

  const rows = templates.data?.templates ?? [];
  const filtered = kind !== 'all' || stage !== 'all' || Boolean(search);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-h-[85dvh] w-[calc(100vw-1.5rem)] max-w-2xl grid-rows-[auto_auto_minmax(0,1fr)] overflow-hidden p-4 sm:p-6">
        <DialogHeader className="pr-11">
          <DialogTitle>Instantiate from the library</DialogTitle>
          <DialogDescription>
            The body and structured fields are copied into this engagement, and the template is
            closed to in-place edits from here on — later changes to it become a new version.
          </DialogDescription>
        </DialogHeader>

        <div className="grid min-w-0 gap-2 sm:grid-cols-[minmax(0,1fr)_9.5rem_9.5rem]">
          <div className="relative min-w-0">
            <Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted" aria-hidden />
            <Input
              aria-label="Search the library"
              className="pl-9"
              placeholder="Search title or summary"
              value={query}
              onChange={(event) => setQuery(event.target.value)}
            />
          </div>
          <Select value={kind} onValueChange={(value) => setKind(value as typeof kind)}>
            <SelectTrigger aria-label="Filter by kind" className="h-11 min-w-0">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectGroup>
                <SelectItem value="all">All kinds</SelectItem>
                {MOTION_KINDS.map((value) => (
                  <SelectItem key={value} value={value}>
                    {MOTION_KIND_LABELS[value]}
                  </SelectItem>
                ))}
              </SelectGroup>
            </SelectContent>
          </Select>
          <Select value={stage} onValueChange={(value) => setStage(value as typeof stage)}>
            <SelectTrigger aria-label="Filter by stage" className="h-11 min-w-0">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectGroup>
                <SelectItem value="all">All stages</SelectItem>
                {DEMAND_STAGES.map((value) => (
                  <SelectItem key={value} value={value}>
                    {DEMAND_STAGE_LABELS[value]}
                  </SelectItem>
                ))}
              </SelectGroup>
            </SelectContent>
          </Select>
        </div>

        <div className="min-w-0 overflow-y-auto">
          {templates.isLoading ? (
            <div className="flex flex-col gap-2">
              {Array.from({ length: 4 }).map((_, index) => (
                <Skeleton key={index} className="h-20" />
              ))}
            </div>
          ) : null}

          {templates.isError ? (
            <EmptyState
              icon={<AlertTriangle />}
              title="Library unavailable"
              description={
                templates.error instanceof Error
                  ? templates.error.message
                  : 'The library could not be loaded.'
              }
              action={
                <Button variant="outline" onClick={() => void templates.refetch()}>
                  <RefreshCw aria-hidden />
                  Try again
                </Button>
              }
            />
          ) : null}

          {!templates.isLoading && !templates.isError && rows.length === 0 ? (
            <EmptyState
              icon={<Library />}
              title={filtered ? 'No template matches' : 'The library is empty'}
              description={
                filtered
                  ? 'Clear a filter, or write the artefact from scratch and promote it once it has proved itself.'
                  : 'Nothing has been published yet. An artefact written here can be promoted into the library once it is final.'
              }
            />
          ) : null}

          {rows.length ? (
            <ul className="flex min-w-0 flex-col gap-2">
              {rows.map((template) => (
                <li
                  key={template.id}
                  className="flex min-w-0 flex-col gap-2 rounded-xl border border-border p-3 sm:flex-row sm:items-center"
                >
                  <div className="min-w-0 flex-1">
                    <div className="flex min-w-0 flex-wrap items-center gap-1.5">
                      <MotionKindBadge kind={template.kind} />
                      <Badge tone="neutral" className="min-w-0">
                        <span className="truncate">{DEMAND_STAGE_LABELS[template.stage]}</span>
                      </Badge>
                      <span className="nums whitespace-nowrap text-xs text-muted">
                        v{template.version} ·{' '}
                        {template.usageCount === 1
                          ? 'used once'
                          : `used ${template.usageCount} times`}
                      </span>
                    </div>
                    <p className="mt-1.5 min-w-0 break-words font-medium leading-snug">
                      {template.title}
                    </p>
                    {template.summary ? (
                      <p className="mt-0.5 line-clamp-2 min-w-0 break-words text-sm leading-6 text-muted">
                        {template.summary}
                      </p>
                    ) : null}
                  </div>
                  <Button
                    type="button"
                    variant="primary"
                    className="w-full shrink-0 sm:w-auto"
                    disabled={instantiate.isPending}
                    onClick={() => instantiate.mutate(template.id)}
                  >
                    Use this
                  </Button>
                </li>
              ))}
            </ul>
          ) : null}

          {templates.data?.truncated ? (
            <p className="mt-3 text-xs text-muted">
              The library is wider than this answer. Narrow it with a kind, a stage or a search.
            </p>
          ) : null}
        </div>
      </DialogContent>
    </Dialog>
  );
}
