'use client';

import { useEffect, useMemo, useRef, useState, useTransition } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { ArrowLeft, Camera, Plus, Printer, RefreshCw, Sparkles } from 'lucide-react';
import { numerologyTitle } from '@/lib/numerology/pythagorean';
import { chakraMeta } from '@/lib/aura/chakraMeta';
import { ELEMENT_INFO } from '@/lib/bazi/guide';
import { INTL_LOCALE } from '@/i18n/config';
import { useLocale, useMessages } from '@/i18n/client';
import { synthesizePersonalBlueprint } from '@/lib/blueprint/synthesizer';
import { getSamples } from '@/lib/reports/samples';
import type { ReportData } from '@/lib/reports/types';
import { claimReport, saveReportBazi, saveReportNumerology } from '@/app/actions/reports';
import { BaziAssessmentModal } from '@/components/assessments/BaziAssessmentModal';
import { NumerologyAssessmentModal } from '@/components/assessments/NumerologyAssessmentModal';
import { BoneWeightChapter, DirectionChapter, EducationChapter } from './DestinyChapters';
import { Button } from '@/components/ui/Button';
import { Container } from '@/components/ui/Container';
import { Logo } from '@/components/ui/Logo';
import { cn } from '@/lib/cn';
import { AskAiSheet, type ChatSeed } from './AskAiSheet';
import { chaptersFor, type ChapterId } from './chapters';
import { isBundle, type Service } from '@/lib/reports/services';
import {
  AuraBodyChapter,
  AuraPhotoChapter,
  AuraScriptChapter,
  ChakraGraphChapter,
  ColorPersonalityChapter,
  EnergyGraphsChapter,
} from './AuraChapters';
import {
  BaziChapter,
  CareerChapter,
  ChapterOrder,
  CHAKRA_ORDER,
  NumerologyChapter,
  RelationshipChapter,
  RitualChapter,
  SummaryChapter,
  type AuraModel,
  type ReportModel,
} from './ReportChapters';



export type ReportViewMode =
  /** Signed-in viewer with access: Tanya AI + editing. */
  | { kind: 'member'; backHref: string; backLabel: string; canEdit: boolean }
  /** Opened from a participant's QR link. */
  | { kind: 'shared'; signedIn: boolean };

