"use client";

import { useRef, useState } from "react";
import { Controller } from "react-hook-form";
import { AlertTriangle, Braces, Eye, FileText, MoreHorizontal, Pencil, Plus, Sparkles, Trash2, X } from "lucide-react";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Field, FieldDescription, FieldError, FieldGroup, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet";
import { Skeleton } from "@/components/ui/skeleton";
import { Spinner } from "@/components/ui/spinner";
import { FormErrorAlert, SelectField, SwitchField, TextField } from "@/components/app/form-fields";
import { SectionCard } from "@/components/app/page";
import { RichTextEditor } from "@/components/app/rich-text-editor";
import { cn } from "@/lib/utils";
import { useAuth } from "../../auth/auth-context";
import { EmptyState, ErrorState, UnauthorizedState } from "../../components/ui/page-states";
import { describeError } from "../../lib/useAsyncAction";
import { formatDate } from "../../lib/format";
import { HtmlPreview } from "../../mail/html-preview";
import { SettingsFrame, SettingsShell } from "../settings-layout";
import { ACTION_OPTIONS, CONTEXT_OPTIONS, isStarter, PREVIEW_TYPE_OPTIONS, RECIPIENT_RULE_OPTIONS, useMailTemplateForm, useMailTemplates } from "./useMailTemplates";

const DESCRIPTION = "The wording each email starts with. Merge fields like {{po.po_no}} fill in from the record; the sender can still edit everything before sending.";

export function EmailTemplatesPage() {
  return <SettingsShell title="Email templates"><EmailTemplatesWorkspace /></SettingsShell>;
}

function EmailTemplatesWorkspace() {
  const { can } = useAuth();
  const canManage = can("mail.manage_templates");
  const templates = useMailTemplates();
  const [editing, setEditing] = useState(null); // { template } — template null = new

  if (!can("mail.view")) {
    return <SettingsFrame title="Email templates" description={DESCRIPTION}><UnauthorizedState permission="mail.view" /></SettingsFrame>;
  }

  return <SettingsFrame title="Email templates" description={DESCRIPTION} actions={canManage && <Button size="sm" onClick={() => setEditing({ template: null })}><Plus />New template</Button>}>
    {!canManage && <p className="text-sm text-muted-foreground">Read-only for your role. Managers and senior merchandisers can change templates.</p>}
    {templates.isLoading
      ? <div className="grid gap-4">{[0, 1, 2].map((index) => <Skeleton key={index} className="h-32 rounded-xl" />)}</div>
      : templates.error
        ? <ErrorState error={templates.error} title="Templates could not be loaded" onRetry={templates.refresh} />
        : !templates.groups.length
          ? <EmptyState icon={FileText} title="No templates yet" detail="Templates give every email a consistent start: greeting, the record's details and your sign-off." action={canManage && <Button size="sm" onClick={() => setEditing({ template: null })}><Plus />New template</Button>} />
          : <SectionCard title="Templates" icon={FileText} description="Grouped by what they're about. Starters come with the app; “Customise” makes your organization's version."
            actions={<Badge variant="outline" className="tabular-nums">{templates.templates.length}</Badge>} contentClassName={cn("p-0 transition-opacity", templates.isRefreshing && "opacity-60")}>
            {templates.groups.map((group) => <section key={group.value} aria-label={group.label} className="border-t">
              <h3 className="bg-muted/40 px-4 py-1.5 text-xs font-medium text-muted-foreground">{group.label} <span className="tabular-nums">· {group.templates.length}</span></h3>
              <ul className="divide-y">
                {group.templates.map((template) => <TemplateRow key={template.id} template={template} canManage={canManage} onEdit={() => setEditing({ template })} onDelete={() => templates.remove(template)} />)}
              </ul>
            </section>)}
          </SectionCard>}

    {editing && <TemplateEditor template={editing.template} readOnly={!canManage} onClose={() => setEditing(null)} onSaved={() => { setEditing(null); templates.refresh(); }} />}
  </SettingsFrame>;
}

