"use client";

import { useMemo, useState } from "react";
import { AlertTriangle } from "lucide-react";
import { Button, Dialog, Field, Input, Select } from "@/components/ui/kit";
import { useToast } from "@/components/ui/toast";
import { PreviewFrame } from "@/components/templates/template-preview";
import { api, ApiError } from "@/lib/api";
import { useApi } from "@/lib/use-api";
import type { BotAsset, BotReply, CustomField, ReplyType, TriggerType, WhatsAppAccount } from "@/lib/types";
import { ContentEditor, defaultContent, type AnyContent } from "./content-editor";
import { ReplyBubble } from "./reply-preview";

export const TRIGGERS: { value: TriggerType; label: string; help: string }[] = [
  { value: "welcome", label: "Welcome (first message)", help: "Sent to someone the first time they message this number, if no keyword reply matches." },
  { value: "is", label: "Is exactly", help: "The whole message must equal the trigger text. Case, extra spaces and end punctuation are ignored." },
  { value: "starts_with", label: "Starts with", help: "Fires when the message starts with the trigger text." },
  { value: "ends_with", label: "Ends with", help: "Fires when the message ends with the trigger text." },
  { value: "contains_word", label: "Contains the word", help: "Fires when the trigger appears as a whole word or phrase, so “ship” matches “do you ship?” but not “shipping”." },
  { value: "contains", label: "Contains", help: "Fires when the trigger appears anywhere in the message, even inside a longer word." },
];

export const REPLY_TYPE_LABEL: Record<ReplyType, string> = { text: "Text reply", media: "Media reply", interactive: "Interactive reply" };

