import { Zap, FlaskConical, ClipboardList, Syringe, Snowflake, AlertCircle, Lightbulb, Scale, Dumbbell, Pipette, Link2, HelpCircle, type LucideIcon } from "lucide-react";
import ProductAssistant from "@/components/ProductAssistant";
import Breadcrumbs from "@/components/Breadcrumbs";
import { useEffect, useState } from "react";
import { createFileRoute, Link, notFound } from "@tanstack/react-router";
import { SectionLabel } from "@/components/kennisbank/SectionLabel";
import { ShopLink } from "@/components/kennisbank/ShopLink";
import { PeptideCard } from "@/components/kennisbank/PeptideCard";
import { categories, getPeptide, peptides } from "@/content/kennisbank/peptides";
import { getDetail } from "@/content/kennisbank/peptideDetails";
import { langParam, pageHead, tr, ui, useLang, type L10n } from "@/lib/kennisbank-i18n";
import { headLang } from "@/lib/i18n";
import { getKennisbank, type KennisbankL10n } from "@/lib/content.functions";
import { sanitizedHtml, stripHtml } from "@/lib/sanitize";

export const Route = createFileRoute("/kennisbank/$slug")({
  /**
   * The knowledge base is managed in the admin panel and arrives through the
   * content snapshot. The content in this codebase is the fallback for an
   * installation where nothing has been imported yet.
   */
  loader: async ({ params }) => {
    const kennisbank = await getKennisbank();
    const item = kennisbank?.items.find((entry) => entry.slug === params.slug);
    const p = item ?? getPeptide(params.slug);

    if (!p) throw notFound();

    const d = item ? item.details : getDetail(params.slug);

    if (!d) throw notFound();

    const all = kennisbank?.items.length ? kennisbank.items : peptides;
    const labels: Record<string, KennisbankL10n> = kennisbank?.categories.length
      ? Object.fromEntries(kennisbank.categories.map((c) => [c.slug, c.name]))
      : (categories as Record<string, KennisbankL10n>);

    return {
      slug: p.slug,
      p,
      d,
      categoryLabel: labels[p.category ?? ""] ?? null,
      related: all.filter((x) => x.slug !== p.slug && x.category === p.category).slice(0, 4),
    };
  },
  head: (ctx) => {
    const p = ctx.loaderData?.p;
    if (!p) return { meta: [{ title: "Not found" }, { name: "robots", content: "noindex" }] };
    const lang = headLang(ctx);
    const item = "metaTitle" in p ? p.metaTitle : null;
    const description = ("metaDescription" in p ? p.metaDescription : null) ?? stripHtml(tr(p.intro, lang)).slice(0, 155);
    const title = item
      ? `${item} | Peptidewinkel`
      : lang === "en"
        ? `${p.name}: dosing, reconstitution & research | Peptidewinkel`
        : `${p.name}: dosering, reconstitutie & onderzoek | Peptidewinkel`;
    const head = pageHead(`/kennisbank/${p.slug}`, title, description, lang);
    return {
      ...head,
      meta: [...head.meta, { property: "og:type", content: "article" }],
      scripts: [{
        type: "application/ld+json",
        children: JSON.stringify({
          "@context": "https://schema.org",
          "@type": "FAQPage",
          mainEntity: p.faq.map((f) => ({ "@type": "Question", name: tr(f.q, lang), acceptedAnswer: { "@type": "Answer", text: tr(f.a, lang) } })),
        }),
      }],
    };
  },
  notFoundComponent: () => <div className="mx-auto max-w-3xl px-6 py-24 text-center text-3xl font-black">Peptide not found</div>,
  component: Detail,
});

function List({ items, lang }: { items: L10n[]; lang: "nl" | "en" }) {
  return <ul>{items.map((i) => <li key={i.nl}>{tr(i, lang)}</li>)}</ul>;
}

/**
 * The profile texts of a knowledge base item are written in the admin editor and
 * arrive as HTML. They used to be printed as plain text, which showed the tags;
 * copy that was entered without markup still gets paragraphs from the sanitizer.
 */
function ProfileText({ html }: { html: string }) {
  if (!stripHtml(html)) return null;

  return <div dangerouslySetInnerHTML={sanitizedHtml(html)} />;
}

