"use client";

/**
 * The two greeting sentences per language (task 8.7, design D9).
 *
 * Four fields, one save. The limit is 100 characters and the counter is live, because the
 * alternative — typing a paragraph and being told no on submit — is the version of this
 * screen that wastes the customer's time.
 *
 * The helper text says *why* the limit exists. "Max 100" reads as an arbitrary restriction;
 * "the greeting sits above the artwork" is a reason someone can design around.
 */
import { useEffect, useState } from "react";

import { api, type Wedding } from "@/lib/api/browser";

import { Button, Card, ErrorNote, Loading } from "./ui";

const MAX = 100;

const FIELDS: { locale: "en" | "bn"; type: "single" | "family"; label: string }[] = [
  { locale: "en", type: "single", label: "English — single guest" },
  { locale: "en", type: "family", label: "English — family" },
  { locale: "bn", type: "single", label: "বাংলা — single guest" },
  { locale: "bn", type: "family", label: "বাংলা — family" },
];

/** What a guest sees when the field is left empty. Shown as placeholder, so the customer can
 * see the fallback rather than guessing at what "blank" does. */
const DEFAULTS: Record<string, string> = {
  "en:single": "You are cordially invited",
  "en:family": "You and your family are cordially invited",
  "bn:single": "আপনাকে সাদর আমন্ত্রণ",
  "bn:family": "আপনাকে ও আপনার পরিবারকে সাদর আমন্ত্রণ",
};

export default function InvitationMessages({ canEdit }: { canEdit: boolean }) {
  const [wedding, setWedding] = useState<Wedding | null>(null);
  const [values, setValues] = useState<Record<string, string>>({});
  const [error, setError] = useState<unknown>(null);
  const [saved, setSaved] = useState(false);
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    void api
      .wedding()
      .then((w) => {
        setWedding(w);
        const flat: Record<string, string> = {};
        for (const { locale, type } of FIELDS) {
          flat[`${locale}:${type}`] = w.invitation_messages?.[locale]?.[type] ?? "";
        }
        setValues(flat);
      })
      .catch(setError);
  }, []);

  async function save() {
    setSaving(true);
    setError(null);
    setSaved(false);
    try {
      // Sent as the whole map, so emptying a field is expressible — with a partial update,
      // "not sent" and "cleared" would be the same request.
      const messages: Record<string, Record<string, string>> = {};
      for (const { locale, type } of FIELDS) {
        const value = values[`${locale}:${type}`]?.trim();
        if (value) (messages[locale] ??= {})[type] = value;
      }
      setWedding(await api.saveInvitationMessages(messages));
      setSaved(true);
    } catch (err) {
      setError(err);
    } finally {
      setSaving(false);
    }
  }

  if (!wedding) return <Loading label="Loading messages…" />;

  const overLimit = FIELDS.some(({ locale, type }) => (values[`${locale}:${type}`] ?? "").length > MAX);

  return (
    <Card title="Invitation messages">
      <p className="mb-4 text-sm text-stone-600">
        The sentence under the guest&apos;s name. Each is limited to {MAX} characters — the
        greeting sits above the card artwork, and a paragraph there crowds the design it is
        meant to introduce. Leave one blank to use the wording shown in grey.
      </p>

      <div className="grid gap-4 sm:grid-cols-2">
        {FIELDS.map(({ locale, type, label }) => {
          const key = `${locale}:${type}`;
          const value = values[key] ?? "";
          const over = value.length > MAX;
          return (
            <div key={key}>
              <label
                htmlFor={`msg-${key}`}
                className="mb-1 flex items-baseline justify-between text-xs font-medium text-stone-600"
              >
                <span>{label}</span>
                <span className={over ? "font-semibold text-red-700" : "text-stone-400"}>
                  {value.length}/{MAX}
                </span>
              </label>
              <textarea
                id={`msg-${key}`}
                rows={2}
                disabled={!canEdit}
                value={value}
                placeholder={DEFAULTS[key]}
                onChange={(e) => setValues((v) => ({ ...v, [key]: e.target.value }))}
                // No maxLength: truncating as they type hides that they went over. The
                // counter turning red says it, and the API says it again on save.
                className={
                  over
                    ? "block w-full rounded-md border border-red-400 px-3 py-2 text-sm"
                    : "block w-full rounded-md border border-stone-300 px-3 py-2 text-sm"
                }
              />
            </div>
          );
        })}
      </div>

      <ErrorNote error={error} />

      {canEdit && (
        <div className="mt-4 flex items-center justify-end gap-3 border-t border-stone-100 pt-4">
          {saved && <span className="text-sm text-emerald-700">Saved.</span>}
          <Button onClick={() => void save()} disabled={saving || overLimit}>
            {saving ? "Saving…" : "Save messages"}
          </Button>
        </div>
      )}
    </Card>
  );
}
