// panels.jsx — Score panel, factors, forecast, hourly chart, clothing, tips sections

// Color helper based on score (0-100)
function scoreColor(score, vars = {}) {
  // returns CSS color string from theme vars
  if (score >= 70) return "var(--good)";
  if (score >= 45) return "var(--warn)";
  return "var(--bad)";
}

function pct(score) {
  return `${Math.max(0, Math.min(100, score))}%`;
}

// ───── Factor row
const FactorRow = ({ factor, t }) => {
  const label = t[factor.key] || factor.key;
  const valueText = typeof factor.format === "function"
    ? factor.format(factor.value, t)
    : `${factor.value}`;
  const c = scoreColor(factor.score);
  return (
    <div className="factor-row">
      <span className="f-label">{label}</span>
      <span className="factor-bar">
        <span style={{ "--w": pct(factor.score), "--c": c }}></span>
      </span>
      <span className="f-value">{valueText}</span>
    </div>
  );
};

// ───── Score panel (one for Day, one for Night)
const ScorePanel = ({ kind, scoreData, sunrise, sunset, target, isToday, t, lang, isMobile }) => {
  const { score, factors } = scoreData;
  const isNight = kind === "night";
  const verdict = t[W.verdictKey(score)];
  const stateK = W.stateKey(score);
  const stateLabel = t[stateK];

  const sunStr = (() => {
    if (isNight) {
      return `${t.sunset} ${fmtTime(sunset, lang)} → ${t.sunrise}`;
    }
    return `${t.sunrise} ${fmtTime(sunrise, lang)} → ${t.sunset} ${fmtTime(sunset, lang)}`;
  })();

  const periodLabel = isToday
    ? `${isNight ? t.night : t.day} · ${t.score}`
    : `${fmtDate(target, lang)} · ${isNight ? t.night : t.day}`;

  return (
    <div className="score-panel">
      <Gauge
        score={score}
        label={isNight ? t.night : t.day}
        subLabel=""
        size={isMobile ? 240 : 300}
        isNight={isNight}
      />
      <div className="label-block">
        <span className="period">{periodLabel}</span>
        <h2 className="verdict">{verdict}</h2>
        <span className="state-pill">{stateLabel} · {Math.round(score)}{t.out_of}</span>
        <span className="sun-time">{sunStr}</span>
        <div className="factors">
          {factors.map((f, i) => <FactorRow key={i} factor={f} t={t} />)}
        </div>
      </div>
    </div>
  );
};

function fmtTime(d, lang) {
  if (!d) return "—";
  const hh = String(d.getHours()).padStart(2, "0");
  const mm = String(d.getMinutes()).padStart(2, "0");
  return `${hh}:${mm}`;
}

function fmtDate(d, lang) {
  const opts = { month: "short", day: "numeric", weekday: "short" };
  const locale = lang === "zh" ? "zh-CN" : lang === "ja" ? "ja-JP" : "en-US";
  return d.toLocaleDateString(locale, opts);
}

// ───── 7-day forecast strip
const ForecastSection = ({ days, t, lang, selectedDate, onSelect }) => {
  const today = new Date(); today.setHours(0,0,0,0);
  const isSameDay = (a, b) => a && b &&
    a.getFullYear() === b.getFullYear() &&
    a.getMonth() === b.getMonth() &&
    a.getDate() === b.getDate();
  return (
    <div className="section">
      <h3 className="section-title">{t.forecast_title}</h3>
      <div className="forecast-grid">
        {days.map((d, i) => {
          const isToday = d.date.toDateString() === today.toDateString();
          const isSelected = isSameDay(d.date, selectedDate) ||
            (selectedDate == null && isToday);
          const c = scoreColor(d.score);
          return (
            <button
              key={i}
              type="button"
              className={`fc-day${isToday ? " today" : ""}${isSelected ? " selected" : ""}`}
              onClick={() => onSelect && onSelect(isToday ? null : new Date(d.date))}
              aria-pressed={isSelected}
            >
              <div className="fc-date">
                <span>{isToday ? t.today : fmtDate(d.date, lang)}</span>
              </div>
              <div className="fc-score" style={{ color: c }}>{Math.round(d.score)}</div>
              <div className="fc-temp">{Math.round(d.tMin)}° / {Math.round(d.tMax)}°</div>
              <div className="fc-rain">☂ {Math.round(d.pop || 0)}% · {(d.precip || 0).toFixed(1)}mm</div>
              <div className="fc-score-bar"><span style={{ "--w": pct(d.score), "--c": c }}></span></div>
            </button>
          );
        })}
      </div>
    </div>
  );
};

