// 依真實歷史序列，替總經卡片產生「這數字／歷史上／會影響」白話脈絡
const CONTEXT_YEARS = 20;

function fmtCtx(val, format, decimals = 2) {
  const d = decimals ?? 2;
  if (!Number.isFinite(val)) return '—';
  switch (format) {
    case 'pct':
    case 'pct_signed': return `${val.toFixed(d)}%`;
    case 'bp': return `${Math.round(val)}bp`;
    case 'num0': return Math.round(val).toLocaleString('en-US');
    case 'num1': return val.toFixed(1);
    case 'num2':
    case 'num2_signed': return val.toFixed(2);
    case 'k':
    case 'k_signed': return `${Math.round(val).toLocaleString('en-US')}K`;
    case 'trillions': return `$${val.toFixed(d)}T`;
    case 'usd': return `$${val.toFixed(d)}`;
    case 'usd0': return `$${Math.round(val).toLocaleString('en-US')}`;
    default: return val.toFixed(d);
  }
}

function percentileRank(values, current) {
  if (!values.length || !Number.isFinite(current)) return null;
  let below = 0;
  for (const v of values) if (v < current) below++;
  return Math.round((below / values.length) * 100);
}

function recentWindow(metric, years = CONTEXT_YEARS) {
  if (!metric.length) return [];
  const cutoff = new Date(metric[metric.length - 1].date);
  cutoff.setFullYear(cutoff.getFullYear() - years);
  const t = cutoff.getTime();
  const window = metric.filter(m => new Date(m.date).getTime() >= t);
  return window.length >= 24 ? window : metric;
}

function levelFromPercentile(pct, ind) {
  if (pct == null) return { label: '—', tone: 'neutral' };
  let label;
  if (pct <= 10) label = '極低';
  else if (pct <= 30) label = '偏低';
  else if (pct <= 70) label = '接近平均';
  else if (pct <= 90) label = '偏高';
  else label = '極高';

  let tone = 'neutral';
  if (ind.inverted) {
    if (pct >= 70) tone = 'bad';
    else if (pct <= 30) tone = 'good';
  } else if (!ind.excludeFromScore) {
    if (pct >= 70) tone = 'good';
    else if (pct <= 30) tone = 'bad';
  }
  return { label, tone };
}

const NUMBER_EXPLAIN = {
  treasury_10y: (v, raw) => `借錢 10 年，市場現在要求年化 ${v} 的利息。等於每借 100 萬，一年約付 ${(raw * 10000).toFixed(0)} 元利息（簡化估算）。`,
  treasury_2y: (v) => `借錢 2 年，市場要求年化 ${v} 的利息；通常反映「未來一兩年升息或降息」的預期。`,
  fed_funds: (v) => `銀行隔夜互相借錢的「官方上限」約 ${v}。越高＝全社會借錢越貴。`,
  yield_spread: (v) => `10 年殖利率減 2 年，差距是 ${v}。正值＝正常向上斜；負值＝倒掛（短借比長借還貴）。`,
  real_rate: (v) => `扣掉通膨後，長期「真實」借錢成本約 ${v}。`,
  cpi: (v) => `一籃子日常東西，平均比一年前貴 ${v}。`,
  core_cpi: (v) => `扣掉油價與食物後，物價仍比一年前貴 ${v}。`,
  pce: (v) => `Fed 最在意的通膨指標，比一年前貴 ${v}（目標約 2%）。`,
  ppi: (v) => `工廠賣出去的東西，比一年前貴 ${v}，常領先 CPI。`,
  breakeven: (v) => `債券市場預期，未來 5 年平均通膨約 ${v}。`,
  unemployment: (v) => `100 個想工作的人裡，約 ${v} 找不到工作。`,
  nfp: (v) => `非農業上月新增 ${v} 個工作（千人＝千人，200K＝20 萬人）。`,
  claims: (v) => `每週約 ${v} 人第一次申請失業救濟。`,
  wages: (v) => `平均時薪比一年前漲 ${v}。`,
  gdp: (v) => `整體經濟產出比一年前多 ${v}（已扣通膨）。`,
  recession_prob: (v) => `模型估計未來 12 個月內，美國陷入衰退的機率約 ${v}。`,
  credit_spread: (v) => `買高風險債，比公債多要求 ${v} 的額外利息補償。`,
  vix: (v) => `市場預期未來 30 天股市會上下震盪的幅度指數；現在約 ${v}（20 以下偏平靜，30 以上偏恐慌）。`,
  m2: (v, raw) => `流通中的廣義貨幣，比一年前 ${raw >= 0 ? '多' : '少'} ${Math.abs(raw).toFixed(1)}%。`,
  oil: (v) => `一桶原油 ${v}。`,
  gold: (v) => `一盎司黃金 ${v}。`,
  sp500: (v) => `美國 500 大公司的股價加總指數，現在約 ${v} 點。`,
};