function TemplateRow({ template, canManage, onEdit, onDelete }) {
  const starter = isStarter(template);
  const action = ACTION_OPTIONS.find((option) => option.value === template.actionKey);
  return <li className="flex flex-wrap items-start gap-3 px-4 py-3 sm:flex-nowrap">
    <div className="grid min-w-0 flex-1 gap-1">
      <div className="flex min-w-0 flex-wrap items-center gap-2">
        <span className="truncate font-medium">{template.name}</span>
        {starter ? <Badge variant="secondary" className="gap-1"><Sparkles aria-hidden="true" />Starter</Badge> : <Badge variant="info">Your version</Badge>}
        {template.replaced && <Badge variant="neutral">Replaced by your version</Badge>}
        {template.isActive === false && <Badge variant="neutral">Inactive</Badge>}
      </div>
      <span className="truncate font-mono text-xs text-muted-foreground">{template.subjectTemplate}</span>
      <span className="text-xs text-muted-foreground">{[action ? `Default for: ${action.label}` : "Pick it from the Template menu in compose", !starter && template.updatedAt ? `Updated ${formatDate(template.updatedAt)}` : null].filter(Boolean).join(" · ")}</span>
    </div>
    <div className="flex shrink-0 items-center gap-2">
      {starter
        ? <Button variant="outline" size="sm" onClick={onEdit}>{canManage ? <><Pencil />Customise</> : <><Eye />View</>}</Button>
        : <Button variant="outline" size="sm" onClick={onEdit}>{canManage ? <><Pencil />Edit</> : <><Eye />View</>}</Button>}
      {!starter && canManage && <DropdownMenu>
        <DropdownMenuTrigger asChild><Button variant="ghost" size="icon-sm" aria-label={`More actions for ${template.name}`}><MoreHorizontal /></Button></DropdownMenuTrigger>
        <DropdownMenuContent align="end"><DropdownMenuItem variant="destructive" onSelect={onDelete}><Trash2 />Delete</DropdownMenuItem></DropdownMenuContent>
      </DropdownMenu>}
    </div>
  </li>;
}

