"use client";

import { useEffect, useId, useRef, useState, type Dispatch, type SetStateAction } from "react";

import {
  TUVI_INTERPRETATION_PROSE_MISSING_VI,
  TUVI_INTERPRETATION_STRUCTURED_FALLBACK_VI,
  TUVI_PALACE_NO_MAJOR_STARS_VI,
  TUVI_STAR_NO_IN_PALACE_RULE_MESSAGE_VI,
  type MajorStarEffectsUi,
  type MajorStarInPalaceRuleUi,
  type MajorStarMeaningUi,
  type PalaceInterpretationCardUi,
  type PalaceProseUi,
  type TuViInterpretationDebugUiV1,
  type TuViMajorStarInterpretBundleUi,
  type TuViPalaceInterpretationRowUi,
} from "@/lib/tuvi-interpretation-context";
import {
  getPalaceProseDebugSectionOrder,
  getPalaceStarEffectKeys,
  getPalaceStructuredCardSectionOrder,
} from "@/lib/tuvi-palace-section-priority";

const CARD =
  "rounded-xl border border-[#d4af37]/14 bg-[linear-gradient(168deg,rgba(12,18,36,0.72)_0%,rgba(4,6,14,0.88)_100%)] px-3.5 py-3 shadow-[inset_0_1px_0_rgba(255,255,255,0.04),inset_0_-12px_32px_rgba(0,0,0,0.22)] sm:px-4 sm:py-3.5";

const INNER =
  "rounded-lg border border-[#d4af37]/10 bg-[#050814]/45 px-2.5 py-2 sm:px-3 sm:py-2.5";

const H_SECTION =
  "font-ctkp-serif text-[10px] uppercase tracking-[0.16em] text-[#d4af37]/72";

const LIST = "list-none space-y-1 pl-0";

const STRUCTURED_SECTIONS: { key: keyof PalaceInterpretationCardUi["sections"]; title: string }[] = [
  { key: "temperament", title: "Tính cách" },
  { key: "career", title: "Sự nghiệp" },
  { key: "finance", title: "Tài chính" },
  { key: "relationship", title: "Tình cảm" },
  { key: "family", title: "Gia đạo" },
  { key: "health", title: "Sức khỏe" },
  { key: "fortune", title: "Vận hạn" },
  { key: "advice", title: "Lời khuyên" },
];

const PROSE_SECTION_META: { key: keyof PalaceProseUi["sections"]; title: string }[] = [
  { key: "overview", title: "Tổng quan" },
  { key: "career", title: "Công danh" },
  { key: "finance", title: "Tài lộc" },
  { key: "love", title: "Tình cảm" },
  { key: "family", title: "Gia đình" },
  { key: "health", title: "Sức khỏe" },
  { key: "fortune", title: "Phúc vận" },
  { key: "advice", title: "Lời khuyên" },
];

function BulletList({ items, empty }: { items: string[]; empty: string }) {
  const xs = items.map((s) => String(s).trim()).filter(Boolean);
  if (xs.length === 0) return <p className="font-sans text-[11px] leading-relaxed text-slate-500">{empty}</p>;
  return (
    <ul className={LIST}>
      {xs.map((line, i) => (
        <li
          key={i}
          className="relative pl-3 font-sans text-[11px] leading-relaxed text-slate-300/95 before:absolute before:left-0 before:top-[0.5em] before:h-1 before:w-1 before:rounded-sm before:bg-[#d4af37]/50 before:content-['']"
        >
          {line}
        </li>
      ))}
    </ul>
  );
}

const CORE_BLOCKS: {
  key: keyof NonNullable<MajorStarMeaningUi["coreMeanings"]>;
  title: string;
}[] = [
  { key: "overview", title: "Tổng quan" },
  { key: "personality", title: "Tính cách" },
  { key: "career", title: "Công danh" },
  { key: "finance", title: "Tài lộc" },
  { key: "love", title: "Tình cảm" },
  { key: "family", title: "Gia đình" },
  { key: "health", title: "Sức khỏe" },
];

