/**
 * EwoooC Chart Theme v3.0 — Production
 * ─────────────────────────────────────────────────────────────
 * 變更重點（相對 v2.x）：
 *   1. 動態讀取當前頁面 [data-page-group]，圖表自動換群組調色盤
 *   2. 移除 dotMatrixPlugin（chart 底圖點陣）— 干擾資料判讀
 *   3. 移除 alpha fill 預設（散布圖、長條圖背景透明度過低看不清）
 *   4. 字體統一走 var(--momo-font-mono) for tick / value
 *   5. 顏色映射保留 — 第三方 chart config 用冷色時自動轉暖色
 *
 * 群組調色盤：
 *   monitor    → caramel  primary，apricot/honey/olive/clay/greige
 *   analytics  → honey    primary，caramel/olive/apricot/clay/greige
 *   ops        → clay     primary，terra/honey/caramel/apricot/greige
 *   ai         → saffron  primary，honey/caramel/olive/apricot/greige
 *   system     → terra    primary，clay/olive/greige/honey/apricot
 */
(function () {
  let chartJsLoader = null;
  const CHART_LOAD_TIMEOUT_MS = 4500;
  const CHART_CDN_URLS = [
    'https://cdn.jsdelivr.net/npm/chart.js@4.4.6/dist/chart.umd.min.js',
    'https://unpkg.com/chart.js@4.4.6/dist/chart.umd.js',
    'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.6/chart.umd.min.js'
  ];
  const root = document.documentElement;
  const css = (name, fallback) =>
    getComputedStyle(root).getPropertyValue(name).trim() || fallback;

  function readPalette() {
    // 優先讀群組變數，沒有就 fallback 到 momo-warm-*
    const shell = document.querySelector('.momo-app[data-page-group]');
    const scope = shell || document.documentElement;
    const get = (n, fb) =>
      getComputedStyle(scope).getPropertyValue(n).trim() || fb;

    return [
      get('--momo-page-chart-1', '#c96442'),
      get('--momo-page-chart-2', '#e7b98f'),
      get('--momo-page-chart-3', '#c89043'),
      get('--momo-page-chart-4', '#8a7340'),
      get('--momo-page-chart-5', '#b86f52'),
      get('--momo-page-chart-6', '#b8aea2'),
      '#a85d3d',
      '#6f6256',
      '#d8c1aa',
      '#edd6cc'
    ];
  }

  const theme = {
    font: css('--momo-font-family', '"Inter", "Noto Sans TC", sans-serif'),
    mono: css('--momo-font-mono', '"JetBrains Mono", monospace'),
    ink: css('--momo-text-primary', '#2a2520'),
    muted: css('--momo-text-secondary', '#6b6155'),
    faint: 'rgba(42, 37, 32, 0.10)',
    paper: css('--momo-bg-paper', '#f5efe2'),
    elevated: css('--momo-bg-elevated', '#fdfaf2')
  };

  const isCompact = () =>
    window.matchMedia && window.matchMedia('(max-width: 768px)').matches;
  const clamp = (v, mn, mx) => Math.max(mn, Math.min(mx, v));

  // 冷色 → 暖色映射（保留 v2 行為）
  const coldColorMap = {
    '#6366f1': '#c96442',
    '#3b82f6': '#4a6b85',
    '#8b5cf6': '#8f4530',
    '#10b981': '#5a7a3f',
    '#14b8a6': '#5a7a3f',
    '#0ea5e9': '#4a6b85',
    '#0284c7': '#4a6b85',
    '#94a3b8': '#8f857a',
    '#d1d5db': '#c7bcae',
    '#ec4899': '#b5342f',
    '#ef4444': '#b5342f',
    '#f59e0b': '#c89043'
  };

  const alpha = (hex, amount) => {
    if (!hex || !hex.startsWith('#') || hex.length < 7) return hex;
    const n = parseInt(hex.slice(1, 7), 16);
    return `rgba(${(n >> 16) & 255}, ${(n >> 8) & 255}, ${n & 255}, ${amount})`;
  };

  function mapColor(color, fb) {
    if (typeof color !== 'string') return color || fb;
    const k = color.trim().toLowerCase();
    return coldColorMap[k] || color;
  }

  function formatNumber(v) {
    if (typeof v !== 'number' || !Number.isFinite(v)) return v;
    return Math.abs(v) >= 10000
      ? `${Math.round(v / 10000).toLocaleString()}萬`
      : v.toLocaleString();
  }

  function formatMetric(v, label = '') {
    if (typeof v !== 'number' || !Number.isFinite(v)) return v;
    const name = String(label || '').toLowerCase();
    if (name.includes('%') || name.includes('率') || name.includes('yoy') || name.includes('mom')) {
      return `${v >= 0 ? '+' : ''}${v.toFixed(1)}%`;
    }
    if (name.includes('$') || name.includes('金額') || name.includes('營收') || name.includes('業績') || name.includes('毛利') || name.includes('客單') || name.includes('單價')) {
      return `$${Math.round(v).toLocaleString()}`;
    }
    return formatNumber(v);
  }

  function tuneDataset(ds, idx, type) {
    if (!ds || typeof ds !== 'object') return;
    const palette = readPalette();
    const color = palette[idx % palette.length];
    const t = ds.type || type;

    if (t === 'doughnut' || t === 'pie' || t === 'polarArea') {
      ds.backgroundColor = palette.map(c => alpha(c, 0.85));
      ds.borderColor = theme.elevated;
      ds.borderWidth = 2;
      return;
    }

    if (typeof ds.backgroundColor !== 'function') {
      ds.backgroundColor =
        t === 'line' ? alpha(color, ds.fill ? 0.18 : 0.0) : alpha(color, 0.78);
    }
    if (typeof ds.borderColor !== 'function') ds.borderColor = color;

    ds.borderWidth = ds.borderWidth || (t === 'line' ? 2 : 1);
    ds.borderRadius = ds.borderRadius ?? (t === 'bar' ? 3 : undefined);
    ds.borderSkipped = ds.borderSkipped ?? (t === 'bar' ? false : undefined);
    ds.pointRadius = ds.pointRadius ?? (t === 'line' ? 2 : undefined);
    ds.pointHoverRadius = ds.pointHoverRadius ?? (t === 'line' ? 4 : undefined);
    ds.pointBackgroundColor = ds.pointBackgroundColor || color;
    ds.pointBorderColor = ds.pointBorderColor || theme.elevated;
    ds.tension = ds.tension ?? (t === 'line' ? 0.32 : undefined);
    ds.hoverBorderWidth = ds.hoverBorderWidth || (t === 'line' ? 3 : 1);
    ds.maxBarThickness = ds.maxBarThickness || (t === 'bar' ? 34 : undefined);
  }

  function tuneChartConfig(config) {
    if (!config || typeof config !== 'object') return config;
    const type = config.type || 'bar';
    const datasets =
      config.data && Array.isArray(config.data.datasets)
        ? config.data.datasets
        : [];
    datasets.forEach((d, i) => tuneDataset(d, i, type));

    config.options = config.options || {};
    config.options.responsive = config.options.responsive !== false;
    config.options.maintainAspectRatio = false;

    const plugins = (config.options.plugins = config.options.plugins || {});
    plugins.legend = {
      ...(plugins.legend || {}),
      position: (plugins.legend || {}).position || (isCompact() ? 'bottom' : 'top'),
      align: (plugins.legend || {}).align || 'start',
      labels: {
        color: theme.muted,
        boxWidth: 10,
        boxHeight: 10,
        borderRadius: 2,
        padding: 12,
        font: { family: theme.mono, size: 11, weight: '600' },
        ...((plugins.legend || {}).labels || {})
      }
    };
    plugins.tooltip = {
      ...(plugins.tooltip || {}),
      backgroundColor: theme.elevated,
      titleColor: theme.ink,
      bodyColor: theme.ink,
      borderColor: theme.faint,
      borderWidth: 1,
      cornerRadius: 4,
      titleFont: { family: theme.mono, weight: '700', size: 12 },
      bodyFont: { family: theme.font, weight: '500', size: 12 },
      padding: 10,
      callbacks: {
        label: ctx => {
          const lbl =
            ctx.dataset && ctx.dataset.label ? `${ctx.dataset.label}: ` : '';
          const v =
            typeof ctx.parsed === 'object'
              ? ctx.parsed.y ?? ctx.parsed.x ?? ctx.raw
              : ctx.parsed;
          return `${lbl}${formatMetric(v, ctx.dataset && ctx.dataset.label)}`;
        },
        ...((plugins.tooltip || {}).callbacks || {})
      }
    };

    const scales = config.options.scales || {};
    Object.keys(scales).forEach(k => {
      scales[k] = {
        border: { color: theme.faint, ...(scales[k].border || {}) },
        grid: {
          color: theme.faint,
          tickColor: 'transparent',
          drawBorder: false,
          ...(scales[k].grid || {})
        },
        ticks: {
          color: theme.muted,
          maxRotation: isCompact() ? 0 : 30,
          autoSkip: isCompact(),
          maxTicksLimit: isCompact() ? 5 : 8,
          font: {
            family: theme.mono,
            size: isCompact() ? 10 : 11,
            weight: '500'
          },
          callback: v => formatNumber(v),
          ...(scales[k].ticks || {})
        },
        ...scales[k]
      };
    });
    config.options.scales = scales;
    return config;
  }

  function installChartJsTheme() {
    if (!window.Chart || window.Chart.__ewooocThemed) return;
    const Native = window.Chart;
    Native.defaults.font.family = theme.font;
    Native.defaults.font.size = 12;
    Native.defaults.color = theme.muted;

    function ThemedChart(item, config) {
      return new Native(item, tuneChartConfig(config));
    }
    for (const k of Reflect.ownKeys(Native)) {
      if (['length', 'name', 'prototype'].includes(k)) continue;
      try {
        Object.defineProperty(
          ThemedChart,
          k,
          Object.getOwnPropertyDescriptor(Native, k)
        );
      } catch (e) {}
    }
    ThemedChart.prototype = Native.prototype;
    Object.setPrototypeOf(ThemedChart, Native);
    ThemedChart.__ewooocThemed = true;
    window.Chart = ThemedChart;
  }

  function loadChartJs() {
    if (window.Chart) {
      installChartJsTheme();
      return Promise.resolve(window.Chart);
    }
    if (chartJsLoader) return chartJsLoader;

    const loadFromCdn = index => new Promise((resolve, reject) => {
      const url = CHART_CDN_URLS[index];
      if (!url) {
        reject(new Error('Chart.js 載入失敗'));
        return;
      }

      if (window.Chart) {
        installChartJsTheme();
        resolve(window.Chart);
        return;
      }

      let settled = false;
      const finish = callback => value => {
        if (settled) return;
        settled = true;
        window.clearTimeout(timer);
        callback(value);
      };
      const fail = finish(error => {
        script.remove();
        if (index + 1 < CHART_CDN_URLS.length) {
          loadFromCdn(index + 1).then(resolve).catch(reject);
        } else {
          reject(error);
        }
      });
      const succeed = finish(() => {
        installChartJsTheme();
        resolve(window.Chart);
      });
      const timer = window.setTimeout(
        () => fail(new Error(`Chart.js 載入逾時: ${url}`)),
        CHART_LOAD_TIMEOUT_MS
      );

      const script = document.createElement('script');
      script.src = url;
      script.async = true;
      script.dataset.ewooocChartjs = String(index + 1);
      script.onload = succeed;
      script.onerror = () => fail(new Error(`Chart.js 載入失敗: ${url}`));
      document.head.appendChild(script);
    });
    chartJsLoader = loadFromCdn(0);
    return chartJsLoader;
  }

  // ECharts 走精簡版（v2 完整 mergeAxis/tuneSeries 保留邏輯但用群組色）
  function installEchartsTheme() {
    if (!window.echarts || window.echarts.__ewooocThemed) return;
    const ec = window.echarts;
    const nativeInit = ec.init.bind(ec);
    const tuneAxis = axis => {
      if (!axis || typeof axis !== 'object') return axis;
      return {
        axisLine: { lineStyle: { color: theme.faint }, ...(axis.axisLine || {}) },
        axisTick: { lineStyle: { color: theme.faint }, ...(axis.axisTick || {}) },
        axisLabel: {
          color: theme.muted,
          fontFamily: theme.mono,
          fontSize: isCompact() ? 10 : 11,
          ...(axis.axisLabel || {})
        },
        splitLine: {
          lineStyle: { color: theme.faint, type: 'dashed' },
          ...(axis.splitLine || {})
        },
        ...axis
      };
    };
    const tuneAxisList = axes => {
      if (Array.isArray(axes)) return axes.map(tuneAxis);
      return tuneAxis(axes);
    };
    ec.init = function (dom, themeName, opts) {
      const chart = nativeInit(dom, themeName || null, opts);
      const setOpt = chart.setOption.bind(chart);
      chart.setOption = function (opt, notMerge, lazy) {
        const palette = readPalette();
        const tuned = {
          ...opt,
          color: palette,
          backgroundColor: 'transparent',
          textStyle: { color: theme.ink, fontFamily: theme.font, ...(opt.textStyle || {}) },
          tooltip: {
            trigger: 'axis',
            confine: true,
            backgroundColor: theme.elevated,
            borderColor: theme.faint,
            borderWidth: 1,
            textStyle: { color: theme.ink, fontFamily: theme.font },
            axisPointer: { type: 'cross', label: { backgroundColor: '#6f6256' } },
            ...(opt.tooltip || {})
          },
          legend: {
            bottom: 0,
            type: 'scroll',
            textStyle: { color: theme.muted, fontFamily: theme.mono, fontSize: 11 },
            ...(opt.legend || {})
          },
          grid: {
            containLabel: true,
            left: isCompact() ? 12 : 28,
            right: isCompact() ? 12 : 24,
            top: isCompact() ? 24 : 36,
            bottom: isCompact() ? 34 : 40,
            ...(opt.grid || {})
          },
          xAxis: tuneAxisList(opt.xAxis),
          yAxis: tuneAxisList(opt.yAxis)
        };
        return setOpt(tuned, notMerge, lazy);
      };
      if (window.ResizeObserver && dom) {
        new ResizeObserver(() =>
          requestAnimationFrame(() => chart.resize())
        ).observe(dom);
      }
      return chart;
    };
    ec.__ewooocThemed = true;
  }

  window.EwoooCChartTheme = {
    readPalette,
    theme,
    tuneChartConfig,
    loadChartJs,
    installChartJsTheme,
    installEchartsTheme
  };
  installChartJsTheme();
  installEchartsTheme();
})();