const AFFECTS = {
  rates: '房貸利率、公司借錢成本、股票估值（利率高→未來利潤折現變便宜→尤其打擊高成長股）、債券價格（利率升→舊債跌價）。',
  treasury_10y: '30 年房貸參考利率、企業長期融資、科技/成長股估值、美元走勢。它是「長期借錢有多貴」的標尺。',
  treasury_2y: '短期定存、浮動利率貸款、市場對 Fed 升降息的押注。',
  yield_spread: '衰退預警、銀行放貸意願、景氣循環（倒掛常領先衰退）。',
  inflation: 'Fed 是否升息/降息、薪資購買力、必需消費品價格、債券實質報酬。',
  labor: '家庭收入、消費能力、Fed 政策（就業太熱+通膨高→難降息）。',
  growth: '企業營收展望、股市盈餘預期、原物料與週期股表現。',
  money: '企業融資難易、新興市場資金、信用危機風險、風險資產流動性。',
  sentiment: '股市波動、避險情緒、大宗商品與匯率連動。',
  credit_spread: '高收益債、小型股、槓桿高的公司——利差一擴大，這些通常先跌。',
  vix: '選擇權價格、短線波動、避險資產（黃金、公債）需求。',
  recession_prob: '整體股票部位、景氣循環股 vs 防禦股、Fed 降息預期。',
};

function numberExplain(ind, value, formatted) {
  const fn = NUMBER_EXPLAIN[ind.key];
  if (fn) return fn(formatted, value);
  switch (ind.format) {
    case 'pct':
    case 'pct_signed':
      if (ind.transform === 'yoy') return `比一年前變化 ${formatted}。`;
      return `目前讀數是 ${formatted}。`;
    case 'bp': return `目前差距是 ${formatted}（100bp＝1%）。`;
    case 'k':
    case 'k_signed': return `目前讀數約 ${formatted}。`;
    case 'trillions': return `規模約 ${formatted}。`;
    case 'usd':
    case 'usd0': return `目前價格 ${formatted}。`;
    default: return `目前讀數是 ${formatted}。`;
  }
}

function affectsExplain(ind) {
  if (AFFECTS[ind.key]) return AFFECTS[ind.key];
  if (AFFECTS[ind.group]) return AFFECTS[ind.group];
  return ind.tip?.impact || '會連動到其他總經指標與風險資產，建議搭配走勢圖一起看方向。';
}

function benchmarkNote(ind, value) {
  if (['cpi', 'core_cpi', 'pce', 'breakeven'].includes(ind.key)) {
    const diff = value - 2;
    if (Math.abs(diff) <= 0.3) return '接近 Fed 的 2% 通膨目標。';
    if (diff > 0.3) return `比 Fed 2% 目標高出約 ${diff.toFixed(1)} 個百分點，偏熱。`;
    return `比 Fed 2% 目標低約 ${Math.abs(diff).toFixed(1)} 個百分點，偏冷。`;
  }
  if (ind.key === 'recession_prob') {
    if (value >= 40) return '屬於歷史上偏高的衰退風險區間。';
    if (value >= 25) return '已進入值得留意的警戒區（常見閾值 25～30%）。';
    return '目前模型認為衰退機率不算高。';
  }
  if (ind.key === 'yield_spread' && value < 0) return '曲線倒掛中——歷史上常領先衰退約 6～18 個月。';
  if (ind.key === 'mfg' || ind.key === 'sentiment_consumer') {
    if (value > 0) return '大於 0 代表在擴張/偏樂觀區間。';
    return '小於 0 代表在收縮/偏悲觀區間。';
  }
  return '';
}