function CoreMeaningsSection({ meaning }: { meaning: MajorStarMeaningUi | null }) {
  const cm = meaning?.coreMeanings;
  if (!cm) return <p className="font-sans text-[11px] text-slate-500">—</p>;
  const any =
    (cm.overview?.length ?? 0) +
      (cm.personality?.length ?? 0) +
      (cm.career?.length ?? 0) +
      (cm.finance?.length ?? 0) +
      (cm.love?.length ?? 0) +
      (cm.family?.length ?? 0) +
      (cm.health?.length ?? 0) >
    0;
  if (!any) return <p className="font-sans text-[11px] text-slate-500">—</p>;
  return (
    <div className="mt-2 space-y-2.5">
      {CORE_BLOCKS.map(({ key, title }) => {
        const arr = cm[key];
        if (!Array.isArray(arr) || arr.length === 0) return null;
        const lines = arr.map((s) => String(s).trim()).filter(Boolean);
        if (lines.length === 0) return null;
        return (
          <div key={key}>
            <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.12em] text-[#d4af37]/58">{title}</p>
            <BulletList items={lines} empty="—" />
          </div>
        );
      })}
    </div>
  );
}

const EFFECT_LABELS: { key: keyof MajorStarEffectsUi; title: string }[] = [
  { key: "overview", title: "Tổng quan" },
  { key: "career", title: "Công danh" },
  { key: "finance", title: "Tài chính" },
  { key: "love", title: "Tình cảm" },
  { key: "family", title: "Gia đình" },
  { key: "health", title: "Sức khỏe" },
  { key: "fortune", title: "Phúc vận" },
];

function RuleBlock({ rule, palaceKey }: { rule: MajorStarInPalaceRuleUi; palaceKey: string }) {
  const eff = rule.effects;
  const allowedEffectKeys = new Set(getPalaceStarEffectKeys(palaceKey));
  return (
    <div className="mt-2.5 rounded-md border border-[#d4af37]/08 bg-black/20 px-2.5 py-2 first:mt-0">
      <p className="font-ctkp-serif text-[12px] leading-snug text-[#faf6e8]/95">{rule.title || "—"}</p>
      <p className="mt-1 font-sans text-[11px] leading-relaxed text-slate-300/95">{rule.summary || ""}</p>
      {eff && typeof eff === "object" ?
        <div className="mt-2 space-y-2">
          {EFFECT_LABELS.filter(({ key }) => allowedEffectKeys.has(key)).map(({ key, title }) => {
            const arr = eff[key];
            if (!Array.isArray(arr) || arr.length === 0) return null;
            const lines = arr.map((s) => String(s).trim()).filter(Boolean);
            if (lines.length === 0) return null;
            return (
              <div key={key}>
                <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.1em] text-[#d4af37]/55">{title}</p>
                <BulletList items={lines} empty="" />
              </div>
            );
          })}
        </div>
      : null}
      <div className="mt-2 grid gap-2 sm:grid-cols-3">
        <div>
          <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.1em] text-emerald-200/85">Strengths</p>
          <BulletList items={rule.strengths ?? []} empty="—" />
        </div>
        <div>
          <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.1em] text-rose-200/80">Risks</p>
          <BulletList items={rule.risks ?? []} empty="—" />
        </div>
        <div>
          <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.1em] text-[#e8d9a8]/75">Advice</p>
          <BulletList items={rule.advice ?? []} empty="—" />
        </div>
      </div>
    </div>
  );
}

function StarLuatTaiCung({ star, palaceKey }: { star: TuViMajorStarInterpretBundleUi; palaceKey: string }) {
  const rules = Array.isArray(star.inPalaceRules) ? star.inPalaceRules : [];
  if (rules.length === 0) {
    return <p className="mt-1 font-sans text-[11px] leading-relaxed text-slate-400">{TUVI_STAR_NO_IN_PALACE_RULE_MESSAGE_VI}</p>;
  }
  return (
    <div className="mt-1 space-y-1">
      {rules.map((rule, idx) => (
        <RuleBlock key={`${star.key}-${rule.title}-${idx}`} rule={rule} palaceKey={palaceKey} />
      ))}
    </div>
  );
}