/** Create or edit a bot reply. `initial` edits; otherwise `type` picks the kind of new reply. */
export function BotReplyDialog({ initial, type, onClose, onSaved }: { initial?: BotReply; type: ReplyType; onClose: () => void; onSaved: (r: BotReply, warnings: string[]) => void }) {
  const toast = useToast();
  const accounts = useApi<{ data: WhatsAppAccount[] }>("/whatsapp/accounts");
  const fieldsReq = useApi<{ data: CustomField[] }>("/custom-fields");
  const customFields = useMemo(() => fieldsReq.data?.data ?? [], [fieldsReq.data]);
  const numbers = (accounts.data?.data ?? []).filter((a) => a.status !== "disconnected");

  const replyType = initial?.reply_type ?? type;
  const [name, setName] = useState(initial?.name ?? "");
  const [triggerType, setTriggerType] = useState<TriggerType>(initial?.trigger_type ?? "is");
  const [subject, setSubject] = useState(initial?.trigger_subject ?? "");
  const [accountId, setAccountId] = useState<number | null>(initial?.whatsapp_account?.id ?? null);
  const [active, setActive] = useState(initial ? initial.status === "active" : true);
  const [content, setContent] = useState<AnyContent>(() => (initial ? (structuredClone(initial.content) as AnyContent) : defaultContent(replyType)));
  const [assets, setAssets] = useState<Record<number, BotAsset>>(() => Object.fromEntries((initial?.assets ?? []).map((a) => [a.id, a])));
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [saving, setSaving] = useState(false);

  const contentErrors = useMemo(() => Object.fromEntries(Object.entries(errors).filter(([k]) => k.startsWith("content.")).map(([k, v]) => [k.slice(8), v])), [errors]);
  const custom = useMemo(() => Object.fromEntries(customFields.map((f) => [f.key, `[${f.label}]`])), [customFields]);
  const trigger = TRIGGERS.find((t) => t.value === triggerType)!;

  async function save() {
    setSaving(true);
    setErrors({});
    const body = { name, reply_type: replyType, trigger_type: triggerType, trigger_subject: triggerType === "welcome" ? undefined : subject, whatsapp_account_id: accountId, status: active ? "active" : "inactive", content };
    try {
      const r = initial ? await api.patch<{ data: BotReply; warnings: string[] }>(`/bot-replies/${initial.id}`, body) : await api.post<{ data: BotReply; warnings: string[] }>("/bot-replies", body);
      onSaved(r.data, r.warnings ?? []);
    } catch (err) {
      if (err instanceof ApiError && Object.keys(err.fields).length) {
        setErrors(err.fields);
        requestAnimationFrame(() => document.querySelector<HTMLElement>("dialog[open] [aria-invalid=true], dialog[open] [role=alert]")?.scrollIntoView({ block: "center", behavior: "smooth" }));
      } else toast("error", (err as Error).message);
    } finally {
      setSaving(false);
    }
  }

  return (
    <Dialog
      open
      onClose={onClose}
      size="lg"
      title={initial ? `Edit ${initial.name}` : `New ${REPLY_TYPE_LABEL[replyType].toLowerCase()}`}
      description="Sent automatically when an incoming message matches the trigger, inside the 24-hour reply window."
      footer={
        <>
          <label className="mr-auto flex items-center gap-2 text-sm">
            <input type="checkbox" role="switch" className="size-4 accent-teal" checked={active} onChange={(e) => setActive(e.target.checked)} />
            Active
          </label>
          <Button onClick={onClose}>Cancel</Button>
          <Button variant="primary" loading={saving} onClick={save}>
            {initial ? "Save changes" : "Create reply"}
          </Button>
        </>
      }
    >
      <div className="grid gap-6 md:grid-cols-[minmax(0,1fr)_280px]">
        <div className="space-y-6">
          <Field label="Name" htmlFor="br-name" error={errors.name} hint="For your team, e.g. Opening hours">
            <Input id="br-name" value={name} onChange={(e) => setName(e.target.value)} maxLength={120} invalid={!!errors.name} autoFocus={!initial} />
          </Field>

          <fieldset className="space-y-3 rounded-lg border border-line p-4">
            <legend className="px-1 text-[13px] font-semibold">When to send it</legend>
            <div className="grid gap-3 sm:grid-cols-2">
              <Field label="Trigger" htmlFor="br-tt" error={errors.trigger_type}>
                <Select id="br-tt" value={triggerType} onChange={(e) => setTriggerType(e.target.value as TriggerType)} invalid={!!errors.trigger_type}>
                  {TRIGGERS.map((t) => (
                    <option key={t.value} value={t.value}>
                      {t.label}
                    </option>
                  ))}
                </Select>
              </Field>
              {triggerType !== "welcome" && (
                <Field label="Trigger text" htmlFor="br-ts" error={errors.trigger_subject}>
                  <Input id="br-ts" value={subject} onChange={(e) => setSubject(e.target.value)} maxLength={255} invalid={!!errors.trigger_subject} placeholder="e.g. price" />
                </Field>
              )}
            </div>
            <p className="rounded-md bg-ink px-3 py-2 text-[13px] text-white/85">{trigger.help}</p>
            {numbers.length > 1 && (
              <Field label="Number" htmlFor="br-acc" error={errors.whatsapp_account_id}>
                <Select id="br-acc" value={accountId ?? ""} onChange={(e) => setAccountId(e.target.value ? Number(e.target.value) : null)}>
                  <option value="">All numbers</option>
                  {numbers.map((a) => (
                    <option key={a.id} value={a.id}>
                      {a.display_phone_number ?? a.phone_number_id}
                    </option>
                  ))}
                </Select>
              </Field>
            )}
          </fieldset>

          <fieldset className="space-y-4">
            <legend className="mb-2 text-[13px] font-semibold">Reply</legend>
            <ContentEditor type={replyType} content={content} onChange={setContent} errors={contentErrors} customFields={customFields} assets={assets} onAsset={(a) => setAssets((m) => ({ ...m, [a.id]: a }))} />
          </fieldset>
          {Object.keys(errors).some((k) => !["name", "trigger_type", "trigger_subject", "whatsapp_account_id"].includes(k) && !k.startsWith("content.")) && (
            <p className="flex items-center gap-2 text-[13px] text-brick">
              <AlertTriangle className="size-4" /> Some settings need attention.
            </p>
          )}
        </div>
        <aside className="md:sticky md:top-0 md:self-start">
          <p className="mb-2 text-[13px] font-medium text-muted">Preview with a sample contact</p>
          <PreviewFrame>
            <ReplyBubble type={replyType} content={content} assets={assets} custom={custom} />
          </PreviewFrame>
        </aside>
      </div>
    </Dialog>
  );
}