// ───── 24-hour stacked chart
const HourlyChart = ({ data, scoring, t, lang }) => {
  // Take 24 hours from selected start
  const start = scoring.hourlyStartIdx != null ? scoring.hourlyStartIdx : scoring.nowIdx;
  const slice = [];
  for (let i = start; i < Math.min(start + 24, data.hourly.time.length); i++) {
    slice.push(i);
  }

  const w = Math.max(640, slice.length * 28);
  const h = 220;
  const padL = 40, padR = 40, padT = 24, padB = 40;
  const chartW = w - padL - padR;
  const chartH = h - padT - padB;

  const tempArr = slice.map(i => data.hourly.temperature_2m[i]);
  const popArr = slice.map(i => data.hourly.precipitation_probability[i] || 0);
  const windArr = slice.map(i => (data.hourly.wind_speed_10m[i] || 0) / 3.6); // m/s

  const tMin = Math.min(...tempArr) - 1;
  const tMax = Math.max(...tempArr) + 1;
  const wMaxScale = Math.max(8, Math.ceil(Math.max(...windArr)) + 1);
  const xs = (idx) => padL + (idx / Math.max(1, slice.length - 1)) * chartW;
  const ysT = (v) => padT + chartH - ((v - tMin) / (tMax - tMin)) * chartH;
  const ysW = (v) => padT + chartH - (v / wMaxScale) * chartH;

  // Paths
  const tempPath = tempArr.map((v, i) => `${i === 0 ? "M" : "L"} ${xs(i)} ${ysT(v)}`).join(" ");
  const windPath = windArr.map((v, i) => `${i === 0 ? "M" : "L"} ${xs(i)} ${ysW(v)}`).join(" ");

  return (
    <div className="section">
      <h3 className="section-title">{t.hourly_title}</h3>
      <div className="chart-legend">
        <span className="lg-item"><span className="lg-swatch lg-temp"></span>{t.f_temp} (°C)</span>
        <span className="lg-item"><span className="lg-swatch lg-wind"></span>{t.f_wind} (m/s)</span>
        <span className="lg-item"><span className="lg-swatch lg-pop"></span>{t.f_pop} (%)</span>
      </div>
      <div className="chart-wrap">
        <svg viewBox={`0 0 ${w} ${h}`} width="100%" preserveAspectRatio="xMidYMid meet">
          {/* Grid */}
          {[0, 25, 50, 75, 100].map(p => (
            <line key={p} x1={padL} y1={padT + (chartH * (1 - p/100))} x2={w - padR} y2={padT + (chartH * (1 - p/100))} stroke="var(--line)" strokeWidth="1" strokeDasharray="2 3"/>
          ))}

          {/* Rain prob bars (uses chartH = 100% scale) */}
          {popArr.map((v, i) => {
            const x = xs(i);
            const barH = (v / 100) * chartH;
            return <rect key={i} x={x - 8} y={padT + chartH - barH} width="16" height={barH} fill="var(--accent)" opacity="0.18" />;
          })}

          {/* Wind line */}
          <path d={windPath} fill="none" stroke="var(--good)" strokeWidth="1.5" strokeDasharray="4 3" opacity="0.85" />
          {windArr.map((v, i) => {
            if (i % 3 !== 0) return null;
            return <circle key={i} cx={xs(i)} cy={ysW(v)} r="2" fill="var(--good)" />;
          })}

          {/* Temp line */}
          <path d={tempPath} fill="none" stroke="var(--accent)" strokeWidth="2" />
          {tempArr.map((v, i) => (
            <circle key={i} cx={xs(i)} cy={ysT(v)} r="2.5" fill="var(--accent)" />
          ))}

          {/* X labels (every 3h) */}
          {slice.map((srcIdx, i) => {
            if (i % 3 !== 0) return null;
            const d = new Date(data.hourly.time[srcIdx]);
            const lbl = `${String(d.getHours()).padStart(2, "0")}`;
            return (
              <text key={i} x={xs(i)} y={h - 18} textAnchor="middle" fill="var(--fg-mute)" fontSize="10" fontFamily="var(--font-mono)">{lbl}</text>
            );
          })}

          {/* Temp values above line (every 3h) */}
          {tempArr.map((v, i) => {
            if (i % 3 !== 0) return null;
            return (
              <text key={i} x={xs(i)} y={ysT(v) - 8} textAnchor="middle" fill="var(--accent)" fontSize="10" fontFamily="var(--font-mono)" fontWeight="600">{Math.round(v)}°</text>
            );
          })}

          {/* Wind values below line (every 6h, to avoid clutter) */}
          {windArr.map((v, i) => {
            if (i % 6 !== 0 || v < 1) return null;
            return (
              <text key={i} x={xs(i)} y={ysW(v) + 14} textAnchor="middle" fill="var(--good)" fontSize="9" fontFamily="var(--font-mono)">{v.toFixed(1)}</text>
            );
          })}

          {/* Pop% values on bars where significant */}
          {popArr.map((v, i) => {
            if (v < 20 || i % 3 !== 0) return null;
            const barH = (v / 100) * chartH;
            return (
              <text key={i} x={xs(i)} y={padT + chartH - barH - 4} textAnchor="middle" fill="var(--fg-mute)" fontSize="9" fontFamily="var(--font-mono)">{Math.round(v)}%</text>
            );
          })}

          {/* Y-axis labels: temp on left, pop on right */}
          <text x={6} y={padT + 4} fill="var(--accent)" fontSize="9" fontFamily="var(--font-mono)">{Math.round(tMax)}°</text>
          <text x={6} y={padT + chartH + 4} fill="var(--accent)" fontSize="9" fontFamily="var(--font-mono)">{Math.round(tMin)}°</text>
          <text x={w - 6} y={padT + 4} textAnchor="end" fill="var(--fg-mute)" fontSize="9" fontFamily="var(--font-mono)">100%</text>
          <text x={w - 6} y={padT + chartH + 4} textAnchor="end" fill="var(--fg-mute)" fontSize="9" fontFamily="var(--font-mono)">0%</text>
        </svg>
      </div>
    </div>
  );
};