function StarChinhTinhBlock({ star }: { star: TuViMajorStarInterpretBundleUi }) {
  const kw = (star.meaning?.keywords ?? []).map((k) => String(k).trim()).filter(Boolean);
  return (
    <div className="mt-3 border-t border-[#d4af37]/08 pt-3 first:mt-0 first:border-t-0 first:pt-0">
      <p className="font-ctkp-serif text-[12px] text-[#e8d9a8]/92">{star.label || star.key}</p>
      {kw.length > 0 ?
        <p className="mt-1 font-sans text-[10px] leading-relaxed text-slate-500">{kw.join(" · ")}</p>
      : null}
      <CoreMeaningsSection meaning={star.meaning} />
    </div>
  );
}

function TuViLuanCungRawSeedAccordionBody({
  palaceRows,
  baseId,
  openSet,
  setOpenSet,
  selectedPalaceKey,
  onSelectPalace,
  bodyPalaceKey,
}: {
  palaceRows: TuViPalaceInterpretationRowUi[];
  baseId: string;
  openSet: Set<string>;
  setOpenSet: Dispatch<SetStateAction<Set<string>>>;
  selectedPalaceKey: string;
  onSelectPalace: (palaceKey: string) => void;
  bodyPalaceKey?: string | null;
}) {
  return (
    <div className="space-y-2">
      {palaceRows.map((row) => {
        const open = openSet.has(row.palaceKey);
        const panelId = `${baseId}-raw-panel-${row.palaceKey}`;
        const btnId = `${baseId}-raw-btn-${row.palaceKey}`;
        const isMenh = row.palaceKey === "menh";
        const isBody = bodyPalaceKey === row.palaceKey && Boolean(bodyPalaceKey);
        const starLine = row.majorStars.map((s) => s.label || s.key).filter(Boolean).join(", ");
        const warnings = Array.isArray(row.warnings) ? row.warnings : [];

        return (
          <div key={row.palaceKey} id={`${baseId}-raw-acc-${row.palaceKey}`} className={CARD}>
            <div className="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
              <button
                type="button"
                id={btnId}
                aria-expanded={open}
                aria-controls={panelId}
                onClick={() => {
                  onSelectPalace(row.palaceKey);
                  setOpenSet((prev) => {
                    const next = new Set(prev);
                    if (next.has(row.palaceKey)) next.delete(row.palaceKey);
                    else next.add(row.palaceKey);
                    return next;
                  });
                }}
                className="flex w-full min-w-0 flex-1 flex-col items-start text-left transition-opacity hover:opacity-95"
              >
                <span className="font-ctkp-serif text-[9px] uppercase tracking-[0.18em] text-[#d4af37]/60">
                  {open ? "Thu gọn" : "Mở rộng"} (seed)
                </span>
                <span className="mt-0.5 font-ctkp-serif text-[14px] font-normal leading-snug tracking-wide text-[#faf6e8] sm:text-[15px]">
                  {row.palaceLabel}
                  <span className="text-[#d4af37]/75"> · </span>
                  <span className="font-sans text-[13px] font-normal text-slate-300/95">{row.branch || "—"}</span>
                </span>
                {starLine ? <span className="mt-1 font-sans text-[11px] leading-snug text-[#ece6d8]/88">{starLine}</span> : null}
              </button>
              <div className="flex shrink-0 flex-wrap justify-end gap-1 sm:pt-0.5">
                {isMenh ?
                  <span className="rounded border border-emerald-500/28 bg-emerald-950/28 px-1.5 py-0.5 font-ctkp-serif text-[9px] uppercase tracking-[0.08em] text-emerald-100/88">
                    Mệnh
                  </span>
                : null}
                {isBody ?
                  <span className="rounded border border-violet-400/25 bg-violet-950/28 px-1.5 py-0.5 font-ctkp-serif text-[9px] uppercase tracking-[0.08em] text-violet-200/85">
                    Thân
                  </span>
                : null}
              </div>
            </div>

            {open ?
              <div
                id={panelId}
                role="region"
                aria-labelledby={btnId}
                className="mt-3 space-y-2.5 border-t border-[#d4af37]/10 pt-3"
              >
                <div className={INNER}>
                  <p className={H_SECTION}>Cung này nói về gì</p>
                  {row.palaceMeaning?.summary ?
                    <p className="mt-1.5 font-sans text-[11px] leading-relaxed text-slate-200/95">{row.palaceMeaning.summary}</p>
                  : <p className="mt-1.5 font-sans text-[11px] text-slate-500">—</p>}
                </div>

                <div className={INNER}>
                  <p className={H_SECTION}>Trọng tâm luận</p>
                  {row.palaceMeaning?.interpretationFocus?.length ?
                    <div className="mt-1.5">
                      <BulletList items={row.palaceMeaning.interpretationFocus} empty="—" />
                    </div>
                  : <p className="mt-1.5 font-sans text-[11px] text-slate-500">—</p>}
                </div>

                <div className={INNER}>
                  <p className={H_SECTION}>Chính tinh trong cung</p>
                  {row.majorStars.length === 0 ?
                    <p className="mt-1.5 font-sans text-[11px] leading-relaxed text-slate-400">{TUVI_PALACE_NO_MAJOR_STARS_VI}</p>
                  : row.majorStars.map((star) => <StarChinhTinhBlock key={star.key} star={star} />)}
                </div>

                <div className={INNER}>
                  <p className={H_SECTION}>Luận sao tại cung</p>
                  {row.majorStars.length === 0 ?
                    <p className="mt-1.5 font-sans text-[11px] text-slate-500">—</p>
                  : (
                    <div className="mt-1.5 space-y-3">
                      {row.majorStars.map((star) => (
                        <div key={`luat-${star.key}`}>
                          <p className="font-ctkp-serif text-[11px] text-[#e8d9a8]/88">{star.label || star.key}</p>
                          <StarLuatTaiCung star={star} palaceKey={row.palaceKey} />
                        </div>
                      ))}
                    </div>
                  )}
                </div>

                {warnings.length > 0 ?
                  <div className={INNER}>
                    <p className={H_SECTION}>Cảnh báo dữ liệu</p>
                    <BulletList items={warnings} empty="—" />
                  </div>
                : null}
              </div>
            : null}
          </div>
        );
      })}
    </div>
  );
}