function historyExplain(ind, stats, formatted) {
  const { pct, min, max, years, level, p50 } = stats;
  if (pct == null) return '歷史資料不足，暫無法對照。';

  const range = `${fmtCtx(min, ind.format, ind.decimals)} ~ ${fmtCtx(max, ind.format, ind.decimals)}`;
  let text = `過去約 ${years} 年落在 ${range}；現在 ${formatted}，比這段時間裡約 ${pct}% 的時候都${valueWord(ind, pct)}（${level.label}）。`;

  if (p50 != null) {
    const med = fmtCtx(p50, ind.format, ind.decimals);
    const diff = ind.format === 'bp' ? (stats.current - p50) : (stats.current - p50);
    if (Math.abs(diff) > (ind.format === 'bp' ? 15 : 0.15)) {
      text += ` 中位數約 ${med}，現在${diff > 0 ? '高' : '低'}於中位數。`;
    }
  }

  const bench = benchmarkNote(ind, stats.current);
  if (bench) text += ` ${bench}`;

  return text;
}

function valueWord(ind, pct) {
  if (pct >= 50) return '高';
  return '低';
}

function cardSummary(ind, stats) {
  if (stats.pct == null) return '';
  const y = stats.years;
  const p = stats.pct;
  const lv = stats.level.label;
  if (ind.key === 'treasury_10y') {
    return p >= 70 ? `近${y}年偏高（第${p}百分位）· 長期借錢偏貴` : p <= 30 ? `近${y}年偏低（第${p}百分位）· 長期借錢偏便宜` : `近${y}年${lv}（第${p}百分位）`;
  }
  if (ind.inverted) {
    return p >= 70 ? `近${y}年偏高（第${p}百分位）· 偏警訊` : p <= 30 ? `近${y}年偏低（第${p}百分位）· 偏友善` : `近${y}年${lv}（第${p}百分位）`;
  }
  if (!ind.excludeFromScore) {
    return p >= 70 ? `近${y}年偏高（第${p}百分位）· 偏順風` : p <= 30 ? `近${y}年偏低（第${p}百分位）· 偏逆風` : `近${y}年${lv}（第${p}百分位）`;
  }
  return `近${y}年${lv}（第${p}百分位）`;
}

export function buildHistoricalContext(metric, ind, value) {
  const window = recentWindow(metric);
  const vals = window.map(m => m.val).filter(Number.isFinite);
  if (!vals.length || !Number.isFinite(value)) return null;

  const sorted = [...vals].sort((a, b) => a - b);
  const pct = percentileRank(vals, value);
  const level = levelFromPercentile(pct, ind);
  const p50 = sorted[Math.floor(sorted.length / 2)];
  const years = Math.max(1, Math.round((new Date(window[window.length - 1].date) - new Date(window[0].date)) / (365.25 * 86400000)));

  const formatted = fmtCtx(value, ind.format, ind.decimals);
  const stats = { pct, min: sorted[0], max: sorted[sorted.length - 1], p50, current: value, years, level };

  return {
    percentile: pct,
    level: level.label,
    tone: level.tone,
    rangeMin: sorted[0],
    rangeMax: sorted[sorted.length - 1],
    rangeYears: years,
    summary: cardSummary(ind, stats),
    number: numberExplain(ind, value, formatted),
    history: historyExplain(ind, stats, formatted),
    affects: affectsExplain(ind),
  };
}
