/* global React, CHANNEL_LABEL, CHANNEL_ORDER, CAR_CLASS_LABEL,
   MONTHS_SUMMARY, HEATMAP, HEATMAP_COUNTS,
   formatYen, formatYenShort, formatPct, formatCount,
   rateBand, clampBarWidth, Donut, heatColor, heatTextColor, monthShortLabel */

const { useState, useMemo, useRef, useEffect } = React;

// =========================================================================
// Header
// =========================================================================
function DashHeader({ generatedAt }) {
  const d = new Date(generatedAt);
  const pad = (n) => String(n).padStart(2, "0");
  const stamp = `${d.getFullYear()}/${pad(d.getMonth() + 1)}/${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
  return (
    <header className="dash-header">
      <div className="dash-header__title">
        <div className="dash-header__eyebrow">株式会社3A · 売掛ダッシュボード</div>
        <h1 className="dash-header__h1">
          宮古島エアレンタカー <span className="accent">— 売掛ダッシュボード</span>
        </h1>
      </div>
      <div className="dash-header__meta">
        <div className="dash-header__updated-label">Last sync</div>
        <div className="dash-header__updated-value">
          <span className="live-dot" aria-hidden="true"></span>
          {stamp}
        </div>
      </div>
    </header>
  );
}

// =========================================================================
// Section header (番号 + タイトル + hint)
// =========================================================================
function SectionHead({ num, title, hint }) {
  return (
    <div className="section__header">
      <div className="section__num">{num}</div>
      <h2 className="section__title">{title}</h2>
      {hint ? <div className="section__hint">{hint}</div> : null}
    </div>
  );
}

// =========================================================================
// Month Card (Section A の1枚)
// =========================================================================
function MonthCard({ data, selected, onClick }) {
  const band = rateBand(data.achievement_rate);
  const num = parseInt(data.month.slice(5, 7), 10);
  const barWidth = clampBarWidth(data.achievement_rate);

  return (
    <button
      type="button"
      className={`month-card month-card--${band} ${selected ? "is-selected" : ""}`}
      onClick={onClick}
      aria-label={`${num}月 詳細を見る`}
    >
      <div className="month-card__row1">
        <div className="month-card__label">{num}月</div>
        <div className={`month-card__rate month-card__rate--${band}`}>
          {formatPct(data.achievement_rate)}
        </div>
      </div>

      <div className="month-card__amount">
        <div className="month-card__total">{formatYen(data.total_amount)}</div>
        <div className="month-card__target">／ {formatYen(data.target_amount)}</div>
      </div>

      <div className="month-card__bar" aria-hidden="true">
        <div
          className={`month-card__bar-fill month-card__bar-fill--${band}`}
          style={{ width: `${barWidth}%` }}
        />
      </div>

      <div className="month-card__counts">
        <span className="conf">
          <span className="sym sym--ok">✓</span>{formatCount(data.confirmed_count)}
        </span>
        <span className="canc">
          <span className="sym sym--ng">✕</span>{formatCount(data.cancelled_count)}
        </span>
      </div>
    </button>
  );
}

// =========================================================================
// Heatmap (Section B)
// =========================================================================
function Heatmap({ months, onCellClick, selectedMonth }) {
  const [tip, setTip] = useState(null);

  // 表示する OTA は、いずれかの月で 1件でも入った channel のみ
  const visibleChannels = useMemo(() => {
    return CHANNEL_ORDER.filter(ch =>
      months.some(m => (HEATMAP_COUNTS[m]?.[ch] || 0) > 0)
    );
  }, [months]);

  // 全セルの最大金額
  const maxValue = useMemo(() => {
    let max = 0;
    for (const m of months) {
      for (const ch of visibleChannels) {
        max = Math.max(max, HEATMAP[m]?.[ch] || 0);
      }
    }
    return max || 1;
  }, [months, visibleChannels]);

  function handleMouseMove(e, m, ch) {
    const amount = HEATMAP[m]?.[ch] || 0;
    const count = HEATMAP_COUNTS[m]?.[ch] || 0;
    setTip({
      x: e.clientX,
      y: e.clientY,
      month: m,
      channel: ch,
      amount,
      count,
    });
  }

  return (
    <div className="panel">
      <div
        className="heatmap"
        style={{ gridTemplateColumns: `180px repeat(${months.length}, 1fr)` }}
      >
        <div className="heatmap__corner" />
        {months.map(m => (
          <div key={m} className="heatmap__col-header">
            {monthShortLabel(m)}
          </div>
        ))}

        {visibleChannels.map(ch => (
          <React.Fragment key={ch}>
            <div className="heatmap__row-header">{CHANNEL_LABEL[ch]}</div>
            {months.map(m => {
              const amount = HEATMAP[m]?.[ch] || 0;
              const count = HEATMAP_COUNTS[m]?.[ch] || 0;
              const bg = heatColor(amount, maxValue);
              if (amount <= 0) {
                return (
                  <div key={m + ch} className="heatmap__cell heatmap__cell--empty">
                    <span className="heatmap__cell-empty-mark">·</span>
                  </div>
                );
              }
              return (
                <div
                  key={m + ch}
                  className="heatmap__cell"
                  style={{
                    background: bg,
                    color: heatTextColor(amount, maxValue),
                    outline: selectedMonth === m ? "1px solid var(--ctp-overlay1)" : "1px solid transparent",
                  }}
                  onMouseMove={(e) => handleMouseMove(e, m, ch)}
                  onMouseLeave={() => setTip(null)}
                  onClick={() => onCellClick && onCellClick(m)}
                >
                  <div className="heatmap__cell-amount">{formatYenShort(amount)}</div>
                  <div className="heatmap__cell-count">{count}件</div>
                </div>
              );
            })}
          </React.Fragment>
        ))}
      </div>

      <div className="heatmap__legend">
        <span>金額(少)</span>
        <div className="heatmap__legend-bar">
          {[0.12, 0.28, 0.46, 0.66, 0.9].map((a, i) => (
            <div
              key={i}
              className="heatmap__legend-swatch"
              style={{ background: `rgba(137, 180, 250, ${a})` }}
            />
          ))}
        </div>
        <span>(多)</span>
      </div>

      {tip && (
        <div
          className="heatmap-tooltip"
          style={{ left: tip.x, top: tip.y }}
        >
          <div className="heatmap-tooltip__title">{monthShortLabel(tip.month)} · {tip.month}</div>
          <div className="heatmap-tooltip__channel">{CHANNEL_LABEL[tip.channel]}</div>
          <div className="heatmap-tooltip__row">
            <span>売掛金</span>
            <span className="val">{formatYen(tip.amount)}</span>
          </div>
          <div className="heatmap-tooltip__row">
            <span>予約件数</span>
            <span className="val">{formatCount(tip.count)}</span>
          </div>
        </div>
      )}
    </div>
  );
}

// =========================================================================
// Detail Pane (Section C) — donut + bars + counts
// =========================================================================
const DONUT_COLORS = [
  "#89B4FA", // blue
  "#CBA6F7", // mauve
  "#94E2D5", // teal
  "#F9E2AF", // yellow
  "#FAB387", // peach
  "#F38BA8", // red
  "#A6E3A1", // green
];

function ChannelDonut({ byChannel, total }) {
  const data = byChannel.map(b => ({ key: b.channel, value: b.amount }));
  if (total === 0 || data.length === 0) return <EmptyState />;

  const totalCount = byChannel.reduce((a, b) => a + b.count, 0);

  return (
    <>
      <div className="donut-wrap">
        <div style={{ position: "relative", width: 200, height: 200 }}>
          <Donut data={data} size={200} thickness={22} colors={DONUT_COLORS} />
          <div style={{
            position: "absolute", inset: 0,
            display: "flex", flexDirection: "column",
            alignItems: "center", justifyContent: "center", gap: 2,
            fontFamily: "var(--font-mono)",
            pointerEvents: "none",
          }}>
            <div style={{ fontSize: 10, letterSpacing: "0.14em", color: "var(--ctp-overlay1)" }}>TOTAL</div>
            <div style={{ fontSize: 17, fontWeight: 600, color: "var(--ctp-text)", fontVariantNumeric: "tabular-nums" }}>{formatYen(total)}</div>
            <div style={{ fontSize: 11, color: "var(--ctp-subtext0)" }}>{formatCount(totalCount)}</div>
          </div>
        </div>
      </div>

      <div className="legend" style={{ marginTop: 4 }}>
        {byChannel.map((b, i) => (
          <div key={b.channel} className="legend__row">
            <div className="legend__swatch" style={{ background: DONUT_COLORS[i % DONUT_COLORS.length] }} />
            <div className="legend__label">{CHANNEL_LABEL[b.channel]}</div>
            <div className="legend__amount">{formatYen(b.amount)}</div>
            <div className="legend__share">{formatPct(b.share)}</div>
          </div>
        ))}
      </div>
    </>
  );
}

function CarClassBars({ byCarClass, total }) {
  if (total === 0 || byCarClass.length === 0) return <EmptyState />;
  const max = Math.max(...byCarClass.map(b => b.amount));
  return (
    <div className="bars">
      {byCarClass.map(b => {
        const widthPct = (b.amount / max) * 100;
        return (
          <div className="bar-row" key={b.car_class}>
            <div className="bar-row__label">{CAR_CLASS_LABEL[b.car_class]}</div>
            <div className="bar-row__track">
              <div className="bar-row__fill" style={{ width: `${widthPct}%` }} />
            </div>
            <div className="bar-row__amount">{formatYen(b.amount)}</div>
            <div className="bar-row__count">{formatCount(b.count)}</div>
          </div>
        );
      })}
    </div>
  );
}

function CountsPanel({ summary }) {
  const cancelRate = summary.confirmed_count + summary.cancelled_count > 0
    ? summary.cancelled_count / (summary.confirmed_count + summary.cancelled_count)
    : 0;
  const remaining = summary.target_amount - summary.total_amount;
  const remainingState = remaining <= 0 ? "good" : (summary.achievement_rate >= 0.7 ? "warn" : "bad");

  return (
    <div className="counts">
      <div className="counts__main">
        <div className="counts__cell counts__cell--confirmed">
          <div className="counts__cell-label">CONFIRMED</div>
          <div className="counts__cell-value">
            {summary.confirmed_count.toLocaleString("ja-JP")}
            <span className="unit">件</span>
          </div>
        </div>
        <div className="counts__cell counts__cell--cancelled">
          <div className="counts__cell-label">CANCELLED</div>
          <div className="counts__cell-value">
            {summary.cancelled_count.toLocaleString("ja-JP")}
            <span className="unit">件</span>
          </div>
          <div className="counts__cancel-rate">キャンセル率 {formatPct(cancelRate, 2)}</div>
        </div>
      </div>

      <div className="counts__delta">
        <div className="counts__delta-row">
          <span className="key">目標金額</span>
          <span className="val">{formatYen(summary.target_amount)}</span>
        </div>
        <div className="counts__delta-row">
          <span className="key">現状売掛</span>
          <span className="val">{formatYen(summary.total_amount)}</span>
        </div>
        <div className="counts__delta-row">
          <span className="key">{remaining <= 0 ? "目標超過" : "目標まで"}</span>
          <span className={`val ${remainingState}`}>
            {remaining <= 0 ? "+" : ""}{formatYen(Math.abs(remaining))}
          </span>
        </div>
        <div className="counts__delta-row">
          <span className="key">達成率</span>
          <span className={`val ${rateBand(summary.achievement_rate)}`}>{formatPct(summary.achievement_rate)}</span>
        </div>
      </div>
    </div>
  );
}

function EmptyState() {
  return (
    <div className="empty">
      <div className="empty__icon">∅</div>
      <div>該当する予約はありません</div>
    </div>
  );
}

Object.assign(window, {
  DashHeader, SectionHead, MonthCard, Heatmap,
  ChannelDonut, CarClassBars, CountsPanel, EmptyState,
});