type Props = {
  /** Luận văn xuôi từ engine — ưu tiên hiển thị. */
  palaceProses: PalaceProseUi[] | null;
  /** Dữ liệu seed thô — chỉ khi bật chế độ xem chi tiết (dev). */
  palaceRows: TuViPalaceInterpretationRowUi[] | null;
  /** Bật panel chi tiết kỹ thuật (chỉ môi trường không production + biến debug). */
  proseDebugUi?: boolean;
  /** Tham số URL dành cho nội bộ — chỉ hoạt động ngoài production. */
  rawSeedDebug?: boolean;
  /** Dữ liệu đối chiếu kỹ thuật khi bật panel chi tiết. */
  interpretationDebugBlock?: TuViInterpretationDebugUiV1 | null;
  selectedPalaceKey: string;
  onSelectPalace: (palaceKey: string) => void;
  bodyPalaceKey?: string | null;
  className?: string;
};

function palaceKeysForInitialOpenFromProse(palaceProses: PalaceProseUi[] | null, bodyPalaceKey?: string | null): string[] {
  if (!palaceProses?.length) return [];
  const keys = new Set<string>();
  if (palaceProses.some((p) => p.palaceKey === "menh")) keys.add("menh");
  const body = bodyPalaceKey?.trim();
  if (body && palaceProses.some((p) => p.palaceKey === body)) keys.add(body);
  return [...keys];
}

function palaceKeysForInitialOpenFromRows(palaceRows: TuViPalaceInterpretationRowUi[] | null, bodyPalaceKey?: string | null): string[] {
  if (!palaceRows?.length) return [];
  const keys = new Set<string>();
  const menhThanKeys = palaceRows.filter((r) => r.palaceMeaningKey === "menh_than").map((r) => r.palaceKey);
  if (menhThanKeys.length > 0) menhThanKeys.forEach((k) => keys.add(k));
  else if (palaceRows.some((r) => r.palaceKey === "menh")) keys.add("menh");
  const body = bodyPalaceKey?.trim();
  if (body && palaceRows.some((r) => r.palaceKey === body)) keys.add(body);
  return [...keys];
}

/**
 * Luận cung — ưu tiên `interpretationProse.palaceProses` (văn xuôi deterministic); dữ liệu seed thô chỉ khi bật chế độ xem chi tiết.
 */
