'use client';

/**
 * Homepage Quiz Section ("What should you wear?")
 * File: src/components/home/QuizSection.tsx
 *
 * - Section visibility / title / subtitle / extra text: Editor Settings -> Homepage -> Quiz Section (homepage.quiz)
 * - Questions, rules, tags: Next.js Editor -> Quiz Editor (GET /wp-json/nextjs-editor/v1/quiz)
 * - Scoring: src/lib/quiz-engine.ts
 */
import React, { useEffect, useMemo, useRef, useState } from 'react';
import Link from 'next/link';
import { Product } from '@/types/woocommerce';
import { siteConfig } from '@/config/site';
import { useCart } from '@/context/CartContext';
import { useSize } from '@/context/SizeContext';
import { pushToDataLayer } from '@/lib/tracking';
import { QuizSectionSettings, ProductHoverTagsSettings } from '@/lib/settings';
import ProductCard from '@/components/product/ProductCard';
import {
  QuizAnswer,
  QuizData,
  QuizProduct,
  buildQuizProducts,
  optionToAnswer,
  scoreQuiz,
} from '@/lib/quiz-engine';

interface QuizSectionProps {
  title: string;
  settings?: QuizSectionSettings;
  data: QuizData | null;
  allProducts: Product[];
  hoverTags?: ProductHoverTagsSettings;
}

const money = (n: number) => `${siteConfig.currency.symbol}${Math.round(n || 0).toLocaleString()}`;