export function ReportView({ report, mode }: { report: ReportData; mode: ReportViewMode }) {
  const router = useRouter();
  const locale = useLocale();
  const all = useMessages();
  const t = all.report.view;
  const [aiOpen, setAiOpen] = useState(false);
  const [seed, setSeed] = useState<ChatSeed | null>(null);
  const [modal, setModal] = useState<'bazi' | 'numerology' | null>(null);
  const [, startTransition] = useTransition();
  const sv = all.services;

  // An aura service without aura data can't render, so it doesn't count.
  const services = useMemo(
    () => report.services.filter((s) => s !== 'aura' || (report.aura && report.scan)),
    [report],
  );
  const has = (s: Service) => services.includes(s);
  const chapters = useMemo(() => chaptersFor(services), [services]);
  const active = useScrollSpy(chapters);

  const isMember = mode.kind === 'member';
  const model: ReportModel = useMemo(() => {
    const samples = getSamples();
    return {
      services,
      aura: report.aura,
      bazi: report.bazi ?? samples.bazi,
      numerology: report.numerology ?? samples.numerology,
      scan: report.scan,
      photo: report.photo,
      isSample: {
        bazi: services.includes('bazi') && !report.bazi,
        numerology: services.includes('numerology') && !report.numerology,
      },
      canEdit: mode.kind === 'member' && mode.canEdit,
    };
  }, [report, mode, services]);
  const auraModel = model.aura && model.scan ? (model as AuraModel) : null;

  const { aura, bazi, numerology } = model;
  const bundle = isBundle(services);
  const blueprint = useMemo(
    () => (bundle && aura ? synthesizePersonalBlueprint(aura, bazi, numerology, locale) : null),
    [bundle, aura, bazi, numerology, locale],
  );
  const meta = chakraMeta(locale);
  const dominant = aura ? meta[aura.dominantChakra] : null;
  const growth = aura ? meta[aura.growthChakra] : null;
  const dmLabel = `${all.insights.polarity[bazi.dayMaster.polarity]} ${ELEMENT_INFO[locale][bazi.dayMaster.element].name}`;
  const coverTitle =
    dominant?.archetype ??
    (has('bazi')
      ? sv.cover.dayMaster(dmLabel)
      : sv.cover.lifePath(numerology.lifePath, numerologyTitle(numerology.lifePath, locale)));
  const coverText = report.scan?.summary ?? sv.cover.reportOf(services.map((s) => sv.names[s]).join(sv.cover.and));
  const glow = dominant?.color ?? '#5B6CFF';
  const coverStats: string[][] = [
    ...(aura && dominant
      ? [
          [t.energy, `${aura.overallEnergyScore}%`],
          [t.dominantChakra, dominant.short],
        ]
      : []),
    ...(has('bazi') ? [[t.dayMaster, model.isSample.bazi ? t.notFilled : dmLabel]] : []),
    ...(has('numerology') ? [[t.lifePath, model.isSample.numerology ? t.notFilled : String(numerology.lifePath)]] : []),
  ];

  // Tanya AI lives here, on the report, for members. Shared viewers are invited to save the report first.
  const ask = (question?: string) => {
    if (question) setSeed({ id: Date.now(), text: question });
    setAiOpen(true);
  };
  const chapterProps = { profile: model, blueprint, onAsk: isMember ? ask : undefined };

  const save = (fn: () => Promise<{ ok: boolean }>) =>
    startTransition(async () => {
      if ((await fn()).ok) router.refresh();
    });

  const createdOn = new Date(report.createdAt).toLocaleDateString(INTL_LOCALE[locale], {
    day: 'numeric',
    month: 'long',
    year: 'numeric',
  });

  return (
    <div
      className={cn(
        'min-h-screen bg-canvas transition-[padding] duration-400 ease-out-expo',
        aiOpen && 'lg:pr-[420px]',
      )}
    >
      {/* Top bar */}
      <header className="sticky top-0 z-30 border-b border-line/80 bg-canvas/85 backdrop-blur-xl backdrop-saturate-150 print:hidden">
        <div className="mx-auto flex h-16 max-w-[1200px] items-center justify-between gap-4 px-5 sm:px-8">
          {isMember ? (
            <Link
              href={mode.backHref}
              className="-ml-2 inline-flex items-center gap-1.5 rounded-full px-2 py-1.5 text-[13px] font-medium text-ink-soft transition-colors hover:text-ink"
            >
              <ArrowLeft className="size-4" aria-hidden />
              {mode.backLabel}
            </Link>
          ) : (
            <Logo tone="dark" />
          )}
          <p className="absolute left-1/2 hidden -translate-x-1/2 text-sm font-semibold text-ink sm:block">
            {t.title}
          </p>
          <div className="flex items-center gap-2">
            <button
              type="button"
              onClick={() => window.print()}
              aria-label={t.print}
              title={t.printTitle}
              className="hidden size-9 items-center justify-center rounded-full text-ink-soft transition-colors hover:bg-surface hover:text-ink sm:inline-flex"
            >
              <Printer className="size-4" />
            </button>
            {isMember ? (
              <Button size="sm" variant="dark" onClick={() => ask()} aria-expanded={aiOpen}>
                <Sparkles className="size-3.5" aria-hidden />
                {t.askAi}
              </Button>
            ) : (
              !report.isClaimed && <ClaimButton token={report.shareToken} size="sm" label={t.saveReport} />
            )}
          </div>
        </div>
      </header>

      {/* Mobile chapter nav */}
      <nav
        aria-label={t.chaptersNav}
        className="sticky top-16 z-20 border-b border-line/80 bg-canvas/90 backdrop-blur-xl lg:hidden print:hidden"
      >
        <ChapterChips chapters={chapters} active={active} />
      </nav>

      <Container className="py-8 sm:py-12">
        {mode.kind === 'shared' && !report.isClaimed && <ClaimBanner token={report.shareToken} signedIn={mode.signedIn} />}

        {/* Cover */}
        <section
          aria-label={t.cover}
          className="relative overflow-hidden rounded-panel bg-night-950 p-6 text-white sm:p-10 print:break-after-page"
        >
          <div
            aria-hidden
            className="absolute -top-24 -right-24 size-[420px] rounded-full opacity-40 blur-3xl"
            style={{ background: `radial-gradient(circle, ${glow}, transparent 65%)` }}
          />
          <div className="relative flex flex-col gap-8 sm:flex-row sm:items-center">
            <AuraPortrait photo={report.photo} colors={CHAKRA_ORDER.map((k) => meta[k].color)} alt={all.insights.auraPhotoAlt} />
            <div className="min-w-0">
              <p className="eyebrow text-white/50">
                {report.subjectName} · {createdOn}
                {report.event && ` · ${report.event.name}`}
              </p>
              <h1 className="mt-4 text-[32px] leading-[1.08] font-semibold tracking-[-0.025em] sm:text-[44px]">
                {coverTitle}
              </h1>
              <p className="mt-4 max-w-xl text-[15px] leading-relaxed text-white/65">{coverText}</p>
              <ul className="mt-5 flex flex-wrap gap-2">
                {services.map((s) => (
                  <li key={s} className="rounded-full bg-white/10 px-3 py-1 text-xs font-medium text-white/80">
                    {sv.names[s]}
                  </li>
                ))}
              </ul>
            </div>
          </div>

          <dl
            className={cn(
              'relative mt-10 grid grid-cols-2 gap-px overflow-hidden rounded-card bg-white/10',
              ['', 'sm:grid-cols-1', 'sm:grid-cols-2', 'sm:grid-cols-3', 'sm:grid-cols-4'][coverStats.length],
            )}
          >
            {coverStats.map(([label, value]) => (
              <div key={label} className="bg-night-950/80 p-4 sm:p-5">
                <dt className="text-[11px] text-white/45">{label}</dt>
                <dd className="mt-1.5 truncate text-[17px] font-semibold">{value}</dd>
              </div>
            ))}
          </dl>
        </section>

        <div className="mt-12 grid gap-12 lg:mt-16 lg:grid-cols-[200px_minmax(0,1fr)] lg:gap-16">
          {/* Desktop chapter nav */}
          <aside className="hidden lg:block print:hidden">
            <nav aria-label={t.chaptersNav} className="sticky top-24">
              <p className="eyebrow text-subtle">{t.toc}</p>
              <ol className="mt-5 space-y-1 border-l border-line">
                {chapters.map((c, i) => (
                  <li key={c}>
                    <a
                      href={`#${c}`}
                      aria-current={active === c ? 'location' : undefined}
                      className={cn(
                        '-ml-px flex gap-3 border-l py-1.5 pl-4 text-[13px] transition-colors',
                        active === c
                          ? 'border-ink font-semibold text-ink'
                          : 'border-transparent text-muted hover:text-ink',
                      )}
                    >
                      <span className="w-4 text-subtle tabular-nums">{i + 1}</span>
                      {t.chapters[c]}
                    </a>
                  </li>
                ))}
              </ol>

              {isMember && (
                <button
                  type="button"
                  onClick={() => ask()}
                  className="group mt-8 w-full rounded-card bg-surface p-4 text-left shadow-card ring-1 ring-line/70 transition-shadow hover:shadow-card-hover"
                >
                  <Sparkles className="size-4 text-accent" aria-hidden />
                  <p className="mt-3 text-[13px] font-semibold text-ink">{t.unclear}</p>
                  <p className="mt-1 text-xs leading-relaxed text-muted">{t.askAboutReport}</p>
                </button>
              )}
            </nav>
          </aside>

          <div className="min-w-0 space-y-20">
            <ChapterOrder.Provider value={chapters}>
              {auraModel && (
                <>
                  <AuraPhotoChapter profile={auraModel} onAsk={chapterProps.onAsk} />
                  <AuraBodyChapter profile={auraModel} onAsk={chapterProps.onAsk} />
                  <ChakraGraphChapter profile={auraModel} onAsk={chapterProps.onAsk} />
                  <EnergyGraphsChapter profile={auraModel} onAsk={chapterProps.onAsk} />
                  <AuraScriptChapter profile={auraModel} onAsk={chapterProps.onAsk} />
                  <ColorPersonalityChapter profile={auraModel} onAsk={chapterProps.onAsk} />
                </>
              )}
              {has('bazi') && (
                <>
                  <BaziChapter {...chapterProps} onComplete={() => setModal('bazi')} />
                  <BoneWeightChapter {...chapterProps} onComplete={() => setModal('bazi')} />
                  <DirectionChapter {...chapterProps} onComplete={() => setModal('bazi')} />
                </>
              )}
              {has('numerology') && <NumerologyChapter {...chapterProps} onComplete={() => setModal('numerology')} />}
              {has('bazi') && (
                <>
                  <CareerChapter {...chapterProps} />
                  <EducationChapter {...chapterProps} onComplete={() => setModal('bazi')} />
                  <RelationshipChapter {...chapterProps} onComplete={() => setModal('bazi')} />
                </>
              )}
              {blueprint && <SummaryChapter {...chapterProps} blueprint={blueprint} />}
              {auraModel && <RitualChapter profile={auraModel} blueprint={blueprint} onAsk={chapterProps.onAsk} />}
            </ChapterOrder.Provider>

            {model.canEdit && services.length < 3 && <AddServices services={services} onAdd={(s) => setModal(s)} />}

            {/* Closing */}
            <section className="rounded-panel bg-night-950 p-8 text-white sm:p-10 print:hidden">
              {isMember ? (
                <>
                  <h2 className="text-2xl font-semibold tracking-[-0.02em]">{t.closingTitle}</h2>
                  <p className="mt-3 max-w-lg text-[15px] leading-relaxed text-white/65">{growth ? t.closingText(growth.name) : sv.closingText}</p>
                  <div className="mt-8 flex flex-wrap items-center gap-x-8 gap-y-4">
                    <Button variant="light" onClick={() => ask()}>
                      <Sparkles className="size-4" aria-hidden />
                      {t.askAi}
                    </Button>
                    <Link
                      href="/akun?foto=1"
                      className="inline-flex items-center gap-2 text-sm font-medium text-white/75 transition-colors hover:text-white"
                    >
                      <RefreshCw className="size-4" aria-hidden />
                      {t.newPhoto}
                    </Link>
                  </div>
                </>
              ) : (
                <>
                  <h2 className="text-2xl font-semibold tracking-[-0.02em]">{t.sharedTitle}</h2>
                  <p className="mt-3 max-w-lg text-[15px] leading-relaxed text-white/65">{t.sharedText}</p>
                  <div className="mt-8">
                    {report.isClaimed ? (
                      <Button variant="light" href="/masuk" withArrow>
                        {t.signIn}
                      </Button>
                    ) : (
                      <ClaimButton token={report.shareToken} variant="light" label={t.saveToAccount} />
                    )}
                  </div>
                </>
              )}
            </section>
          </div>
        </div>
      </Container>

      {isMember && (
        <AskAiSheet
          open={aiOpen}
          onClose={() => setAiOpen(false)}
          seed={seed}
          reportId={report.id}
          suggestions={growth && has('numerology') ? t.suggestions(growth.name, numerology.lifePath) : sv.suggestions}
        />
      )}

      {model.canEdit && (
        <>
          <BaziAssessmentModal
            isOpen={modal === 'bazi'}
            onClose={() => setModal(null)}
            onComplete={(res) => save(() => saveReportBazi(report.id, res))}
          />
          <NumerologyAssessmentModal
            isOpen={modal === 'numerology'}
            onClose={() => setModal(null)}
            onComplete={(res) => save(() => saveReportNumerology(report.id, res))}
          />
        </>
      )}
    </div>
  );
}

