import Link from "next/link";
import { redirect } from "next/navigation";
import { TONE } from "@/components/Chip";
import type { ItemKind } from "@/db/schema";
import { getPeople, type PersonWithItems } from "@/lib/data";
import { joinNames, norm } from "@/lib/text";

export const metadata = { title: "Cena · AmiCibi" };

type Restriction = { label: string; who: { name: string; foods: string[] }[] };
type Tally = { label: string; names: string[] };

type Short = (name: string) => string;

// Nome di battesimo, a meno che due invitati non si chiamino uguale (i due Lorenzo)
function shortNames(people: PersonWithItems[]): Short {
  const firstOf = (name: string) => name.split(" ")[0];
  const counts = new Map<string, number>();
  for (const p of people) counts.set(firstOf(p.name), (counts.get(firstOf(p.name)) ?? 0) + 1);
  return (name) => ((counts.get(firstOf(name)) ?? 0) > 1 ? name : firstOf(name));
}

// Raggruppa per voce, così "Nichel" di due persone diventa una riga sola
function restrictions(people: PersonWithItems[], kind: ItemKind): Restriction[] {
  const map = new Map<string, Restriction>();
  for (const p of people) {
    for (const top of p.items.filter((i) => i.kind === kind && !i.parentId)) {
      const key = norm(top.label);
      const entry = map.get(key) ?? { label: top.label, who: [] };
      entry.who.push({ name: p.name, foods: p.items.filter((i) => i.parentId === top.id).map((i) => i.label) });
      map.set(key, entry);
    }
  }
  return [...map.values()].sort((a, b) => b.who.length - a.who.length || a.label.localeCompare(b.label, "it"));
}

function tally(people: PersonWithItems[], kind: ItemKind): Tally[] {
  const map = new Map<string, Tally>();
  for (const p of people) {
    for (const i of p.items.filter((i) => i.kind === kind)) {
      const key = norm(i.label);
      const entry = map.get(key) ?? { label: i.label, names: [] };
      if (!entry.names.includes(p.name)) entry.names.push(p.name);
      map.set(key, entry);
    }
  }
  return [...map.values()].sort((a, b) => b.names.length - a.names.length || a.label.localeCompare(b.label, "it"));
}

export default async function DinnerPage({ searchParams }: PageProps<"/cena">) {
  const { ospiti } = await searchParams;
  const ids = typeof ospiti === "string" ? ospiti.split(",").filter(Boolean).slice(0, 40) : [];
  const people = await getPeople(ids);
  if (!people.length) redirect("/");
  const first = shortNames(people);

  const allergies = restrictions(people, "allergy");
  const intolerances = restrictions(people, "intolerance");
  const dislikes = tally(people, "dislike");
  const favorites = tally(people, "favorite");
  const notes = people.filter((p) => p.notes);
  const many = people.length > 1;

  return (
    <div className="flex min-h-dvh flex-col">
      <header className="gingham safe-top rounded-b-[28px] shadow-[0_6px_20px_-12px_rgba(28,42,82,0.6)]">
        <div className="mx-auto max-w-2xl px-5 pb-6">
        <div className="flex items-center justify-between pt-4">
          <Link href={`/?ospiti=${ids.join(",")}`} className="-ml-2 rounded-field px-2 py-2 text-[15px] font-bold">
            ‹ Cambia invitati
          </Link>
        </div>
        <h1 className="mt-2 font-display text-[34px] leading-[1.1] [text-shadow:0_2px_0_rgba(28,42,82,0.35)]">A cena con…</h1>
        <p className="mt-2 text-[17px] leading-snug font-bold">{joinNames(people.map((p) => p.name))}</p>
        </div>
      </header>

      <main className="mx-auto flex w-full max-w-2xl flex-col gap-4 px-3 pt-4 pb-12">
        {allergies.length + intolerances.length === 0 ? (
          <p className="rounded-card bg-fav-soft px-4 py-3 font-semibold text-fav-ink">
            Nessuna allergia né intolleranza segnata. Via libera!
          </p>
        ) : (
          <>
            <RestrictionBlock kind="allergy" title="Allergie" items={allergies} first={first} />
            <RestrictionBlock kind="intolerance" title="Intolleranze" items={intolerances} first={first} />
          </>
        )}

        {notes.length > 0 && (
          <section className="flex flex-col gap-2 rounded-card bg-surface p-4">
            <h2 className="text-[13px] font-extrabold tracking-wider text-ink uppercase">Note</h2>
            {notes.map((p) => (
              <p key={p.id} className="text-[15px]">
                <span className="font-extrabold">{first(p.name)}:</span> {p.notes}
              </p>
            ))}
          </section>
        )}

        <TallyBlock kind="dislike" title="Meglio evitare" items={dislikes} many={many} first={first} />
        <TallyBlock kind="favorite" title={many ? "Piatti graditi" : "Piatti preferiti"} items={favorites} many={many} first={first} />

        <section className="flex flex-col gap-1 px-1 pt-2">
          <h2 className="text-xs font-extrabold tracking-wider text-muted uppercase">Schede</h2>
          <div className="flex flex-wrap gap-2 pt-1">
            {people.map((p) => (
              <Link key={p.id} href={`/persona/${p.id}`} className="rounded-chip bg-surface px-3 py-2 text-sm font-bold ring-2 ring-line">
                {p.name}
              </Link>
            ))}
          </div>
        </section>
      </main>
    </div>
  );
}