function TemplateEditor({ template, readOnly, onClose, onSaved }) {
  const { form, guard, submit, mergeFields, preview, setPreview, runPreview } = useMailTemplateForm(template, { onSaved });
  const close = guard.guardOpenChange((open) => { if (!open) onClose(); });
  const editorRef = useRef(null);
  const subjectRef = useRef(null);
  const starter = template && isStarter(template);
  const submitting = form.formState.isSubmitting;
  const context = form.watch("contextType");
  const actionOptions = ACTION_OPTIONS.filter((option) => option.context === context || option.value === "record.email").map(({ value, label }) => ({ value, label }));

  const insertInSubject = (token) => {
    const input = subjectRef.current;
    const current = form.getValues("subjectTemplate");
    const start = input?.selectionStart ?? current.length;
    const end = input?.selectionEnd ?? current.length;
    form.setValue("subjectTemplate", `${current.slice(0, start)}${token}${current.slice(end)}`, { shouldDirty: true });
    window.requestAnimationFrame(() => { input?.focus(); input?.setSelectionRange(start + token.length, start + token.length); });
  };

  const title = readOnly ? template?.name : !template ? "New template" : starter ? `Customise “${template.name}”` : `Edit “${template.name}”`;

  return <Sheet open onOpenChange={close}>
    <SheetContent side="right" showCloseButton={false} className="w-full gap-0 p-0 sm:max-w-3xl"
      onEscapeKeyDown={(event) => { event.preventDefault(); close(false); }} onInteractOutside={(event) => { event.preventDefault(); close(false); }}>
      <SheetHeader className="relative border-b px-4 py-3 pr-12 sm:px-6">
        <SheetTitle className="text-lg">{title}</SheetTitle>
        <SheetDescription>{starter && !readOnly ? "Saving creates your organization's version; the starter stays as it is." : "Merge fields fill in from the record when someone starts an email."}</SheetDescription>
        <Button type="button" variant="ghost" size="icon-sm" className="absolute top-3 right-3" aria-label="Close" onClick={() => close(false)}><X /></Button>
      </SheetHeader>

      <form onSubmit={submit} noValidate className="flex min-h-0 flex-1 flex-col">
        <fieldset disabled={readOnly} className="grid flex-1 content-start gap-5 overflow-y-auto px-4 py-5 sm:px-6">
          <FormErrorAlert form={form} />
          <FieldGroup className="grid gap-4 sm:grid-cols-2">
            <TextField control={form.control} name="name" label="Template name" placeholder="Send quotation" className="sm:col-span-2" />
            <SelectField control={form.control} name="contextType" label="About" options={CONTEXT_OPTIONS} description="Decides which merge fields are available." disabled={readOnly} />
            <SelectField control={form.control} name="actionKey" label="Default for action" options={actionOptions} allowEmpty emptyLabel="None: pick it manually" description="Compose starts with this template for that action." disabled={readOnly} />
            <SelectField control={form.control} name="defaultRecipientRule" label="Default recipients" options={RECIPIENT_RULE_OPTIONS} disabled={readOnly} />
            <SwitchField control={form.control} name="isActive" label="Active" description="Inactive templates are hidden in compose." />
          </FieldGroup>

          <Controller control={form.control} name="subjectTemplate" render={({ field, fieldState }) => <Field data-invalid={fieldState.invalid}>
            <div className="flex items-center justify-between gap-2">
              <FieldLabel htmlFor="subjectTemplate">Subject</FieldLabel>
              {!readOnly && <MergeFieldPicker fields={mergeFields} onPick={insertInSubject} label="Insert field in subject" allowBlocks={false} />}
            </div>
            <Input id="subjectTemplate" ref={(node) => { field.ref(node); subjectRef.current = node; }} value={field.value} onChange={field.onChange} onBlur={field.onBlur} aria-invalid={fieldState.invalid} className="font-mono text-sm" />
            {fieldState.error ? <FieldError>{fieldState.error.message}</FieldError> : <FieldDescription>The record tag, e.g. [PO-20260924-0001], is added automatically when the mailbox has it on.</FieldDescription>}
          </Field>} />

          <Controller control={form.control} name="bodyTemplate" render={({ field, fieldState }) => <Field data-invalid={fieldState.invalid}>
            <FieldLabel htmlFor="bodyTemplate">Message</FieldLabel>
            <RichTextEditor ref={editorRef} id="bodyTemplate" aria-label="Message template" value={field.value} onChange={field.onChange} invalid={fieldState.invalid} disabled={readOnly} minHeight="min-h-56"
              toolbarEnd={!readOnly && <MergeFieldPicker fields={mergeFields} onPick={(token) => editorRef.current?.insertText(token)} label="Insert field" />} />
            {fieldState.error ? <FieldError>{fieldState.error.message}</FieldError> : <FieldDescription>The mailbox signature is added below the message; don&apos;t repeat it here.</FieldDescription>}
          </Field>} />

          <PreviewPanel preview={preview} setPreview={setPreview} runPreview={runPreview} />
        </fieldset>

        <div className="flex flex-wrap items-center justify-end gap-2 border-t px-4 py-3 sm:px-6">
          <Button type="button" variant="outline" onClick={() => close(false)}>{readOnly ? "Close" : "Cancel"}</Button>
          {!readOnly && <Button type="submit" disabled={submitting || (!starter && template && !form.formState.isDirty)}>{submitting && <Spinner />}{starter ? "Save my version" : template ? "Save changes" : "Create template"}</Button>}
        </div>
      </form>
    </SheetContent>
  </Sheet>;
}