// ───── Clothing section
const ClothingSection = ({ items, t }) => {
  return (
    <div className="section">
      <h3 className="section-title">{t.clothing_title}</h3>
      <div className="gear-grid">
        {items.map((it, i) => (
          <div key={i} className="gear-card">
            <div className="gear-icon"><REC.GearIcon kind={it.icon} /></div>
            <span className="gear-kind">{it.kind}</span>
            <span className="gear-name">{it.name}</span>
          </div>
        ))}
      </div>
    </div>
  );
};

// ───── Tips section
const TipsSection = ({ tips, t }) => {
  if (!tips.length) return null;
  return (
    <div className="section">
      <h3 className="section-title">{t.tips_title}</h3>
      <div className="tip-list">
        {tips.map((tip, i) => (
          <div key={i} className="tip">
            <span className={`tip-dot ${tip.level}`}></span>
            <span>{tip.text}</span>
          </div>
        ))}
      </div>
    </div>
  );
};

// ───── Meta info row (now / road / moon / source)
const MetaRow = ({ scoring, t, lang, source }) => {
  const moon = W.moonPhase(scoring.target || new Date());
  const roadText = scoring.roadStatus
    ? (scoring.roadStatus === "dry" ? t.road_dry : scoring.roadStatus === "damp" ? t.road_damp : t.road_wet)
    : "—";
  return (
    <div className="meta-row">
      {scoring.isToday && <span><strong>{t.now}</strong> {fmtTime(scoring.now, lang)}</span>}
      {!scoring.isToday && <span><strong>{fmtDate(scoring.target, lang)}</strong></span>}
      {scoring.roadStatus && <span><strong>{t.f_road}:</strong> {roadText}</span>}
      <span><strong>{t.moonphase}:</strong> {t[moon.key]} ({Math.round(moon.illum)}%)</span>
      <span><strong>{t.f_daylight}:</strong> {scoring.daylightHours.toFixed(1)}h</span>
      <span>{source}</span>
    </div>
  );
};

Object.assign(window, {
  ScorePanel,
  ForecastSection,
  HourlyChart,
  ClothingSection,
  TipsSection,
  MetaRow,
  fmtTime,
  fmtDate,
});