function RestrictionBlock({ kind, title, items, first }: { kind: ItemKind; title: string; items: Restriction[]; first: Short }) {
  if (!items.length) return null;
  return (
    <section className={`flex flex-col gap-4 rounded-card bg-surface p-4 ${kind === "allergy" ? "ring-2 ring-all" : ""}`}>
      <h2 className={`flex items-center gap-2 text-[13px] font-extrabold tracking-wider uppercase ${TONE[kind].text}`}>
        <span className={`size-2.5 rounded-full ${TONE[kind].dot}`} />
        {title}
      </h2>
      {items.map((r) => (
        <div key={r.label} className="flex flex-col gap-2">
          <div className="flex flex-wrap items-baseline gap-x-2">
            <h3 className="font-display text-xl">{r.label}</h3>
            <span className="text-sm font-bold text-muted">{joinNames(r.who.map((w) => first(w.name)))}</span>
          </div>
          {r.who.length === 1
            ? r.who[0].foods.length > 0 && <FoodChips kind={kind} foods={r.who[0].foods} />
            : r.who
                .filter((w) => w.foods.length > 0)
                .map((w) => (
                  <div key={w.name} className="flex flex-col gap-1.5">
                    <span className="text-sm font-extrabold">{first(w.name)} non può:</span>
                    <FoodChips kind={kind} foods={w.foods} />
                  </div>
                ))}
        </div>
      ))}
    </section>
  );
}

function TallyBlock({ kind, title, items, many, first }: { kind: ItemKind; title: string; items: Tally[]; many: boolean; first: Short }) {
  if (!items.length) return null;
  return (
    <section className="flex flex-col gap-3 rounded-card bg-surface p-4">
      <h2 className={`flex items-center gap-2 text-[13px] font-extrabold tracking-wider uppercase ${TONE[kind].text}`}>
        <span className={`size-2.5 rounded-full ${TONE[kind].dot}`} />
        {title}
      </h2>
      <ul className="flex flex-col">
        {items.map((t) => (
          <li key={t.label} className="flex items-baseline justify-between gap-3 border-t border-line py-2 first:border-t-0 first:pt-0">
            <span className="font-bold">{t.label}</span>
            {many && <span className="text-right text-sm text-muted">{joinNames(t.names.map(first))}</span>}
          </li>
        ))}
      </ul>
    </section>
  );
}

function FoodChips({ kind, foods }: { kind: ItemKind; foods: string[] }) {
  return (
    <div className="flex flex-wrap gap-1.5">
      {foods.map((f) => (
        <span key={f} className={`rounded-chip px-2.5 py-1 text-sm font-bold ${TONE[kind].chip}`}>
          {f}
        </span>
      ))}
    </div>
  );
}