export default function QuizSection({ title, settings, data, allProducts, hoverTags }: QuizSectionProps) {
  const { quickAdd } = useCart();
  const { selectedSize } = useSize();
  const cfg = data?.config;
  const questions = cfg?.questions || [];
  const total = questions.length;

  // step: -1 intro | 0..total-1 question | total computing | total+1 result
  const [step, setStep] = useState(-1);
  const [answers, setAnswers] = useState<QuizAnswer[]>([]);
  const [picked, setPicked] = useState<number | null>(null);
  const [added, setAdded] = useState(false);
  const boxRef = useRef<HTMLDivElement>(null);

  const products = useMemo(
    () => (data ? buildQuizProducts(data.catalog, allProducts) : []),
    [data, allProducts]
  );

  const result = useMemo(
    () => (cfg && step === total + 1 ? scoreQuiz(products, cfg, answers, selectedSize) : null),
    [cfg, step, total, products, answers, selectedSize]
  );

  // "Checking the shelf…" for ~1s, then show the result
  useEffect(() => {
    if (step !== total || total === 0) return;
    const t = setTimeout(() => setStep(total + 1), 1000);
    return () => clearTimeout(t);
  }, [step, total]);

  // Track completion once per result
  useEffect(() => {
    if (!result) return;
    const top = result.ranked[0];
    pushToDataLayer({
      event: 'quiz_complete',
      quiz_answers: answers.map((a) => a.label).join(' | '),
      quiz_result_id: top ? top.p.id : null,
      quiz_result_name: top ? top.p.name : null,
      quiz_over_budget: result.overBudget,
    });
  }, [result, answers]);

  if (!cfg || total === 0) return null;

  const scrollIntoBox = () => {
    if (boxRef.current && typeof window !== 'undefined') {
      const top = boxRef.current.getBoundingClientRect().top + window.scrollY - 140;
      if (Math.abs(window.scrollY - top) > 200) window.scrollTo({ top, behavior: 'smooth' });
    }
  };

  const start = () => {
    setAnswers([]);
    setAdded(false);
    setStep(0);
    pushToDataLayer({ event: 'quiz_start' });
    scrollIntoBox();
  };

  const choose = (oi: number) => {
    if (picked !== null || step < 0 || step >= total) return;
    setPicked(oi);
    const q = questions[step];
    const ans = optionToAnswer(q, q.options[oi]);
    setTimeout(() => {
      setAnswers((prev) => {
        const next = prev.slice(0, step);
        next[step] = ans;
        return next;
      });
      setPicked(null);
      setStep((s) => s + 1);
    }, 190);
  };

  const back = () => {
    setStep((s) => Math.max(-1, s - 1));
  };

  const reset = () => {
    setAnswers([]);
    setAdded(false);
    setStep(-1);
  };

  const dots = (filledUpTo: number) => (
    <span className="rmq-dots" aria-hidden="true">
      {questions.map((_, i) => (
        <i key={i} className={i <= filledUpTo ? 'on' : ''} />
      ))}
    </span>
  );

  /* ---------- intro images: option images first, then product images ---------- */
  const introImages = (() => {
    const imgs: string[] = [];
    questions.forEach((q) => q.options.forEach((o) => o.image && imgs.push(o.image)));
    products.forEach((p) => p.image && imgs.push(p.image));
    return Array.from(new Set(imgs)).slice(0, 3);
  })();

  let body: React.ReactNode = null;

  if (step === -1) {
    body = (
      <div className="rmq-intro rmq-step">
        <div>
          <span className="rmq-score">🎯 Takes about 20 seconds</span>
          <h3>{cfg.intro_heading}</h3>
          {cfg.intro_text && (
            <p>
              {cfg.intro_text}
            </p>
          )}
          <div className="rmq-badges">
            <span>{total} questions</span>
            <span>No sign-up</span>
            <span>Real stock only</span>
          </div>
          <div className="rmq-nav">
            <button type="button" className="btn btn-pri" onClick={start}>
              {cfg.start_label}
            </button>
          </div>
        </div>
        {introImages.length > 0 && (
          <div className="rmq-stack" aria-hidden="true">
            {introImages.map((src) => (
              // eslint-disable-next-line @next/next/no-img-element
              <img key={src} src={src} alt="" loading="lazy" />
            ))}
          </div>
        )}
      </div>
    );
  } else if (step < total) {
    const q = questions[step];
    const hasPics = q.options.some((o) => !!o.image);
    body = (
      <>
        <div className="rmq-top">
          <b>
            Question {step + 1} of {total}
          </b>
          <span className="rmq-prog">
            <i style={{ width: `${(step / total) * 100}%` }} />
          </span>
          {dots(step)}
        </div>
        <div className="rmq-body rmq-step" key={q.id}>
          <h3>{q.title}</h3>
          {q.subtitle && <p>{q.subtitle}</p>}
          <div className={`rmq-opts${hasPics ? ' has-pics' : ''}`}>
            {q.options.map((o, oi) => (
              <button
                type="button"
                key={o.id || oi}
                className={`rmq-opt${o.image ? ' pic' : ''}${picked === oi ? ' sel' : ''}`}
                onClick={() => choose(oi)}
              >
                {o.image && (
                  // eslint-disable-next-line @next/next/no-img-element
                  <img
                    src={o.image}
                    alt=""
                    loading="lazy"
                    onError={(e) => {
                      e.currentTarget.src = '/images/placeholder.png';
                    }}
                  />
                )}
                <span>
                  <b>{o.label}</b>
                  {o.desc && <small>{o.desc}</small>}
                </span>
              </button>
            ))}
          </div>
          <div className="rmq-nav">
            <button type="button" className="rmq-lnk" onClick={back}>
              {step ? 'Back' : 'Cancel'}
            </button>
            <button type="button" className="rmq-lnk" style={{ marginLeft: 'auto' }} onClick={reset}>
              Start over
            </button>
          </div>
        </div>
      </>
    );
  } else if (step === total) {
    body = (
      <>
        <div className="rmq-top">
          <b>Matching</b>
          <span className="rmq-prog">
            <i style={{ width: '100%' }} />
          </span>
          {dots(total)}
        </div>
        <div className="rmq-load">
          <div className="rmq-spin" />
          <b>{cfg.computing_text}</b>
          <p>
            Matching your {total} answers against {products.length} products in stock.
          </p>
        </div>
      </>
    );
  } else if (result) {
    const fallbackProduct: QuizProduct | null =
      products[0] ||
      (allProducts[0]
        ? {
            id: Number(allProducts[0].id),
            slug: allProducts[0].slug,
            name: allProducts[0].name,
            price: Number(allProducts[0].price) || 0,
            regular: Number(allProducts[0].regularPrice) || Number(allProducts[0].price) || 0,
            image: allProducts[0].image || '/images/hero1.webp',
            cats: allProducts[0].categories || ['sneakers'],
            sizes: allProducts[0].availableSizes || ['40', '41', '42', '43', '44'],
            stock: 'in' as const,
            sales: 15,
            tags: ['clean', 'versatile', 'campus'],
            product: allProducts[0],
          }
        : null);

    const rankedList =
      result.ranked.length > 0
        ? result.ranked
        : fallbackProduct
        ? [
            {
              p: fallbackProduct,
              score: 10,
              axes: 1,
              pct: 85,
              why: ['Closest alternative', 'Popular in store'],
            },
          ]
        : [];

    if (rankedList.length === 0) {
      body = (
        <div className="rmq-body rmq-step">
          <h3>{cfg.empty_title}</h3>
          <p>{cfg.empty_text}</p>
          <div className="rmq-nav">
            <Link className="btn btn-pri" href={cfg.empty_btn_link || '/contact'}>
              {cfg.empty_btn_label}
            </Link>
            <button type="button" className="rmq-lnk" style={{ marginLeft: 'auto' }} onClick={reset}>
              Try again
            </button>
          </div>
        </div>
      );
    } else {
      const top = rankedList[0];
      const p = top.p;
      const disc = p.regular > p.price ? Math.round(((p.regular - p.price) / p.regular) * 100) : 0;
      const rest =
        result.ranked.length > 1
          ? result.ranked.slice(1, 1 + (cfg.result_count || 0)).map((x) => x.p.product)
          : products.slice(1, 1 + (cfg.result_count || 0)).map((x) => x.product);

      body = (
        <>
          <div className="rmq-top">
            <b>{cfg.result_heading}</b>
            <span className="rmq-prog">
              <i style={{ width: '100%' }} />
            </span>
            {dots(total)}
          </div>
          <div className="rmq-body">
            {result.overBudget && (
              <p className="rmq-note">Nothing fits that budget right now — this is the closest pair just above it.</p>
            )}
            <div className="rmq-res">
              <Link className="rmq-pic" href={`/product/${p.slug}`}>
                {/* eslint-disable-next-line @next/next/no-img-element */}
                <img
                  src={p.image}
                  alt={p.name}
                  onError={(e) => {
                    e.currentTarget.src = '/images/placeholder.png';
                  }}
                />
              </Link>
              <div>
                {(cfg.show_match_percent || selectedSize) && (
                  <span className="rmq-score">
                    ✓ {cfg.show_match_percent ? `${top.pct}% match` : 'Your pick'}
                    {selectedSize ? ` · size ${selectedSize} ready` : ''}
                  </span>
                )}
                <h3>{p.name}</h3>
                <p className="rmq-price">
                  <b>{money(p.price)}</b>
                  {disc > 0 && <del>{money(p.regular)}</del>}
                  {disc > 0 && <i>{disc}% off</i>}
                </p>
                <div className="rmq-why">
                  {answers.map((a, i) => (
                    <span key={i}>{a.label}</span>
                  ))}
                </div>
                <div className="rmq-nav" style={{ flexWrap: 'wrap' }}>
                  <Link className="btn btn-pri" href={`/product/${p.slug}`}>
                    See this product
                  </Link>
                  <button
                    type="button"
                    className="btn btn-ghost"
                    onClick={() => {
                      quickAdd(p.product, false, selectedSize);
                      setAdded(true);
                    }}
                  >
                    {added ? 'Added ✓' : 'Add to cart'}
                  </button>
                  <button type="button" className="rmq-lnk" style={{ marginLeft: 'auto' }} onClick={reset}>
                    Play again
                  </button>
                </div>
              </div>
            </div>
          </div>
          {rest.length > 0 && (
            <div className="rmq-more">
              <div className="rmq-more-header">
                <h4>{cfg.runners_heading}</h4>
                <span className="rmq-swipe-hint">Swipe →</span>
              </div>
              <div className="rmq-more-grid">
                {rest.map((rp, i) => (
                  <ProductCard key={rp.id} product={rp} index={i} hideBadge hoverTags={hoverTags} />
                ))}
              </div>
            </div>
          )}
        </>
      );
    }
  }

  return (
    <section className="sec wrap" id="quiz" aria-label="প্রোডাক্ট ফাইন্ডার কুইজ">
      <div className="quiz" id="quizbox" ref={boxRef}>
        {body}
      </div>
    </section>
  );
}