/* ------------------------------------------------------------------ */

/** Lets the owner add the services this report doesn't include yet. */
function AddServices({ services, onAdd }: { services: Service[]; onAdd: (s: 'bazi' | 'numerology') => void }) {
  const sv = useMessages().services;
  const missing = (['bazi', 'numerology'] as const).filter((s) => !services.includes(s));
  return (
    <section className="rounded-panel bg-surface p-6 shadow-card ring-1 ring-line/70 sm:p-8 print:hidden">
      <h2 className="text-lg font-semibold text-ink">{sv.add.title}</h2>
      <p className="mt-1 text-sm text-muted">{sv.add.text}</p>
      <div className="mt-5 grid gap-3 sm:grid-cols-3">
        {missing.map((s) => (
          <button
            key={s}
            type="button"
            onClick={() => onAdd(s)}
            className="group rounded-2xl p-4 text-left ring-1 ring-line transition-colors hover:bg-canvas"
          >
            <Plus className="size-4 text-accent" aria-hidden />
            <p className="mt-2 text-sm font-semibold text-ink">{sv.add.action(sv.names[s])}</p>
            <p className="mt-1 text-xs leading-relaxed text-muted">{sv.picker.items[s]}</p>
          </button>
        ))}
        {!services.includes('aura') && (
          <Link href="/akun?foto=1" className="group rounded-2xl p-4 text-left ring-1 ring-line transition-colors hover:bg-canvas">
            <Camera className="size-4 text-accent" aria-hidden />
            <p className="mt-2 text-sm font-semibold text-ink">{sv.add.newPhoto}</p>
            <p className="mt-1 text-xs leading-relaxed text-muted">{sv.add.auraText}</p>
          </Link>
        )}
      </div>
    </section>
  );
}

