import type { PyramidProps } from "./schema";

/** 重みを高さ比率(%)に正規化。全重み0以下の退化ケースは均等割りにする */
export const normalizeWeights = (tiers: { weight: number }[]): number[] => {
  const total = tiers.reduce((s, t) => s + Math.max(0, t.weight), 0);
  if (total <= 0) return tiers.map(() => 100 / tiers.length);
  return tiers.map((t) => (Math.max(0, t.weight) / total) * 100);
};

/**
 * 各帯の頂点からの累積位置(%)。真の三角形では「頂点からの垂直位置」と
 * 「その高さでのテーパー幅」が同じ比率になるため、topWidthPct/bottomWidthPct
 * は帯の縦位置（top/height）と横のテーパー（clip-path）の両方に使い回せる。
 */
export const pyramidBands = (
  tiers: { weight: number }[],
): { heightPct: number; topWidthPct: number; bottomWidthPct: number }[] => {
  const heights = normalizeWeights(tiers);
  let acc = 0;
  return heights.map((h) => {
    const topWidthPct = acc;
    acc += h;
    return { heightPct: h, topWidthPct, bottomWidthPct: acc };
  });
};

/** 頂点→中間→底辺の固定indexを、帯・ガイド・ledgerの共有identityへ使う */
const TIER_STYLE = [
  {
    band: "bg-tertiary",
    record: "text-tertiary",
    guide: "border-tertiary/55",
    role: "頂点",
  },
  {
    band: "bg-tertiary-container",
    record: "text-secondary",
    guide: "border-outline",
    role: "重点",
  },
  {
    band: "bg-neutral",
    record: "text-secondary",
    guide: "border-outline",
    role: "基盤",
  },
];

/** エントランスの時差。間隔は global.css の --stagger-step で統一 */
const stagger = (i: number, baseMs = 0) =>
  `calc(${baseMs}ms + ${i} * var(--stagger-step))`;