function Detail() {
  const { slug, p, d, categoryLabel, related } = Route.useLoaderData();
  const lang = useLang();
  const en = lang === "en";
  const t = (nl: string, e: string) => (en ? e : nl);
  const unit = p.unit === "iu" ? "IU" : "mg";
  const ready = d.waterMl === null;
  const nasal = ready && !d.oral;
  // Optional fields the admin panel adds on top of the original content model.
  const image = "image" in p ? p.image : null;
  const extraBody = "body" in p && p.body ? tr(p.body, lang) : "";

  const toc: [string, string][] = [
    ["highlights", t("Kernpunten", "Quickstart highlights")],
    ["reconstitutie", t("Dosering & reconstitutie", "Dosing & reconstitution")],
    ["protocol", t("Protocoloverzicht", "Protocol overview")],
    ["dosering", t("Doseringsschema", "Dosing protocol")],
    ["bewaren", t("Bewaren", "Storage instructions")],
    ["notities", t("Belangrijke opmerkingen", "Important notes")],
    ["werking", t("Hoe het werkt", "How this works")],
    ["effecten", t("Effecten & bijwerkingen", "Benefits & side effects")],
    ["leefstijl", t("Leefstijlfactoren", "Lifestyle factors")],
    ["techniek", d.oral ? t("Inname", "Intake") : t("Injectietechniek", "Injection technique")],
    ["bron", t("Aanbevolen bron", "Recommended source")],
    ["faq", "FAQ"],
  ];

  const [active, setActive] = useState("highlights");
  useEffect(() => {
    const onScroll = () => {
      let cur = toc[0]?.[0] ?? "highlights";
      const atBottom = window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 4;
      for (const [id] of toc) {
        const el = document.getElementById(id);
        if (el && el.getBoundingClientRect().top <= 140) cur = id;
      }
      setActive(atBottom ? (toc[toc.length - 1]?.[0] ?? cur) : cur);
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [slug, lang]);

  const card = "rounded-xl border border-border bg-card/40 p-5";

  return (
    <>
      <Breadcrumbs items={[{ label: t("Kennisbank", "Knowledge base"), to: "/kennisbank" }, { label: p.name }]} />
      <section className="container pb-8 pt-12">
        <div className="mt-6 grid items-end gap-8 lg:grid-cols-12">
          <div className="lg:col-span-8">
            {image && (
              <img
                src={image.url}
                alt={tr(
                  { nl: image.alt_nl || p.name, en: image.alt_en || image.alt_nl || p.name },
                  lang,
                )}
                width={image.width ?? 1200}
                height={image.height ?? 630}
                loading="eager"
                decoding="async"
                className="mb-6 aspect-video w-full rounded-2xl object-cover"
              />
            )}
            {categoryLabel && (
              <span className="rounded-full bg-primary/10 px-2 py-0.5 font-mono text-[10px] uppercase text-primary">{tr(categoryLabel, lang)}</span>
            )}
            <h1 className="rise mt-4 text-balance text-4xl md:text-6xl font-black tracking-tight">{p.name}</h1>
            <p className="mt-5 max-w-[56ch] text-pretty text-lg text-muted-foreground leading-relaxed">{tr(p.short, lang)}</p>
          </div>
          <div className="lg:col-span-4">
            <div className="rotate-2 rounded-2xl border border-border bg-card/60 p-5 backdrop-blur-md">
              <p className="font-mono text-xs uppercase tracking-widest text-primary">{t("Kerngegevens", "Quick facts")}</p>
              <dl className="mt-3 grid grid-cols-2 gap-y-2 text-sm">
                <dt className="text-foreground/50">Vial</dt><dd className="font-mono">{p.vialMg} {unit}</dd>
                <dt className="text-foreground/50">{t("Concentratie", "Concentration")}</dt><dd className="font-mono">{d.concentration}</dd>
                <dt className="text-foreground/50">{t("Toediening", "Route")}</dt><dd className="font-mono">{tr(d.protocol.route, lang).split(" ")[0]}</dd>
                <dt className="text-foreground/50">{t("Duur", "Duration")}</dt><dd className="font-mono text-xs">{tr(d.protocol.duration, lang)}</dd>
              </dl>
            </div>
          </div>
        </div>
      </section>

      <section className="mx-auto grid max-w-7xl gap-10 px-6 py-8 lg:grid-cols-12">
        <aside className="lg:col-span-3 lg:self-stretch">
          <details className="rounded-xl border border-border bg-card/40 p-4 lg:hidden">
            <summary className="cursor-pointer font-mono text-xs uppercase tracking-widest text-primary">{t("Inhoud", "Contents")}</summary>
            <nav className="mt-3 flex flex-col gap-2 text-sm text-foreground/60">
              {toc.map(([id, label]) => <a key={id} href={`#${id}`} className="inline-flex items-center gap-1.5"><SecIcon id={id} small />{label}</a>)}
            </nav>
          </details>
          <nav className="sticky top-24 hidden max-h-[calc(100vh-7rem)] flex-col overflow-y-auto border-l border-border pr-2 lg:flex">
            <p className="mb-3 pl-4 font-mono text-[10px] uppercase tracking-[0.2em] text-foreground/40">{t("Inhoudsopgave", "Table of contents")}</p>
            {toc.map(([id, label], i) => (
              <a key={id} href={`#${id}`} className={`-ml-px border-l-2 py-1.5 pl-4 text-sm transition ${active === id ? "border-primary text-primary" : "border-transparent text-foreground/50 hover:text-foreground"}`}>
                <span className="mr-2 font-mono text-[10px] text-foreground/30">{String(i + 1).padStart(2, "0")}</span><SecIcon id={id} small />{label}
              </a>
            ))}
          </nav>
        </aside>

        <article className="prose-pa scroll-smooth lg:col-span-9 [&_h2]:scroll-mt-28">
          <h2 id="highlights" className="!mt-0 flex items-center gap-3"><SecIcon id="highlights" />{t("Kernpunten", "Quickstart highlights")}</h2>
          <div className="grid gap-3 sm:grid-cols-2">
            {d.highlights.map((h) => (
              <div key={h.nl} className={`${card} text-sm text-foreground/80`}><span className="mr-2 text-primary">◆</span>{tr(h, lang)}</div>
            ))}
          </div>

          <h2 id="reconstitutie" className="flex items-center gap-3"><SecIcon id="reconstitutie" />{t("Dosering- & reconstitutiegids", "Dosing & reconstitution guide")}</h2>
          {ready ? (
            <p>{t("Dit product wordt kant-en-klaar geleverd; reconstitutie is niet nodig.", "This product is supplied ready to use; no reconstitution is required.")}</p>
          ) : (
            <>
              <h3>{t(`Standaardprotocol (${d.waterMl} mL = ${d.concentration})`, `Standard protocol (${d.waterMl} mL = ${d.concentration})`)}</h3>
              <p>{t(`Een vial van ${p.vialMg} ${unit} opgelost in ${d.waterMl} mL bacteriostatisch water geeft een concentratie van ${d.concentration}.`, `A ${p.vialMg} ${unit} vial dissolved in ${d.waterMl} mL bacteriostatic water gives a concentration of ${d.concentration}.`)}{" "}
                <Link to="/peptide-calculator" className="text-primary hover:underline">{t("Reken je eigen verdunning uit →", "Calculate your own dilution →")}</Link>
              </p>
              <h3>{t("Reconstitutiestappen", "Reconstitution steps")}</h3>
              <ol className="mb-4 list-decimal space-y-1.5 pl-5 text-foreground/70">
                <li>{t("Laat de vial op kamertemperatuur komen en was je handen.", "Let the vial reach room temperature and wash your hands.")}</li>
                <li>{t("Desinfecteer beide rubberen doppen met een alcoholdoekje.", "Disinfect both rubber stoppers with an alcohol swab.")}</li>
                <li>{t(`Trek ${d.waterMl} mL bacteriostatisch water op.`, `Draw up ${d.waterMl} mL of bacteriostatic water.`)}</li>
                <li>{t("Spuit het water langzaam langs de glaswand, niet direct op het poeder.", "Inject the water slowly down the glass wall, not directly onto the powder.")}</li>
                <li>{t("Zwenk zachtjes tot de oplossing helder is — nooit schudden.", "Swirl gently until clear — never shake.")}</li>
                <li>{t("Label de vial met datum en concentratie en bewaar gekoeld.", "Label the vial with date and concentration and refrigerate.")}</li>
              </ol>
              <h3>{t("Benodigdheden", "Supplies needed")}</h3>
              <ul>
                <li>{t(`${p.name} vial (${p.vialMg} ${unit})`, `${p.name} vial (${p.vialMg} ${unit})`)}</li>
                <li>{t("Bacteriostatisch water", "Bacteriostatic water")}</li>
                <li>{t("Mengspuit (1–3 mL) en U-100 insulinespuiten", "Mixing syringe (1–3 mL) and U-100 insulin syringes")}</li>
                <li>{t("Alcoholdoekjes en naaldcontainer", "Alcohol swabs and sharps container")}</li>
              </ul>
            </>
          )}

          <h2 id="protocol" className="flex items-center gap-3"><SecIcon id="protocol" />{t("Protocoloverzicht", "Protocol overview")}</h2>
          <div className="grid gap-3 sm:grid-cols-3">
            {[[t("Duur", "Duration"), d.protocol.duration], [t("Toediening", "Route"), d.protocol.route], [t("Timing", "Timing"), d.protocol.timing]].map(([k, v]) => (
              <div key={k as string} className={card}>
                <p className="font-mono text-[10px] uppercase tracking-widest text-primary">{k as string}</p>
                <p className="mt-1 text-sm text-foreground/80">{tr(v as L10n, lang)}</p>
              </div>
            ))}
          </div>

          <h2 id="dosering" className="flex items-center gap-3"><SecIcon id="dosering" />{t("Doseringsschema in onderzoek", "Dosing protocol in research")}</h2>
          <div className="mb-4 overflow-x-auto rounded-xl border border-border">
            <table className="w-full text-left text-sm">
              <thead className="bg-card/60 font-mono text-[11px] uppercase tracking-wider text-foreground/50">
                <tr><th className="px-4 py-3">{t("Fase", "Phase")}</th><th className="px-4 py-3">{t("Dosis", "Dose")}</th><th className="px-4 py-3">{t("Frequentie", "Frequency")}</th></tr>
              </thead>
              <tbody>
                {d.dosing.map((r) => (
                  <tr key={r.phase.nl} className="border-t border-border">
                    <td className="px-4 py-3 text-foreground/80">{tr(r.phase, lang)}</td>
                    <td className="px-4 py-3 font-mono text-primary">{typeof r.dose === "string" ? r.dose : tr(r.dose, lang)}</td>
                    <td className="px-4 py-3 text-foreground/70">{tr(r.freq, lang)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          <p className="text-xs">{t("Waarden zoals beschreven in literatuur en onderzoeksprotocollen; geen doseringsadvies.", "Values as described in literature and research protocols; not dosing advice.")}</p>

          <h2 id="bewaren" className="flex items-center gap-3"><SecIcon id="bewaren" />{t("Bewaarinstructies", "Storage instructions")}</h2>
          <ul>
            {d.oral ? (
              <li>{t("Droog, koel en donker bewaren in de originele verpakking.", "Store dry, cool and dark in the original packaging.")}</li>
            ) : nasal ? (
              <li>{t("Gekoeld bewaren (2–8 °C), rechtop en uit direct licht.", "Store refrigerated (2–8 °C), upright and out of direct light.")}</li>
            ) : (
              <>
                <li>{t("Gevriesdroogd (poeder): koel, droog en donker; langdurig bij −20 °C.", "Lyophilised (powder): cool, dry and dark; long-term at −20 °C.")}</li>
                <li>{t("Na reconstitutie: koelkast bij 2–8 °C, binnen ~4 weken gebruiken.", "After reconstitution: refrigerator at 2–8 °C, use within ~4 weeks.")}</li>
              </>
            )}
            <li>{t("Vermijd herhaald invriezen en ontdooien.", "Avoid repeated freezing and thawing.")}</li>
          </ul>

          <h2 id="notities" className="flex items-center gap-3"><SecIcon id="notities" />{t("Belangrijke opmerkingen", "Important notes")}</h2>
          <div className="rounded-xl border border-primary/30 bg-primary/5 p-5 [&_ul]:mb-0"><List items={d.notes} lang={lang} /></div>

          <h2 id="werking" className="flex items-center gap-3"><SecIcon id="werking" />{t("Hoe het werkt", "How this works")}</h2>
          <ProfileText html={tr(p.intro, lang)} />
          <ProfileText html={tr(p.mechanism, lang)} />
          <ProfileText html={tr(p.research, lang)} />
          {extraBody !== "" && (
            <div className="not-prose my-6 space-y-4" dangerouslySetInnerHTML={sanitizedHtml(extraBody)} />
          )}

          <h2 id="effecten" className="flex items-center gap-3"><SecIcon id="effecten" />{t("Mogelijke effecten & bijwerkingen", "Potential benefits & side effects")}</h2>
          <h3>{t("Beschreven effecten in onderzoek", "Effects described in research")}</h3>
          <List items={d.benefits} lang={lang} />
          <h3>{t("Veelgemelde bijwerkingen", "Common side effects")}</h3>
          <List items={d.sideEffects} lang={lang} />
          <ProfileText html={tr(p.sideEffects, lang)} />
          <h3>{t("Contra-indicaties", "Contraindications")}</h3>
          <List items={d.contraindications} lang={lang} />

          <h2 id="leefstijl" className="flex items-center gap-3"><SecIcon id="leefstijl" />{t("Leefstijlfactoren", "Lifestyle factors")}</h2>
          <List items={d.lifestyle} lang={lang} />

          <h2 id="techniek" className="flex items-center gap-3"><SecIcon id="techniek" />{d.oral ? t("Inname", "Intake") : t("Injectietechniek", "Injection technique")}</h2>
          {d.oral ? (
            <ul>
              <li>{t("Neem de tablet met water in, op een vast tijdstip per dag.", "Take the tablet with water at the same time each day.")}</li>
              <li>{t("Inname voor het slapen wordt vaak beschreven om lethargie overdag te beperken.", "Bedtime intake is often described to limit daytime lethargy.")}</li>
            </ul>
          ) : nasal ? (
            <ul>
              <li>{t("Snuit eerst je neus en houd het hoofd licht voorover.", "Blow your nose first and tilt your head slightly forward.")}</li>
              <li>{t("Spray in één neusgat terwijl je het andere dichtdrukt; adem rustig in.", "Spray into one nostril while closing the other; inhale gently.")}</li>
              <li>{t("Wissel van neusgat bij elke toediening.", "Alternate nostrils each time.")}</li>
            </ul>
          ) : (
            <ul>
              <li>{t("Kies een plek met onderhuids vet: buik (5 cm naast de navel), dij of achterkant bovenarm.", "Choose a site with subcutaneous fat: abdomen (5 cm from the navel), thigh or back of upper arm.")}</li>
              <li>{t("Desinfecteer, knijp een huidplooi en prik onder een hoek van 45–90°.", "Disinfect, pinch a skin fold and insert at a 45–90° angle.")}</li>
              <li>{t("Spuit langzaam in, wacht 5 seconden en trek de naald terug.", "Inject slowly, wait 5 seconds and withdraw.")}</li>
              <li>{t("Roteer injectieplaatsen en gebruik elke naald één keer.", "Rotate sites and use each needle once.")}</li>
            </ul>
          )}

          <h2 id="bron" className="flex items-center gap-3"><SecIcon id="bron" />{t("Aanbevolen bron", "Recommended source")}</h2>
          <p>{t(
            "Kwaliteit verschilt sterk per leverancier. Let op een onafhankelijk HPLC/MS-labrapport per batch, zuiverheid ≥ 98% en duidelijke opslag- en verzendcondities.",
            "Quality varies widely between suppliers. Look for an independent HPLC/MS lab report per batch, purity ≥ 98% and clear storage and shipping conditions.",
          )}</p>
          <p>
            {t(`Wij gebruiken als referentie de ${p.name} van `, `As a reference we use the ${p.name} from `)}
            <ShopLink product={p.shopSlug} source="peptide-source" className="text-primary underline-offset-4 hover:underline">PeptideWinkel</ShopLink>
            {t(", dat per batch labrapporten publiceert.", ", which publishes lab reports per batch.")}
          </p>

          <div className="not-prose my-10"><ProductAssistant context={p.name} /></div>
          <h2 id="faq" className="flex items-center gap-3"><SecIcon id="faq" />{t("Veelgestelde vragen", "Frequently asked questions")}</h2>
          {p.faq.map((f) => (
            <div key={f.q.nl}>
              <h3>{tr(f.q, lang)}</h3>
              <p>{tr(f.a, lang)}</p>
            </div>
          ))}
          <div className="mt-10 rounded-xl border border-border bg-card/40 p-5 text-xs leading-relaxed text-foreground/50">{tr(ui.disclaimer, lang)}</div>
        </article>
      </section>

      {related.length > 0 && (
        <section className="container pb-20 pt-6">
          <SectionLabel>{t("Gerelateerd", "Related")}</SectionLabel>
          <div className="mt-6 grid gap-5 sm:grid-cols-2 lg:grid-cols-4">
            {related.map((r, i) => <PeptideCard key={r.slug} p={r} index={i} />)}
          </div>
        </section>
      )}
    </>
  );
}

const SEC_ICONS: Record<string, LucideIcon> = {
  highlights: Zap, reconstitutie: FlaskConical, protocol: ClipboardList, dosering: Syringe,
  bewaren: Snowflake, notities: AlertCircle, werking: Lightbulb, effecten: Scale,
  leefstijl: Dumbbell, techniek: Pipette, bron: Link2, faq: HelpCircle,
};

function SecIcon({ id, small }: { id: string; small?: boolean }) {
  const Icon = SEC_ICONS[id];
  if (!Icon) return null;
  return small
    ? <Icon className="mr-2 inline h-3.5 w-3.5 shrink-0 text-primary" aria-hidden />
    : <Icon className="h-6 w-6 shrink-0 text-primary" aria-hidden />;
}