export function TuViLuanCungSeedAccordion({
  palaceProses,
  palaceRows,
  proseDebugUi = false,
  rawSeedDebug = false,
  interpretationDebugBlock = null,
  selectedPalaceKey,
  onSelectPalace,
  bodyPalaceKey,
  className = "",
}: Props) {
  const baseId = useId();
  const openedDefault = useRef(false);
  const [openSet, setOpenSet] = useState<Set<string>>(() => new Set());
  const [rawOpenSet, setRawOpenSet] = useState<Set<string>>(() => new Set());

  const hasProse = Boolean(palaceProses && palaceProses.length > 0);
  const rows = palaceRows ?? [];
  const showRawPanel = rawSeedDebug && rows.length > 0;

  /* eslint-disable react-hooks/set-state-in-effect -- one-time initial open + scroll sync when palace selection changes */
  useEffect(() => {
    if (openedDefault.current) return;
    const proseKeys = palaceKeysForInitialOpenFromProse(palaceProses, bodyPalaceKey);
    const pr = palaceRows ?? [];
    const rawKeys = palaceKeysForInitialOpenFromRows(pr.length > 0 ? pr : null, bodyPalaceKey);
    if (proseKeys.length === 0 && rawKeys.length === 0) return;
    openedDefault.current = true;
    if (hasProse && proseKeys.length > 0) setOpenSet(new Set(proseKeys));
    if (rawSeedDebug && pr.length > 0 && rawKeys.length > 0) setRawOpenSet(new Set(rawKeys));
  }, [palaceProses, palaceRows, hasProse, rawSeedDebug, bodyPalaceKey]);

  useEffect(() => {
    if (!selectedPalaceKey) return;
    setOpenSet((prev) => {
      const next = new Set(prev);
      next.add(selectedPalaceKey);
      return next;
    });
    if (showRawPanel) {
      setRawOpenSet((prev) => {
        const next = new Set(prev);
        next.add(selectedPalaceKey);
        return next;
      });
    }
    const el = document.getElementById(`${baseId}-acc-${selectedPalaceKey}`);
    el?.scrollIntoView({ behavior: "smooth", block: "nearest" });
  }, [selectedPalaceKey, baseId, showRawPanel]);
  /* eslint-enable react-hooks/set-state-in-effect */

  if (!hasProse && !showRawPanel) {
    return (
      <div className={`mx-auto w-full max-w-[40rem] ${className}`} role="status">
        <div className={`${CARD} border-[#d4af37]/16 text-center`}>
          <p className="font-sans text-[12px] leading-relaxed text-slate-400">{TUVI_INTERPRETATION_PROSE_MISSING_VI}</p>
        </div>
      </div>
    );
  }

  return (
    <section
      className={`mx-auto w-full max-w-[40rem] space-y-3 ${className}`}
      aria-label="Luận cung — văn xuôi từ engine"
    >
      <div className={`${CARD} border-[#d4af37]/16`}>
        <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.22em] text-[#d4af37]/65">Mười hai cung</p>
        <h3 className="ctkp-tuvi-text-title-soft mt-1 font-ctkp-serif text-[15px] font-normal tracking-wide text-[#faf6e8]">
          Luận theo nghĩa cung và chính tinh
        </h3>
        <p className="ctkp-tuvi-text-muted mt-1 font-sans text-[11px] leading-relaxed">
          Bản luận do engine ghép từ nghĩa cung và chính tinh (deterministic, không AI). Đọc lần lượt từng ô như một đoạn trong sổ tay
          luận giải — mặc định mở Mệnh và Thân khi có trên lá.
        </p>
        {proseDebugUi && hasProse && palaceProses ?
          <p
            className="mt-2 rounded border border-amber-500/22 bg-amber-950/22 px-2 py-1.5 font-mono text-[10px] leading-snug tracking-wide text-amber-100/88"
            role="status"
          >
            Luận cung: đã có {palaceProses.length}/12 cung
          </p>
        : null}
      </div>

      {proseDebugUi ?
        <details className={`${CARD} border-amber-900/28 bg-[#080a12]/90`}>
          <summary className="cursor-pointer list-none font-ctkp-serif text-[11px] tracking-wide text-amber-200/88 outline-none [&::-webkit-details-marker]:hidden">
            <span className="inline-flex items-center gap-2">
              <span className="rounded-sm bg-amber-500/15 px-1 py-px font-mono text-[9px] uppercase tracking-[0.08em] text-amber-100/90">
                Nội bộ
              </span>
              Chi tiết kỹ thuật luận giải
            </span>
          </summary>
          <div className="mt-3 space-y-3 border-t border-[#d4af37]/12 pt-3 font-sans text-[11px] leading-relaxed text-slate-400">
            {interpretationDebugBlock ?
              <>
                <p>
                  <span className="font-ctkp-serif text-[10px] uppercase tracking-[0.12em] text-[#d4af37]/60">Số cung có luận</span>{" "}
                  <span className="tabular-nums text-slate-200">{interpretationDebugBlock.palaceCount}</span>
                </p>
                <p>
                  <span className="font-ctkp-serif text-[10px] uppercase tracking-[0.12em] text-[#d4af37]/60">Số đoạn luận</span>{" "}
                  <span className="tabular-nums text-slate-200">{interpretationDebugBlock.proseCount}</span>
                </p>
                <div>
                  <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.12em] text-[#d4af37]/60">
                    Cung chưa có nghĩa đủ
                  </p>
                  <p className="mt-1 font-mono text-[10px] text-slate-500">
                    {interpretationDebugBlock.missingPalaceMeanings.length ?
                      interpretationDebugBlock.missingPalaceMeanings.join(" · ")
                    : "—"}
                  </p>
                </div>
                <div>
                  <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.12em] text-[#d4af37]/60">
                    Sao chưa có nghĩa đủ
                  </p>
                  <p className="mt-1 font-mono text-[10px] text-slate-500">
                    {interpretationDebugBlock.missingMajorStarMeanings.length ?
                      interpretationDebugBlock.missingMajorStarMeanings.join(" · ")
                    : "—"}
                  </p>
                </div>
                <div>
                  <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.12em] text-[#d4af37]/60">
                    Quy tắc tại cung chưa đủ
                  </p>
                  <p className="mt-1 font-mono text-[10px] text-slate-500">
                    {interpretationDebugBlock.missingStarInPalaceRules.length ?
                      interpretationDebugBlock.missingStarInPalaceRules.join(" · ")
                    : "—"}
                  </p>
                </div>
              </>
            : (
              <p>
                Chưa có dữ liệu đối chiếu kỹ thuật cho lần tải này — ghi lại lá hoặc thử lại sau.
              </p>
            )}
            {palaceProses?.some((p) => p.quality) ?
              <div className="border-t border-[#d4af37]/10 pt-3">
                <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.12em] text-[#d4af37]/60">
                  Điểm chất lượng theo cung
                </p>
                <ul className="mt-2 space-y-2 font-mono text-[10px] leading-snug text-slate-400">
                  {palaceProses
                    .filter((p): p is typeof p & { quality: NonNullable<(typeof p)["quality"]> } => Boolean(p.quality))
                    .map((p) => (
                      <li key={p.palaceKey}>
                        <span className="text-slate-300">{p.palaceKey}</span>
                        <span className="mx-1.5 text-[#d4af37]/55">·</span>
                        <span className="tabular-nums text-amber-100/90">{p.quality.score}</span>
                        {p.quality.issues.length > 0 ?
                          <span className="mt-0.5 block pl-0 text-[9px] text-slate-500">{p.quality.issues.join(", ")}</span>
                        : null}
                      </li>
                    ))}
                </ul>
              </div>
            : (
              <p className="border-t border-[#d4af37]/10 pt-3 text-[10px] text-slate-500">
                Chưa có điểm chất lượng chi tiết theo từng cung trong lần tải hiện tại.
              </p>
            )}
          </div>
        </details>
      : null}

      {hasProse && palaceProses ?
        <div className="space-y-2.5">
          {palaceProses.map((p) => {
            const open = openSet.has(p.palaceKey);
            const panelId = `${baseId}-panel-${p.palaceKey}`;
            const btnId = `${baseId}-btn-${p.palaceKey}`;
            const isMenhBadge = p.card.isMenh === true || p.palaceKey === "menh";
            const isThanBadge = p.card.isThan === true || (bodyPalaceKey === p.palaceKey && Boolean(bodyPalaceKey));
            const branchShort = p.card.branchLabel || p.branch || "—";
            const titleLine = `${p.card.palaceName || p.palaceLabel} · ${branchShort.split("·").pop()?.trim() ?? branchShort}`;
            const warnings = Array.isArray(p.warnings) ? p.warnings : [];

            return (
              <div key={p.palaceKey} id={`${baseId}-acc-${p.palaceKey}`} className={CARD}>
                <div className="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
                  <button
                    type="button"
                    id={btnId}
                    aria-expanded={open}
                    aria-controls={panelId}
                    onClick={() => {
                      onSelectPalace(p.palaceKey);
                      setOpenSet((prev) => {
                        const next = new Set(prev);
                        if (next.has(p.palaceKey)) next.delete(p.palaceKey);
                        else next.add(p.palaceKey);
                        return next;
                      });
                    }}
                    className="flex w-full min-w-0 flex-1 flex-col items-start text-left transition-opacity hover:opacity-95"
                  >
                    <span className="font-ctkp-serif text-[9px] uppercase tracking-[0.18em] text-[#d4af37]/60">
                      {open ? "Thu gọn" : "Mở rộng"}
                    </span>
                    <span className="mt-0.5 min-w-0 font-ctkp-serif text-[14px] font-normal leading-snug tracking-wide text-[#faf6e8] sm:text-[15px]">
                      <span className="break-words">{titleLine}</span>
                    </span>
                  </button>
                  <div className="flex shrink-0 flex-wrap justify-end gap-1 sm:pt-0.5">
                    {isMenhBadge ?
                      <span className="rounded border border-emerald-500/28 bg-emerald-950/28 px-1.5 py-0.5 font-ctkp-serif text-[9px] uppercase tracking-[0.08em] text-emerald-100/88">
                        MỆNH
                      </span>
                    : null}
                    {isThanBadge ?
                      <span className="rounded border border-violet-400/25 bg-violet-950/28 px-1.5 py-0.5 font-ctkp-serif text-[9px] uppercase tracking-[0.08em] text-violet-200/85">
                        THÂN
                      </span>
                    : null}
                  </div>
                </div>

                {open ?
                  <div
                    id={panelId}
                    role="region"
                    aria-labelledby={btnId}
                    className="mt-3 space-y-3 border-t border-[#d4af37]/10 pt-3"
                  >
                    <div className={`${INNER} border-[#d4af37]/08 space-y-3 overflow-hidden`}>
                      <p className="break-words font-ctkp-serif text-[14px] leading-snug text-[#e8c96b] sm:text-[15px]">
                        {(p.card.headline ?? "").trim() || TUVI_INTERPRETATION_STRUCTURED_FALLBACK_VI}
                      </p>
                      <div className="rounded-md border border-[#d4af37]/22 bg-[linear-gradient(180deg,rgba(212,175,55,0.12)_0%,rgba(5,8,20,0.42)_100%)] px-3 py-2.5">
                        <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.14em] text-[#d4af37]/72">
                          Tóm tắt
                        </p>
                        <p className="mt-1 max-h-[5.5rem] overflow-y-auto whitespace-pre-line break-words font-sans text-[12px] leading-snug text-[#faf6e8]/95 sm:text-[13px]">
                          {(p.card.summary ?? "").trim() || TUVI_INTERPRETATION_STRUCTURED_FALLBACK_VI}
                        </p>
                      </div>
                      <div className="grid gap-2 sm:grid-cols-2">
                        {getPalaceStructuredCardSectionOrder(p.palaceKey).map((sectionKey) => {
                          const meta = STRUCTURED_SECTIONS.find((s) => s.key === sectionKey);
                          if (!meta) return null;
                          const arr = p.card.sections[sectionKey];
                          if (!Array.isArray(arr) || arr.length === 0) return null;
                          return (
                            <div
                              key={sectionKey}
                              className="flex max-h-[min(28vh,220px)] min-h-0 flex-col rounded-md border border-[#d4af37]/08 bg-black/22 px-2.5 py-2"
                            >
                              <p className={`${H_SECTION} shrink-0`}>{meta.title}</p>
                              <div className="mt-1.5 min-h-0 flex-1 overflow-y-auto pr-0.5">
                                <BulletList items={arr} empty="" />
                              </div>
                            </div>
                          );
                        })}
                      </div>

                      <details className="rounded-md border border-[#d4af37]/10 bg-black/18 px-2.5 py-2">
                        <summary className="cursor-pointer font-ctkp-serif text-[11px] tracking-wide text-[#d4af37]/85 outline-none [&::-webkit-details-marker]:hidden">
                          Cơ sở luận giải
                        </summary>
                        <div className="mt-2 space-y-2 border-t border-[#d4af37]/08 pt-2 font-sans text-[10px] leading-relaxed text-slate-400">
                          <p>
                            <span className="font-ctkp-serif text-[9px] uppercase tracking-[0.12em] text-[#d4af37]/55">
                              Chính tinh
                            </span>
                            <span className="mt-1 block break-words text-slate-300/90">
                              {p.card.evidence.majorStars.length ? p.card.evidence.majorStars.join(" · ") : "—"}
                            </span>
                          </p>
                          <p>
                            <span className="font-ctkp-serif text-[9px] uppercase tracking-[0.12em] text-[#d4af37]/55">
                              Phụ tinh
                            </span>
                            <span className="mt-1 block break-words text-slate-300/90">
                              {p.card.evidence.minorStars.length ? p.card.evidence.minorStars.join(" · ") : "—"}
                            </span>
                          </p>
                          <p>
                            <span className="font-ctkp-serif text-[9px] uppercase tracking-[0.12em] text-[#d4af37]/55">
                              Thẻ
                            </span>
                            <span className="mt-1 block break-words font-mono text-[9px] text-slate-500">
                              {p.card.evidence.tags.length ? p.card.evidence.tags.join(" · ") : "—"}
                            </span>
                          </p>
                        </div>
                      </details>
                    </div>

                    {proseDebugUi && warnings.length > 0 ?
                      <div className={`${INNER} border-[#d4af37]/06 bg-black/25`}>
                        <p className={H_SECTION}>Lưu ý khi đọc</p>
                        <div className="mt-1.5 space-y-1">
                          {warnings.map((w, i) => (
                            <p key={i} className="font-sans text-[10px] leading-relaxed text-slate-500">
                              {w}
                            </p>
                          ))}
                        </div>
                      </div>
                    : null}

                    {proseDebugUi ?
                      <details className={`${INNER} border-[#d4af37]/06`}>
                        <summary className="cursor-pointer font-ctkp-serif text-[11px] tracking-wide text-[#d4af37]/80 outline-none marker:text-[#d4af37]/60">
                          Chuỗi đoạn luận gộp (chi tiết)
                        </summary>
                        <div className="mt-2 space-y-2.5 border-t border-[#d4af37]/08 pt-2.5">
                          {getPalaceProseDebugSectionOrder(p.palaceKey).map((key) => {
                            const meta = PROSE_SECTION_META.find((m) => m.key === key);
                            if (!meta) return null;
                            const text = p.sections[key];
                            const t = typeof text === "string" ? text.trim() : "";
                            if (!t || t === "—") return null;
                            return (
                              <div key={key}>
                                <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.12em] text-[#d4af37]/58">{meta.title}</p>
                                <p className="mt-1 font-sans text-[11px] leading-relaxed text-slate-300/95">{t}</p>
                              </div>
                            );
                          })}
                        </div>
                      </details>
                    : null}
                  </div>
                : null}
              </div>
            );
          })}
        </div>
      : null}

      {showRawPanel ?
        <div className="space-y-2">
          <div className={`${CARD} border-amber-800/25 bg-amber-950/12`}>
            <p className="font-ctkp-serif text-[10px] uppercase tracking-[0.18em] text-amber-200/85">Chế độ xem chi tiết</p>
            <p className="mt-1 font-sans text-[11px] leading-relaxed text-amber-100/80">
              Đang xem dữ liệu kỹ thuật gốc (rule, từ khóa, cường độ…). Chỉ dùng trong môi trường phát triển qua tham số URL nội bộ.
            </p>
          </div>
          <TuViLuanCungRawSeedAccordionBody
            palaceRows={rows}
            baseId={baseId}
            openSet={rawOpenSet}
            setOpenSet={setRawOpenSet}
            selectedPalaceKey={selectedPalaceKey}
            onSelectPalace={onSelectPalace}
            bodyPalaceKey={bodyPalaceKey}
          />
        </div>
      : null}
    </section>
  );
}