export default function Pyramid({ title, subtitle, tiers }: PyramidProps) {
  const bands = pyramidBands(tiers);
  const notes = tiers.filter(
    (tier) => tier.note || (tier.items && tier.items.length > 0),
  );

  return (
    <section className="mx-auto max-w-slide bg-surface p-6 font-sans text-on-surface sm:p-12">
      <header className="mb-8">
        <h1 className="text-h1">{title}</h1>
        {subtitle && (
          <p className="mt-2 text-body-sm text-secondary">{subtitle}</p>
        )}
      </header>

      <style>{`
        [data-pyramid-map] [data-pyramid-band],
        [data-pyramid-map] [data-pyramid-record],
        [data-pyramid-map] [data-pyramid-guide] {
          transition:
            color 140ms ease,
            background-color 140ms ease,
            border-color 140ms ease,
            opacity 140ms ease;
        }

        [data-pyramid-map]:has([data-pyramid-hotspot="0"]:is(:hover, :focus))
          [data-pyramid-band="0"],
        [data-pyramid-map]:has([data-pyramid-hotspot="1"]:is(:hover, :focus))
          [data-pyramid-band="1"],
        [data-pyramid-map]:has([data-pyramid-hotspot="2"]:is(:hover, :focus))
          [data-pyramid-band="2"] {
          background-color: var(--color-on-surface);
          opacity: 1;
        }

        [data-pyramid-map]:has([data-pyramid-hotspot="0"]:is(:hover, :focus))
          [data-pyramid-record="0"],
        [data-pyramid-map]:has([data-pyramid-hotspot="1"]:is(:hover, :focus))
          [data-pyramid-record="1"],
        [data-pyramid-map]:has([data-pyramid-hotspot="2"]:is(:hover, :focus))
          [data-pyramid-record="2"] {
          color: var(--color-on-surface);
          opacity: 1;
        }

        [data-pyramid-map]:has([data-pyramid-hotspot="0"]:is(:hover, :focus))
          [data-pyramid-guide="0"],
        [data-pyramid-map]:has([data-pyramid-hotspot="1"]:is(:hover, :focus))
          [data-pyramid-guide="1"],
        [data-pyramid-map]:has([data-pyramid-hotspot="2"]:is(:hover, :focus))
          [data-pyramid-guide="2"] {
          border-color: var(--color-on-surface);
          opacity: 1;
        }

        [data-pyramid-map]:has([data-pyramid-hotspot="1"]:is(:hover, :focus))
          :is([data-pyramid-band="0"], [data-pyramid-record="0"], [data-pyramid-guide="0"]),
        [data-pyramid-map]:has([data-pyramid-hotspot="2"]:is(:hover, :focus))
          :is([data-pyramid-band="0"], [data-pyramid-record="0"], [data-pyramid-guide="0"]) {
          opacity: 0.34;
        }
      `}</style>

      {/*
       * 一つの重み付き座標系を左右で共有する「地層断面」。
       * 左の三角帯と右の階層ledgerは同じ top/height を使い、
       * mobileでも上下へ分離せず対応関係を保つ。
       */}
      <div
        data-pyramid-map="true"
        className="grid h-80 grid-cols-[4.5rem_minmax(0,1fr)] gap-x-4 sm:h-96 sm:grid-cols-[16rem_minmax(0,1fr)] sm:gap-x-8"
      >
        <div className="relative h-full">
          {tiers.map((_, i) => {
            const band = bands[i];
            const clipPath = `polygon(${50 - band.topWidthPct / 2}% 0%, ${50 + band.topWidthPct / 2}% 0%, ${50 + band.bottomWidthPct / 2}% 100%, ${50 - band.bottomWidthPct / 2}% 100%)`;
            return (
              <div key={i}>
                <button
                  type="button"
                  data-pyramid-band={i}
                  data-pyramid-hotspot={i}
                  data-top-pct={band.topWidthPct}
                  data-height-pct={band.heightPct}
                  aria-label={`${tiers[i].label}、配分${Math.round(band.heightPct)}%`}
                  className={`absolute inset-x-0 cursor-default focus-visible:outline-none ${TIER_STYLE[i].band}`}
                  style={{
                    top: `${band.topWidthPct}%`,
                    height: `${band.heightPct}%`,
                    clipPath,
                  }}
                />
                <span
                  data-pyramid-guide={i}
                  aria-hidden="true"
                  className={`pointer-events-none absolute right-0 border-t ${TIER_STYLE[i].guide}`}
                  style={{
                    top: `${band.topWidthPct}%`,
                    left: `${50 + band.topWidthPct / 2}%`,
                  }}
                />
              </div>
            );
          })}
        </div>

        <div className="relative h-full min-w-0">
          {tiers.map((tier, i) => (
            <button
              type="button"
              key={i}
              data-pyramid-record={i}
              data-pyramid-hotspot={i}
              data-top-pct={bands[i].topWidthPct}
              data-height-pct={bands[i].heightPct}
              className={`absolute inset-x-0 grid min-h-0 cursor-default grid-cols-[minmax(0,1fr)_auto] items-center gap-2 border-t pl-2 pr-1 text-left focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-on-surface sm:gap-4 sm:pl-4 sm:pr-3 ${i === tiers.length - 1 ? "border-b" : ""} ${TIER_STYLE[i].record} ${TIER_STYLE[i].guide}`}
              style={{
                top: `${bands[i].topWidthPct}%`,
                height: `${bands[i].heightPct}%`,
              }}
            >
              <span
                aria-hidden="true"
                className={`pointer-events-none absolute right-full top-0 w-4 border-t sm:w-8 ${TIER_STYLE[i].guide}`}
              />
              <span
                className="animate-rise flex min-w-0 items-baseline gap-3"
                style={{ animationDelay: stagger(i, 150) }}
              >
                <span className="hidden shrink-0 font-mono text-label opacity-60 sm:inline">
                  {TIER_STYLE[i].role}
                </span>
                <span className="min-w-0 truncate text-label sm:text-h3">
                  {tier.label}
                </span>
              </span>
              <span className="font-mono text-label tabular-nums">
                {Math.round(bands[i].heightPct)}%
              </span>
            </button>
          ))}
        </div>
      </div>

      {notes.length > 0 && (
        <details
          data-inline-disclosure="true"
          className="group mt-6 border-y border-outline bg-surface-subtle"
        >
          <summary className="flex cursor-pointer list-none items-center px-4 py-3 text-label text-secondary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tertiary">
            <span>階層の補足を確認</span>
            <span className="ml-auto font-mono">{notes.length}層</span>
            <span
              aria-hidden="true"
              className="ml-2 text-tertiary transition-transform group-open:rotate-45"
            >
              ＋
            </span>
          </summary>
          <div className="border-t border-outline px-4">
            {notes.map((tier) => {
              const index = tiers.indexOf(tier);
              return (
                <article
                  key={index}
                  data-note-item="true"
                  className="grid gap-2 border-b border-outline py-4 last:border-b-0 sm:grid-cols-[11rem_minmax(0,1fr)] sm:gap-6"
                >
                  <div>
                    <h2 className="text-label">{tier.label}</h2>
                    <p className="mt-1 font-mono text-label text-secondary">
                      {TIER_STYLE[index].role} ・ 配分{" "}
                      {Math.round(bands[index].heightPct)}%
                    </p>
                  </div>
                  <div className="min-w-0">
                    {tier.note && (
                      <p className="text-body-sm">{tier.note}</p>
                    )}
                    {tier.items && tier.items.length > 0 && (
                      <ul className="mt-2 grid gap-x-6 gap-y-1 text-body-sm sm:grid-cols-2">
                        {tier.items.map((item, itemIndex) => (
                          <li key={itemIndex} className="flex gap-2">
                            <span aria-hidden="true" className="text-tertiary">
                              —
                            </span>
                            <span>{item}</span>
                          </li>
                        ))}
                      </ul>
                    )}
                  </div>
                </article>
              );
            })}
          </div>
        </details>
      )}
    </section>
  );
}