// Inserts {{ field }} tokens; blocks (tables) only go in the message.
function MergeFieldPicker({ fields, onPick, label, allowBlocks = true }) {
  const [open, setOpen] = useState(false);
  const groups = {};
  fields.fields.forEach((field) => {
    const group = field.key.split(".")[0];
    (groups[group] ||= []).push(field);
  });

  return <Popover open={open} onOpenChange={setOpen}>
    <PopoverTrigger asChild><Button type="button" variant="ghost" size="sm" className="h-7 text-xs"><Braces />{label}</Button></PopoverTrigger>
    <PopoverContent align="end" className="w-80 p-0">
      <Command>
        <CommandInput placeholder="Search fields…" />
        <CommandList className="max-h-80">
          {fields.isLoading ? <div className="grid gap-2 p-2">{[0, 1, 2].map((index) => <Skeleton key={index} className="h-8" />)}</div> : <CommandEmpty>No field matches.</CommandEmpty>}
          {Object.entries(groups).map(([group, items]) => <CommandGroup key={group} heading={group.replaceAll("_", " ")}>
            {items.map((field) => <CommandItem key={field.key} value={`${field.key} ${field.label}`} onSelect={() => { onPick(`{{${field.key}}}`); setOpen(false); }}>
              <span className="grid min-w-0">
                <span className="truncate">{field.label}</span>
                <span className="truncate font-mono text-xs text-muted-foreground">{`{{${field.key}}}`}{field.example ? ` · ${field.example}` : ""}</span>
              </span>
            </CommandItem>)}
          </CommandGroup>)}
          {allowBlocks && fields.blocks.length > 0 && <CommandGroup heading="Blocks">
            {fields.blocks.map((block) => <CommandItem key={block.key} value={`${block.key} ${block.label}`} onSelect={() => { onPick(`{{${block.key}}}`); setOpen(false); }}>
              <span className="grid"><span>{block.label}</span><span className="font-mono text-xs text-muted-foreground">{`{{${block.key}}}`}</span></span>
            </CommandItem>)}
          </CommandGroup>}
        </CommandList>
      </Command>
    </PopoverContent>
  </Popover>;
}

function PreviewPanel({ preview, setPreview, runPreview }) {
  const result = preview.result;
  return <section className="grid gap-3 rounded-lg border bg-muted/30 p-3" aria-label="Preview">
    <div className="flex flex-wrap items-end gap-2">
      <div className="grid gap-1.5">
        <label htmlFor="preview-type" className="text-sm font-medium">Preview with</label>
        <Select value={preview.type} onValueChange={(type) => setPreview((current) => ({ ...current, type }))}>
          <SelectTrigger id="preview-type" className="w-32"><SelectValue /></SelectTrigger>
          <SelectContent>{PREVIEW_TYPE_OPTIONS.map((option) => <SelectItem key={option.value} value={option.value}>{option.label}</SelectItem>)}</SelectContent>
        </Select>
      </div>
      <Input aria-label="Record code" value={preview.code} placeholder="Record code, e.g. PO-20260924-0001" className="min-w-48 flex-1"
        onChange={(event) => setPreview((current) => ({ ...current, code: event.target.value }))}
        onKeyDown={(event) => { if (event.key === "Enter") { event.preventDefault(); runPreview(); } }} />
      <Button type="button" variant="outline" disabled={preview.status === "running"} onClick={runPreview}>{preview.status === "running" ? <Spinner /> : <Eye />}Preview</Button>
    </div>
    {preview.status === "error" && <p className="text-sm text-destructive">{describeError(preview.error)}</p>}
    {preview.status === "idle" && <p className="text-xs text-muted-foreground">See exactly what a sender starts with for a real record. Nothing is sent.</p>}
    {result && <div className="grid gap-2 rounded-md border bg-background p-3">
      {result.unknownFields?.length > 0 && <Alert className="border-warning/40 bg-warning/5 [&>svg]:text-warning"><AlertTriangle /><AlertDescription>These fields can't be filled for this record: {result.unknownFields.map((key) => `{{${key}}}`).join(", ")}</AlertDescription></Alert>}
      <p className="text-sm"><span className="text-muted-foreground">Subject: </span><span className="font-medium">{result.subject}</span></p>
      <HtmlPreview html={result.bodyHtml} title="Template preview" />
    </div>}
  </section>;
}
