import { createFileRoute, Link } from "@tanstack/react-router";
import Breadcrumbs from "@/components/Breadcrumbs";
import { useMemo, useRef, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { ChevronRight, X, Calculator, BookOpen, Loader2, ShoppingCart } from "lucide-react";
import { Sheet, SheetContent, SheetTitle, SheetDescription } from "@/components/ui/sheet";
import { SectionLabel } from "@/components/kennisbank/SectionLabel";
import { ShopLink } from "@/components/kennisbank/ShopLink";
import { categories } from "@/content/kennisbank/peptides";
import { pageHead, tr, useLang } from "@/lib/kennisbank-i18n";
import { headLang } from "@/lib/i18n";
import { questions as builtInQuestions, recommend, type Answers } from "@/lib/peptidewijzer";
import { getPeptidewijzerConfig, logQuizEvent } from "@/lib/peptidewijzer.functions";
import { matchMappedProducts, selectProducts, type QuizAnswers } from "@/lib/peptidewijzer-mapping";
import type { PwQuizQuestion, QuizEvent } from "@/lib/pw-config.types";
import { wc } from "@/lib/woocommerce";
import { useGqlCart } from "@/hooks/useGqlCart";
import { useCartDrawerStore } from "@/stores/cartDrawerStore";
import { toast } from "sonner";

export const Route = createFileRoute("/peptidewijzer")({
  head: (ctx) => {
    const lang = headLang(ctx);
    return lang === "en"
      ? pageHead(
          "/peptidewijzer",
          "Peptide Finder — which peptide fits your research? | Peptidewinkel",
          "Pick your research goal, answer a few short questions and get a personal overview of the peptides that fit best.",
          lang,
        )
      : pageHead(
          "/peptidewijzer",
          "Peptidewijzer — welke peptide past bij jouw onderzoek? | Peptidewinkel",
          "Kies je onderzoeksdoel, beantwoord een paar korte vragen en ontvang een persoonlijk overzicht van de peptiden die het best passen.",
          lang,
        );
  },
  component: Wizard,
});

/**
 * The questionnaire, its translations and the mapping to WooCommerce products are
 * managed in WP-admin (Peptidewinkel Companion). The built-in questionnaire below
 * is the fallback for when WordPress does not answer, so this page never breaks.
 */
const builtIn = builtInQuestions as unknown as PwQuizQuestion[];

function newSessionId(): string {
  try {
    return crypto.randomUUID();
  } catch {
    return `s${Date.now().toString(36)}`;
  }
}

function Wizard() {
  const lang = useLang();
  const en = lang === "en";
  const t = (nl: string, e: string) => (en ? e : nl);
  const { addItem } = useGqlCart();
  const openCart = useCartDrawerStore((s) => s.open);
  const sessionId = useRef<string>(newSessionId());

  const [open, setOpen] = useState(false);
  const [step, setStep] = useState(0);
  const [answers, setAnswers] = useState<QuizAnswers>({});

  const { data: remoteConfig } = useQuery({
    queryKey: ["pw-quiz-config"],
    queryFn: async () => await getPeptidewijzerConfig(),
    staleTime: 5 * 60 * 1000,
  });

  const quizQuestions = remoteConfig?.questions?.length ? remoteConfig.questions : builtIn;
  const firstQuestion = quizQuestions[0]!;
  const total = quizQuestions.length;
  const done = step >= total;
  const current = !done && step > 0 ? quizQuestions[step] : null;

  const log = (event: Omit<QuizEvent, "session_id">) => {
    void logQuizEvent({ data: { ...event, session_id: sessionId.current } }).catch(() => {
      /* logging must never block the visitor */
    });
  };

  // Products from the WP-admin mapping (live price + stock from WooCommerce).
  const mapped = useMemo(() => {
    if (!done || !remoteConfig) return null;

    const result = matchMappedProducts(
      remoteConfig,
      quizQuestions.map((question) => question.key),
      answers,
    );

    if (result.products.length === 0) return null;

    return {
      ids: result.products.slice(0, 8),
      notes: result.notes,
      maxResults: remoteConfig.settings.maxResults,
      hideOutOfStock: remoteConfig.settings.hideOutOfStock,
    };
  }, [done, remoteConfig, quizQuestions, answers]);

  const { data: mappedProducts, isFetching: mappedLoading } = useQuery({
    queryKey: ["pw-quiz-products", mapped?.ids.join(",") ?? ""],
    enabled: !!mapped,
    staleTime: 2 * 60 * 1000,
    queryFn: async () => {
      const ids = mapped?.ids ?? [];
      const fetched = await Promise.allSettled(ids.map((id) => wc.getProduct(id)));
      const byId = new Map(
        fetched.flatMap((result) =>
          result.status === "fulfilled" ? [[result.value.data.id, result.value.data] as const] : [],
        ),
      );
      const ordered = ids.flatMap((id) => {
        const product = byId.get(id);

        return product ? [product] : [];
      });

      return selectProducts(ordered, mapped?.maxResults ?? 3, mapped?.hideOutOfStock ?? true);
    },
  });

  const builtInResults = done && !mapped ? recommend(answers as unknown as Answers) : [];

  const reset = () => {
    setAnswers({});
    setStep(0);
  };

  const start = (goal?: string) => {
    reset();
    if (goal) {
      setAnswers({ [firstQuestion.key]: goal });
      setStep(1);
    }
    setOpen(true);
  };

  const choose = (key: string, value: string) => {
    setAnswers((previous) => ({ ...previous, [key]: value }));
    log({ event_type: "answer", question_key: key, answer_value: value, step });
    setStep((currentStep) => currentStep + 1);
  };

  const goalLabel = firstQuestion.options.find(
    (option) => option.value === answers[firstQuestion.key],
  );

  const addMappedToCart = async (productId: number) => {
    log({ event_type: "product_click", product_id: productId, step: total });

    try {
      await addItem({ productId, quantity: 1 });
      openCart();
    } catch {
      toast.error(t("Toevoegen mislukt.", "Could not add to cart."));
    }
  };

  return (
    <>
      <Breadcrumbs items={[{ label: t('Peptidewijzer', 'Peptide Finder') }]} />
    <section className="container max-w-5xl pb-24 pt-16">
      <div className="rounded-3xl border border-border bg-card/60 p-8 md:p-12">
        <SectionLabel>{t("Peptidewijzer", "Peptide Finder")}</SectionLabel>
        <h1 className="mt-3 text-balance text-4xl md:text-6xl font-black tracking-tight">
          {t(
            "Vind snel de peptide die bij jouw onderzoek past",
            "Quickly find the peptide that fits your research",
          )}
        </h1>
        <p className="mt-5 max-w-[60ch] text-pretty text-lg text-muted-foreground leading-relaxed">
          {t(
            "Kies je onderzoeksdoel en beantwoord een paar korte vragen. Je ziet direct welke peptiden het best aansluiten — gebaseerd op onderzoeksdata, niet op marketing.",
            "Pick your research goal and answer a few short questions. You will instantly see which peptides fit best — based on research data, not marketing.",
          )}
        </p>
        <div className="mt-8 flex flex-wrap gap-3">
          <button
            onClick={() => start()}
            className="rounded-full bg-primary px-6 py-3 text-sm font-semibold text-primary-foreground transition hover:brightness-110"
          >
            {t("Start wijzer", "Start finder")}
          </button>
          <Link
            to="/shop"
            className="rounded-full border border-border px-6 py-3 text-sm font-semibold transition hover:border-primary/50 hover:text-primary"
          >
            {t("Bekijk webshop", "View shop")}
          </Link>
          <Link
            to="/kennisbank"
            className="rounded-full border border-border px-6 py-3 text-sm font-semibold transition hover:border-primary/50 hover:text-primary"
          >
            {t("Naar de kennisbank", "Go to knowledge base")}
          </Link>
        </div>
      </div>

      <h2 className="mt-14 text-2xl md:text-3xl font-black">
        {t("Kies direct je onderwerp", "Pick your topic directly")}
      </h2>
      <div className="mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
        {firstQuestion.options.map((option) => (
          <button
            key={option.value}
            onClick={() => start(option.value)}
            className="group rounded-2xl border border-border bg-card/60 p-6 text-left transition hover:border-primary/50"
          >
            <span className="inline-block rounded-full bg-primary/10 px-2.5 py-0.5 text-xs font-medium text-primary">
              {t("1 minuut", "1 minute")}
            </span>
            <h3 className="mt-3 text-lg font-bold">{tr(option.label, lang)}</h3>
            <p className="mt-1 text-sm text-muted-foreground">
              {total - 1} {t("vragen", "questions")}
            </p>
            <span className="mt-4 inline-flex items-center gap-1 text-sm font-semibold text-primary">
              {t("Start", "Start")}{" "}
              <ChevronRight className="h-4 w-4 transition group-hover:translate-x-0.5" />
            </span>
          </button>
        ))}
        <Link
          to="/peptide-calculator"
          className="group rounded-2xl border border-border bg-card/60 p-6 transition hover:border-primary/50"
        >
          <Calculator className="h-5 w-5 text-primary" />
          <h3 className="mt-3 text-lg font-bold">
            {t("Peptide calculator", "Peptide calculator")}
          </h3>
          <p className="mt-1 text-sm text-muted-foreground">
            {t(
              "Bereken de reconstitutie van je vial.",
              "Calculate the reconstitution of your vial.",
            )}
          </p>
          <span className="mt-4 inline-flex items-center gap-1 text-sm font-semibold text-primary">
            {t("Open calculator", "Open calculator")} <ChevronRight className="h-4 w-4" />
          </span>
        </Link>
      </div>

      <Sheet open={open} onOpenChange={setOpen}>
        <SheetContent side="right" className="w-full sm:max-w-xl overflow-y-auto">
          <div className="mx-auto w-full max-w-lg pb-10 pt-2">
            <div className="mb-6 flex items-center justify-between">
              <div className="h-1.5 flex-1 overflow-hidden rounded-full bg-border">
                <div
                  className="h-full rounded-full bg-primary transition-all"
                  style={{ width: `${Math.min(100, (step / (total + 1)) * 100)}%` }}
                />
              </div>
              <button
                onClick={() => setOpen(false)}
                className="ml-4 rounded-full p-2 text-muted-foreground transition hover:bg-muted"
                aria-label={t("Sluiten", "Close")}
              >
                <X className="h-4 w-4" />
              </button>
            </div>

            {step === 0 && !done && (
              <div className="rise">
                <SheetTitle className="text-2xl md:text-3xl font-black">
                  {tr(firstQuestion.title, lang)}
                </SheetTitle>
                <SheetDescription className="sr-only">
                  {t("Kies een antwoord", "Choose an answer")}
                </SheetDescription>
                <div className="mt-6 grid gap-3">
                  {firstQuestion.options.map((option) => (
                    <button
                      key={option.value}
                      onClick={() => choose(firstQuestion.key, option.value)}
                      className="flex items-center justify-between rounded-xl border border-border px-5 py-4 text-left transition hover:border-primary/50"
                    >
                      <span>
                        <span className="block font-semibold">{tr(option.label, lang)}</span>
                        <span className="text-sm text-muted-foreground">
                          {total - 1} {t("vragen", "questions")}
                        </span>
                      </span>
                      <ChevronRight className="h-4 w-4 text-muted-foreground" />
                    </button>
                  ))}
                </div>
              </div>
            )}

            {current && (
              <div key={step} className="rise">
                {goalLabel && (
                  <p className="text-xs font-semibold uppercase tracking-widest text-primary">
                    {tr(goalLabel.label, lang)}
                  </p>
                )}
                <p className="mt-1 text-sm text-muted-foreground">
                  {t(`Vraag ${step} van ${total - 1}`, `Question ${step} of ${total - 1}`)}
                </p>
                <SheetTitle className="mt-2 text-2xl md:text-3xl font-black">
                  {tr(current.title, lang)}
                </SheetTitle>
                <SheetDescription className="sr-only">
                  {t("Kies een antwoord", "Choose an answer")}
                </SheetDescription>
                <div className="mt-6 grid gap-3">
                  {current.options.map((option) => (
                    <button
                      key={option.value}
                      onClick={() => choose(current.key, option.value)}
                      className={`flex items-center justify-between rounded-xl border px-5 py-4 text-left font-medium transition hover:border-primary/50 ${answers[current.key] === option.value ? "border-primary/50 bg-primary/10 text-primary" : "border-border"}`}
                    >
                      {tr(option.label, lang)}
                      <ChevronRight className="h-4 w-4 text-muted-foreground" />
                    </button>
                  ))}
                </div>
                {step > 1 && (
                  <button
                    onClick={() => setStep((currentStep) => currentStep - 1)}
                    className="mt-5 text-sm font-semibold text-muted-foreground hover:text-primary"
                  >
                    ← {t("Vorige vraag", "Previous question")}
                  </button>
                )}
              </div>
            )}

            {done && (
              <div className="rise">
                <SheetTitle className="text-3xl font-black">
                  {t("Jouw advies", "Your recommendation")}
                </SheetTitle>
                <SheetDescription className="mt-2">
                  {t(
                    "Op basis van je antwoorden passen deze producten het best.",
                    "Based on your answers, these products fit best.",
                  )}
                </SheetDescription>

                {mapped && mapped.notes.length > 0 && (
                  <p className="mt-4 text-sm text-muted-foreground">
                    {mapped.notes.map((note) => tr(note, lang)).join(" · ")}
                  </p>
                )}

                {mappedLoading && (
                  <p className="mt-6 inline-flex items-center gap-2 text-sm text-muted-foreground">
                    <Loader2 className="h-4 w-4 animate-spin" />{" "}
                    {t("Producten laden…", "Loading products…")}
                  </p>
                )}

                {!mappedLoading && mappedProducts && mappedProducts.length > 0 && (
                  <div className="mt-6 grid gap-4">
                    {mappedProducts.map((product, index) => (
                      <div
                        key={product.id}
                        className={`rounded-2xl border p-4 ${index === 0 ? "border-primary/50 bg-primary/5" : "border-border"}`}
                      >
                        <div className="flex gap-4">
                          {product.images?.[0]?.src && (
                            <img
                              src={product.images[0].src}
                              alt={product.name}
                              className="h-20 w-20 shrink-0 rounded-xl object-cover"
                              loading="lazy"
                            />
                          )}
                          <div className="min-w-0 flex-1">
                            <div className="flex flex-wrap items-center gap-2">
                              {index === 0 && (
                                <span className="rounded-full bg-primary px-2 py-0.5 text-[10px] font-semibold uppercase text-primary-foreground">
                                  {t("Beste match", "Best match")}
                                </span>
                              )}
                              {product.stock_status === "outofstock" && (
                                <span className="rounded-full bg-destructive/10 px-2 py-0.5 text-[10px] font-semibold uppercase text-destructive">
                                  {t("Uitverkocht", "Sold out")}
                                </span>
                              )}
                            </div>
                            <h3 className="mt-1.5 text-lg font-black">{product.name}</h3>
                            <p className="text-sm font-semibold text-primary">
                              €
                              {Number.parseFloat(
                                product.price || product.regular_price || "0",
                              ).toFixed(2)}
                            </p>
                            <div className="mt-3 flex flex-wrap gap-2">
                              <button
                                onClick={() => addMappedToCart(product.id)}
                                disabled={product.stock_status === "outofstock"}
                                className="inline-flex items-center gap-2 rounded-full bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground transition hover:brightness-110 disabled:opacity-50"
                              >
                                <ShoppingCart className="h-4 w-4" />{" "}
                                {t("In winkelmand", "Add to cart")}
                              </button>
                              <Link
                                to="/product/$slug"
                                params={{ slug: product.slug }}
                                className="inline-flex items-center gap-1 rounded-full border border-border px-4 py-2 text-sm font-medium transition hover:border-primary/50 hover:text-primary"
                              >
                                {t("Bekijk product", "View product")}
                              </Link>
                            </div>
                          </div>
                        </div>
                      </div>
                    ))}
                  </div>
                )}

                {!mappedLoading && mapped && (!mappedProducts || mappedProducts.length === 0) && (
                  <p className="mt-6 text-muted-foreground">
                    {t(
                      "De aanbevolen producten zijn momenteel niet op voorraad. Probeer een andere combinatie of bekijk de webshop.",
                      "The recommended products are currently out of stock. Try another combination or browse the shop.",
                    )}
                  </p>
                )}

                {builtInResults.length === 0 && !mapped && (
                  <p className="mt-6 text-muted-foreground">
                    {t(
                      "Geen sterke match met deze voorkeuren. Probeer een minder strikte voorkeur voor toediening.",
                      "No strong match with these preferences. Try a less strict administration preference.",
                    )}
                  </p>
                )}

                {builtInResults.length > 0 && (
                  <div className="mt-6 grid gap-4">
                    {builtInResults.map(({ peptide: p }, i) => (
                      <div
                        key={p.slug}
                        className={`rounded-2xl border p-5 ${i === 0 ? "border-primary/50 bg-primary/5" : "border-border"}`}
                      >
                        <div className="flex flex-wrap items-center gap-2">
                          {i === 0 && (
                            <span className="rounded-full bg-primary px-2 py-0.5 text-[10px] font-semibold uppercase text-primary-foreground">
                              {t("Beste match", "Best match")}
                            </span>
                          )}
                          <span className="rounded-full bg-primary/10 px-2 py-0.5 text-[10px] font-semibold uppercase text-primary">
                            {tr(categories[p.category], lang)}
                          </span>
                        </div>
                        <h3 className="mt-2 text-xl font-black">{p.name}</h3>
                        <p className="mt-1 text-sm text-muted-foreground leading-relaxed">
                          {tr(p.short, lang)}
                        </p>
                        <div className="mt-4 flex flex-wrap gap-2">
                          <ShopLink
                            product={p.shopSlug}
                            source={`wizard-${i + 1}`}
                            className="rounded-full bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground transition hover:brightness-110"
                          >
                            {t(`Bestel ${p.name} →`, `Order ${p.name} →`)}
                          </ShopLink>
                          <Link
                            to="/kennisbank/$slug"
                            params={{ slug: p.slug }}
                            className="inline-flex items-center gap-1 rounded-full border border-border px-4 py-2 text-sm font-medium transition hover:border-primary/50 hover:text-primary"
                          >
                            <BookOpen className="h-4 w-4" /> {t("Profiel", "Profile")}
                          </Link>
                        </div>
                      </div>
                    ))}
                  </div>
                )}

                <button
                  onClick={() => {
                    reset();
                    log({ event_type: "restart" });
                  }}
                  className="mt-8 text-sm font-semibold text-primary hover:underline"
                >
                  {t("Opnieuw beginnen", "Start again")}
                </button>
                <p className="mt-6 text-xs text-muted-foreground">
                  {t(
                    "Dit overzicht is educatief en geen medisch advies. Uitsluitend voor onderzoek.",
                    "This overview is educational, not medical advice. For research purposes only.",
                  )}
                </p>
              </div>
            )}
          </div>
        </SheetContent>
      </Sheet>
    </section>
    </>
  );
}