function ClaimButton({
  token,
  label,
  size = 'md',
  variant = 'dark',
}: {
  token: string;
  label: string;
  size?: 'sm' | 'md';
  variant?: 'dark' | 'light';
}) {
  return (
    <form action={claimReport}>
      <input type="hidden" name="token" value={token} />
      <Button type="submit" size={size} variant={variant} withArrow={size === 'md'}>
        {label}
      </Button>
    </form>
  );
}

function ClaimBanner({ token, signedIn }: { token: string; signedIn: boolean }) {
  const t = useMessages().report.view;
  return (
    <div className="mb-6 flex flex-col gap-4 rounded-card bg-surface p-5 shadow-card ring-1 ring-line/70 sm:flex-row sm:items-center sm:justify-between print:hidden">
      <div>
        <p className="text-sm font-semibold text-ink">{t.claimTitle}</p>
        <p className="mt-1 text-[13px] leading-relaxed text-muted">{signedIn ? t.claimSignedIn : t.claimGuest}</p>
      </div>
      <ClaimButton token={token} size="sm" label={signedIn ? t.saveToAccount : t.saveReport} />
    </div>
  );
}

function AuraPortrait({ photo, colors, alt }: { photo: string | null; colors: string[]; alt: string }) {
  const ring = `conic-gradient(from 180deg, ${[...colors, colors[0]].join(', ')})`;
  return (
    <div className="relative size-28 shrink-0 rounded-full p-[3px] sm:size-36" style={{ background: ring }}>
      <div aria-hidden className="absolute inset-0 rounded-full opacity-60 blur-xl" style={{ background: ring }} />
      <div className="relative size-full overflow-hidden rounded-full border-[3px] border-night-950 bg-night-800">
        {photo ? (
          // Data URL captured on-device — next/image adds nothing here.
          // eslint-disable-next-line @next/next/no-img-element
          <img src={photo} alt={alt} className="size-full object-cover" />
        ) : (
          <Camera className="m-auto mt-[38%] size-7 text-white/40" aria-hidden />
        )}
      </div>
    </div>
  );
}

