"use client";

import { useState } from "react";
import { useRouter } from "next/navigation";
import ImageUploader from "@/components/image-uploader";
import { fromEatInputValue, toEatInputValue } from "@/lib/format";
import type { CategoryRow, EventRow } from "@/lib/types";

// Inline editor for an existing event's details -- everything an organizer
// might need to correct after publishing: name, dates, place, description.
export default function EventDetailsForm({
  event,
  categories,
}: {
  event: Omit<EventRow, "fee_bps">;
  categories: CategoryRow[];
}) {
  const router = useRouter();
  const [title, setTitle] = useState(event.title);
  const [venue, setVenue] = useState(event.venue ?? "");
  const [description, setDescription] = useState(event.description ?? "");
  const [categoryId, setCategoryId] = useState(event.category_id ?? "");
  const [cover, setCover] = useState(event.cover_image_url ?? "");
  const [city, setCity] = useState(event.city ?? "");
  const [organizerName, setOrganizerName] = useState(event.organizer_name ?? "");
  const [ageRestriction, setAgeRestriction] = useState(event.age_restriction ?? "");
  const [startsAt, setStartsAt] = useState(toEatInputValue(event.starts_at));
  const [endsAt, setEndsAt] = useState(toEatInputValue(event.ends_at));
  const [organizerPhone, setOrganizerPhone] = useState(event.organizer_phone ?? "");
  const [organizerEmail, setOrganizerEmail] = useState(event.organizer_email ?? "");
  const [saving, setSaving] = useState(false);
  const [msg, setMsg] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  // Set after a save that moved the date or venue of an event with ticket
  // holders; accumulates across saves until the organizer sends or dismisses.
  const [pendingNotice, setPendingNotice] = useState<{ changes: Change[]; holders: number } | null>(null);
  const [notifying, setNotifying] = useState(false);
  const [notifyResult, setNotifyResult] = useState<{ ok: boolean; text: string } | null>(null);

  async function notifyHolders() {
    if (!pendingNotice) return;
    setNotifying(true);
    setNotifyResult(null);
    const res = await fetch(`/api/dashboard/events/${event.id}/notify-change`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ changes: pendingNotice.changes }),
    }).catch(() => null);
    const data = res ? await res.json().catch(() => ({})) : {};
    setNotifying(false);
    if (!res || !res.ok) {
      setNotifyResult({ ok: false, text: data.error ?? "Couldn't send the update." });
      return;
    }
    setPendingNotice(null);
    setNotifyResult({ ok: true, text: describeDelivery(data) });
  }

  async function save() {
    setMsg(null);
    setError(null);

    const startsIso = fromEatInputValue(startsAt);
    const endsIso = endsAt ? fromEatInputValue(endsAt) : null;
    if (!title.trim()) return setError("The event needs a title.");
    if (!startsIso) return setError("Pick a start date and time.");
    if (endsAt && !endsIso) return setError("The end date and time isn't valid.");
    if (endsIso && endsIso <= startsIso) return setError("The event has to end after it starts.");

    setSaving(true);
    const res = await fetch(`/api/dashboard/events/${event.id}`, {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        title: title.trim(),
        venue: venue.trim() || null,
        city: city.trim() || null,
        organizerName: organizerName.trim() || null,
        ageRestriction: ageRestriction.trim() || null,
        startsAt: startsIso,
        endsAt: endsIso,
        description: description || null,
        categoryId: categoryId || null,
        coverImageUrl: cover || null,
        organizerPhone: organizerPhone || null,
        organizerEmail: organizerEmail || null,
      }),
    }).catch(() => null);
    setSaving(false);
    if (!res || !res.ok) {
      const data = res ? await res.json().catch(() => ({})) : {};
      setError(data.error ?? "Could not save");
      return;
    }
    const data: { changes?: Change[]; holders?: number } = await res.json().catch(() => ({}));
    setMsg("Saved. The event page shows the changes now.");
    if (data.changes?.length && data.holders) {
      setNotifyResult(null);
      setPendingNotice((prev) => ({
        changes: [...new Set([...(prev?.changes ?? []), ...data.changes!])],
        holders: data.holders!,
      }));
    }
    router.refresh();
  }

  return (
    <div className="rounded-lg border border-be-border bg-be-surface p-4 space-y-4">
      <div className="grid gap-4 sm:grid-cols-2">
        <Field label="Title">
          <input value={title} onChange={(e) => setTitle(e.target.value)} className="input" />
        </Field>
        <Field label="Presented by" hint="Shown as “By …” on the event page">
          <input value={organizerName} onChange={(e) => setOrganizerName(e.target.value)} className="input" />
        </Field>
      </div>
      <div className="grid gap-4 sm:grid-cols-2">
        <Field label="Starts" hint="Kenya time (EAT)">
          <input
            type="datetime-local"
            required
            value={startsAt}
            onChange={(e) => setStartsAt(e.target.value)}
            className="input"
          />
        </Field>
        <Field label="Ends" hint="Optional · Kenya time (EAT)">
          <input
            type="datetime-local"
            value={endsAt}
            min={startsAt || undefined}
            onChange={(e) => setEndsAt(e.target.value)}
            className="input"
          />
        </Field>
      </div>
      <div className="grid gap-4 sm:grid-cols-3">
        <Field label="Venue">
          <input value={venue} onChange={(e) => setVenue(e.target.value)} className="input" />
        </Field>
        <Field label="City / town">
          <input value={city} onChange={(e) => setCity(e.target.value)} className="input" />
        </Field>
        <Field label="Age limit" hint="Optional, e.g. 18+">
          <input value={ageRestriction} onChange={(e) => setAgeRestriction(e.target.value)} className="input" />
        </Field>
      </div>
      <Field label="Description">
        <textarea
          value={description}
          onChange={(e) => setDescription(e.target.value)}
          rows={3}
          className="input"
        />
      </Field>
      <Field label="Category">
        <select
          value={categoryId}
          onChange={(e) => setCategoryId(e.target.value)}
          className="input"
        >
          <option value="">— None —</option>
          {categories.map((c) => (
            <option key={c.id} value={c.id}>
              {c.name}
            </option>
          ))}
        </select>
      </Field>
      <div className="grid gap-4 sm:grid-cols-2">
        <Field label="Organizer phone number">
          <input
            type="tel"
            placeholder="07XX XXX XXX"
            value={organizerPhone}
            onChange={(e) => setOrganizerPhone(e.target.value)}
            className="input"
          />
        </Field>
        <Field label="Organizer contact email">
          <input
            type="email"
            placeholder="you@example.com"
            value={organizerEmail}
            onChange={(e) => setOrganizerEmail(e.target.value)}
            className="input"
          />
        </Field>
      </div>
      <ImageUploader value={cover} onChange={setCover} folder="events" label="Cover image" />
      <div className="flex items-center gap-3">
        <button
          onClick={save}
          disabled={saving}
          className="rounded-md bg-brand-green px-4 py-2 text-sm font-medium text-white hover:bg-brand-green-deep disabled:opacity-50"
        >
          {saving ? "Saving…" : "Save details"}
        </button>
        {msg && <p className="text-sm text-green-600">{msg}</p>}
        {error && <p className="text-sm text-red-600">{error}</p>}
      </div>

      {pendingNotice && (
        <div className="space-y-3 rounded-lg border border-[color:var(--pill-warn-fg)] bg-be-surface-2 p-4">
          <p className="text-sm text-be-text">
            You changed the <strong>{describe(pendingNotice.changes)}</strong>. This event has{" "}
            <strong>
              {pendingNotice.holders} ticket holder{pendingNotice.holders === 1 ? "" : "s"}
            </strong>
            . Let them know?
          </p>
          <p className="text-xs text-be-muted">
            They&apos;ll get an email and an SMS with the new details, saying their tickets are still valid. If
            you&apos;re still making corrections, finish first — you can send one update every 10 minutes.
          </p>
          <div className="flex flex-wrap gap-2">
            <button
              type="button"
              onClick={notifyHolders}
              disabled={notifying}
              className="rounded-md bg-brand-green px-4 py-2 text-sm font-medium text-white hover:bg-brand-green-deep disabled:opacity-50"
            >
              {notifying ? "Sending…" : `Notify ${pendingNotice.holders} ticket holder${pendingNotice.holders === 1 ? "" : "s"}`}
            </button>
            <button
              type="button"
              onClick={() => setPendingNotice(null)}
              disabled={notifying}
              className="rounded-md border border-be-border px-4 py-2 text-sm font-medium hover:bg-be-surface"
            >
              Not now
            </button>
          </div>
        </div>
      )}
      {notifyResult && (
        <p className={`text-sm ${notifyResult.ok ? "text-green-600" : "text-red-600"}`}>{notifyResult.text}</p>
      )}
    </div>
  );
}

type Change = "date" | "venue";

function describe(changes: Change[]) {
  return [changes.includes("date") && "date and time", changes.includes("venue") && "venue"].filter(Boolean).join(" and ");
}

type Outcome = { status: "sent" | "not_configured" | "failed" | "partial"; sent: number; failed: number };

function describeDelivery(data: { holders?: number; email?: Outcome; sms?: Outcome }) {
  const part = (label: string, o?: Outcome) => {
    if (!o) return null;
    if (o.status === "not_configured") return `${label}: not set up, nothing sent`;
    if (o.sent === 0 && o.failed === 0) return `${label}: no one to send to`;
    return `${label}: ${o.sent} sent${o.failed ? `, ${o.failed} failed` : ""}`;
  };
  return [`Update sent to ${data.holders ?? 0} ticket holder(s).`, part("Email", data.email), part("SMS", data.sms)]
    .filter(Boolean)
    .join(" · ");
}

function Field({ label, hint, children }: { label: string; hint?: string; children: React.ReactNode }) {
  return (
    <div>
      <label className="block text-sm font-medium mb-1">
        {label} {hint && <span className="font-normal text-be-muted">· {hint}</span>}
      </label>
      {children}
    </div>
  );
}