function ChapterChips({ chapters, active }: { chapters: ChapterId[]; active: string }) {
  const t = useMessages().report.view;
  const listRef = useRef<HTMLOListElement>(null);

  useEffect(() => {
    const el = listRef.current?.querySelector<HTMLElement>(`[data-id="${active}"]`);
    el?.scrollIntoView({ inline: 'center', block: 'nearest', behavior: 'smooth' });
  }, [active]);

  return (
    <ol ref={listRef} className="no-scrollbar flex gap-1.5 overflow-x-auto px-5 py-2.5 sm:px-8">
      {chapters.map((c) => (
        <li key={c} data-id={c} className="shrink-0">
          <a
            href={`#${c}`}
            aria-current={active === c ? 'location' : undefined}
            className={cn(
              'block rounded-full px-3.5 py-1.5 text-[13px] font-medium transition-colors',
              active === c ? 'bg-ink text-white' : 'text-muted hover:text-ink',
            )}
          >
            {t.chapters[c]}
          </a>
        </li>
      ))}
    </ol>
  );
}

function useScrollSpy(ids: readonly string[]) {
  const [active, setActive] = useState(ids[0]);
  const key = ids.join(',');

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        const visible = entries.filter((e) => e.isIntersecting);
        if (visible.length) setActive(visible[0].target.id);
      },
      { rootMargin: '-30% 0px -60% 0px' },
    );
    key.split(',').forEach((id) => {
      const el = document.getElementById(id);
      if (el) observer.observe(el);
    });
    return () => observer.disconnect();
  }, [key]);

  return active;
}
