/* =========================================================
   page-sales-analysis.js
   業績分析頁邏輯（v3）
   依賴：jQuery / Bootstrap5 / Chart.js 3.9 / chartjs-chart-treemap / DataTables / Flatpickr
         analysis-chart-theme.js  ← 全站暖色 palette + Chart.defaults
   ========================================================= */
(function () {
  'use strict';

  // ─── Token helpers ──────────────────────────────────────
  const css = (name, fallback) => {
    const v = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
    return v || fallback;
  };
  const PALETTE = (window.EwoooCChart && window.EwoooCChart.palette) || [
    css('--momo-page-accent',  '#C77B4E'),
    css('--momo-tag-olive',    '#7A8C3F'),
    css('--momo-tag-mahogany', '#9B4D3F'),
    css('--momo-tag-honey',    '#C39A3D'),
    css('--momo-tag-walnut',   '#7A5C44'),
    css('--momo-tag-rust',     '#B85C3A'),
    css('--momo-tag-caramel',  '#D49464')
  ];
  const INK     = css('--momo-text-strong', '#2A2520');
  const MUTED   = css('--momo-text-muted',  '#6F635A');
  const BORDER  = css('--momo-border-subtle', '#E2D7C9');
  const SURFACE = css('--momo-surface',     '#FAF6EE');
  const ACCENT  = PALETTE[0];

  // mix helper – browser already supports color-mix; fallback to manual rgba
  const mix = (c, pct) => `color-mix(in srgb, ${c} ${pct}%, transparent)`;

  // ─── Loading overlay ────────────────────────────────────
  const overlay = document.getElementById('loadingOverlay');
  const showLoading = (text) => {
    if (!overlay) return;
    overlay.style.display = 'flex';
    const txt = document.getElementById('loadingText');
    if (txt && text) txt.innerHTML = `<i class="fas fa-chart-bar me-2"></i>${text}`;
  };
  const hideLoading = () => { if (overlay) overlay.style.display = 'none'; };

  // ─── Filter helpers ─────────────────────────────────────
  window.setFilter = function (key, value) {
    showLoading('正在更新篩選...');
    const url = new URL(window.location.href);
    if (value === 'all' || value === '' || value == null) url.searchParams.delete(key);
    else url.searchParams.set(key, value);
    window.location.href = url.toString();
  };

  window.handleDataRangeChange = function (sel) {
    if (!sel.value) return;
    showLoading('正在載入資料...');
    const form = sel.closest('form');
    if (form) form.submit();
  };

  window.clearDateRange = function () {
    showLoading('正在清除日期...');
    const url = new URL(window.location.href);
    url.searchParams.delete('start_date');
    url.searchParams.delete('end_date');
    window.location.href = url.toString();
  };

  window.filterDropdown = function (input) {
    const term = input.value.toLowerCase();
    const items = input.closest('.dropdown-menu').querySelectorAll('.dropdown-item');
    items.forEach((it) => {
      const txt = it.textContent.toLowerCase();
      it.style.display = txt.includes(term) ? '' : 'none';
    });
  };

  window.showTopDetail = function (kind, metric) {
    const url = new URL('/top_detail', window.location.origin);
    url.searchParams.set('kind', kind);
    url.searchParams.set('metric', metric);
    // forward existing filters
    new URLSearchParams(window.location.search).forEach((v, k) => {
      if (!url.searchParams.has(k)) url.searchParams.set(k, v);
    });
    window.open(url.toString(), '_blank');
  };

  window.exportMarketingExcel = function (campaign) {
    const url = new URL('/api/export/excel/marketing', window.location.origin);
    url.searchParams.set('campaign', campaign || 'all');
    new URLSearchParams(window.location.search).forEach((v, k) => {
      if (!url.searchParams.has(k)) url.searchParams.set(k, v);
    });
    window.location.href = url.toString();
  };

  // ─── Flatpickr (zh-tw) ─────────────────────────────────
  const initFlatpickr = () => {
    if (typeof flatpickr === 'undefined') return;
    const opts = {
      dateFormat: 'Y-m-d',
      locale: (flatpickr.l10ns && flatpickr.l10ns.zh_tw) || 'default',
      allowInput: false,
      static: true,
    };
    const start = document.getElementById('start_date');
    const end   = document.getElementById('end_date');
    if (start) flatpickr(start, { ...opts, onChange: () => end && end.dispatchEvent(new Event('focus')) });
    if (end)   flatpickr(end,   opts);
  };

  // ─── Read embedded data ────────────────────────────────
  const readData = () => {
    const node = document.getElementById('sales-data');
    if (!node) return null;
    try { return JSON.parse(node.textContent); }
    catch (e) { console.warn('[sales-analysis] data parse failed:', e); return null; }
  };

  // ─── Chart factory helpers ─────────────────────────────
  const baseGrid  = { color: mix(INK, 8), drawBorder: false };
  const baseTicks = { color: MUTED, font: { family: getComputedStyle(document.documentElement).fontFamily } };

  const horizontalBar = (canvas, labels, values, label, fmt) => {
    if (!canvas || !labels || !labels.length) return null;
    return new Chart(canvas, {
      type: 'bar',
      data: {
        labels, datasets: [{
          label, data: values,
          backgroundColor: labels.map((_, i) => PALETTE[i % PALETTE.length]),
          borderRadius: 6, borderSkipped: false,
        }]
      },
      options: {
        indexAxis: 'y', responsive: true, maintainAspectRatio: false,
        plugins: {
          legend: { display: false },
          tooltip: {
            callbacks: { label: (c) => fmt ? fmt(c.parsed.x) : c.parsed.x.toLocaleString() }
          }
        },
        scales: {
          x: { grid: baseGrid, ticks: { ...baseTicks, callback: (v) => fmt ? fmt(v) : v.toLocaleString() } },
          y: { grid: { display: false }, ticks: baseTicks }
        }
      }
    });
  };

  const doughnut = (canvas, labels, values) => {
    if (!canvas || !labels || !labels.length) return null;
    return new Chart(canvas, {
      type: 'doughnut',
      data: {
        labels, datasets: [{
          data: values,
          backgroundColor: labels.map((_, i) => PALETTE[i % PALETTE.length]),
          borderColor: SURFACE, borderWidth: 2,
        }]
      },
      options: {
        responsive: true, maintainAspectRatio: false, cutout: '55%',
        plugins: {
          legend: { position: 'right', labels: { color: INK, font: { size: 11 }, boxWidth: 12 } },
          tooltip: {
            callbacks: {
              label: (c) => {
                const total = c.dataset.data.reduce((a, b) => a + b, 0);
                const pct = total ? (c.parsed / total * 100).toFixed(1) : 0;
                return `${c.label}: ${c.parsed.toLocaleString()} (${pct}%)`;
              }
            }
          }
        }
      }
    });
  };

  const lineTrend = (canvas, labels, values, label, fmt) => {
    if (!canvas || !labels || !labels.length) return null;
    return new Chart(canvas, {
      type: 'line',
      data: {
        labels, datasets: [{
          label, data: values,
          borderColor: ACCENT,
          backgroundColor: mix(ACCENT, 14),
          tension: 0.34, fill: true, pointBackgroundColor: ACCENT,
          pointRadius: 3, pointHoverRadius: 5, borderWidth: 2.5
        }]
      },
      options: {
        responsive: true, maintainAspectRatio: false,
        plugins: {
          legend: { display: false },
          tooltip: { callbacks: { label: (c) => fmt ? fmt(c.parsed.y) : c.parsed.y.toLocaleString() } }
        },
        scales: {
          x: { grid: { display: false }, ticks: baseTicks },
          y: { grid: baseGrid, ticks: { ...baseTicks, callback: (v) => fmt ? fmt(v) : v.toLocaleString() }, beginAtZero: true }
        }
      }
    });
  };

  const verticalBar = (canvas, labels, values, label, fmt) => {
    if (!canvas || !labels || !labels.length) return null;
    return new Chart(canvas, {
      type: 'bar',
      data: {
        labels, datasets: [{
          label, data: values,
          backgroundColor: labels.map((_, i) => PALETTE[i % PALETTE.length]),
          borderRadius: 5, borderSkipped: false
        }]
      },
      options: {
        responsive: true, maintainAspectRatio: false,
        plugins: { legend: { display: false }, tooltip: { callbacks: { label: (c) => fmt ? fmt(c.parsed.y) : c.parsed.y.toLocaleString() } } },
        scales: {
          x: { grid: { display: false }, ticks: baseTicks },
          y: { grid: baseGrid, ticks: { ...baseTicks, callback: (v) => fmt ? fmt(v) : v.toLocaleString() } }
        }
      }
    });
  };

  const fmtMoney = (v) => '$' + Number(v).toLocaleString();
  const fmtNum   = (v) => Number(v).toLocaleString();

  // ─── BCG quadrant plugin (cross-hair lines) ────────────
  const bcgQuadrants = (xMid, yMid, xMax, yMax) => ({
    id: 'bcgQuadrants',
    beforeDraw(chart) {
      const { ctx, chartArea, scales } = chart;
      if (!chartArea) return;
      const x = scales.x.getPixelForValue(xMid);
      const y = scales.y.getPixelForValue(yMid);
      ctx.save();
      ctx.strokeStyle = mix(MUTED, 30);
      ctx.setLineDash([4, 4]);
      ctx.lineWidth = 1;
      ctx.beginPath();
      ctx.moveTo(x, chartArea.top); ctx.lineTo(x, chartArea.bottom);
      ctx.moveTo(chartArea.left, y); ctx.lineTo(chartArea.right, y);
      ctx.stroke();
      // quadrant labels
      ctx.fillStyle = mix(INK, 50);
      ctx.font = 'bold 11px system-ui';
      ctx.fillText('★ 明星 (Star)',     chartArea.left + 12,  chartArea.top + 18);
      ctx.fillText('? 問題兒童 (Question)', x + 12,         chartArea.top + 18);
      ctx.fillText('🐮 金牛 (Cash Cow)', chartArea.left + 12, chartArea.bottom - 8);
      ctx.fillText('🐶 瘦狗 (Dog)',     x + 12,            chartArea.bottom - 8);
      ctx.restore();
    }
  });

  // ─── Build all charts ──────────────────────────────────
  const buildCharts = (data) => {
    if (!data) return;

    // 1. Top 20 horizontal bar
    if (data.barData) {
      horizontalBar(
        document.getElementById('barChart'),
        data.barData.labels, data.barData.values,
        data.barData.label || '銷售',
        data.barData.is_money ? fmtMoney : fmtNum
      );
    }

    // 2. Category doughnut
    if (data.categoryData) {
      doughnut(document.getElementById('categoryChart'),
        data.categoryData.labels, data.categoryData.values);
    }

    // 3. Treemap
    const treemapEl = document.getElementById('treemapChart');
    if (treemapEl && data.treemapData && data.treemapData.length) {
      new Chart(treemapEl, {
        type: 'treemap',
        data: {
          datasets: [{
            tree: data.treemapData,
            key: 'value',
            groups: ['category', 'name'],
            backgroundColor: (ctx) => {
              if (ctx.type !== 'data') return 'transparent';
              const idx = ctx.dataIndex || 0;
              return PALETTE[idx % PALETTE.length];
            },
            borderColor: SURFACE, borderWidth: 1.5, spacing: 2,
            labels: {
              display: true, color: '#fff8ef',
              font: { size: 11, weight: '600' },
              formatter: (c) => c.raw && c.raw._data ? c.raw._data.name : ''
            }
          }]
        },
        options: {
          responsive: true, maintainAspectRatio: false,
          plugins: {
            legend: { display: false },
            tooltip: { callbacks: { label: (c) => c.raw && c.raw._data ? `${c.raw._data.name}: ${fmtMoney(c.raw.v)}` : '' } }
          }
        }
      });
    }

    // 4. Price distribution (vertical bar)
    if (data.priceDistData) {
      verticalBar(document.getElementById('priceDistChart'),
        data.priceDistData.labels, data.priceDistData.values,
        '業績', fmtMoney);
    }

    // 5. Scatter
    const scEl = document.getElementById('scatterChart');
    if (scEl && data.scatterData && data.scatterData.length) {
      new Chart(scEl, {
        type: 'scatter',
        data: {
          datasets: [{
            label: '商品',
            data: data.scatterData,
            backgroundColor: mix(PALETTE[0], 65),
            borderColor: PALETTE[0], borderWidth: 1, pointRadius: 4
          }]
        },
        options: {
          responsive: true, maintainAspectRatio: false,
          plugins: {
            legend: { display: false },
            tooltip: { callbacks: { label: (c) => `${c.raw.name || ''} — 價:${fmtMoney(c.parsed.x)} 量:${fmtNum(c.parsed.y)}` } }
          },
          scales: {
            x: { title: { display: true, text: '單價 ($)', color: MUTED }, grid: baseGrid, ticks: baseTicks },
            y: { title: { display: true, text: '銷量',     color: MUTED }, grid: baseGrid, ticks: baseTicks }
          }
        }
      });
    }

    // 6. BCG matrix
    const bcgEl = document.getElementById('bcgChart');
    if (bcgEl && data.bcgData && data.bcgData.points && data.bcgData.points.length) {
      const pts = data.bcgData.points;
      const xMid = data.bcgData.x_median || 0;
      const yMid = data.bcgData.y_median || 0;
      new Chart(bcgEl, {
        type: 'scatter',
        data: { datasets: [{
          label: '商品',
          data: pts,
          backgroundColor: pts.map(p => {
            if (p.x >= xMid && p.y >= yMid) return mix(PALETTE[1], 70); // Star
            if (p.x <  xMid && p.y >= yMid) return mix(PALETTE[3], 70); // Question
            if (p.x >= xMid && p.y <  yMid) return mix(PALETTE[0], 70); // Cash cow
            return mix(MUTED, 40); // Dog
          }),
          borderColor: INK, borderWidth: 0.5, pointRadius: 5
        }]},
        options: {
          responsive: true, maintainAspectRatio: false,
          plugins: {
            legend: { display: false },
            tooltip: { callbacks: { label: (c) => `${c.raw.name || ''} — 銷量:${fmtNum(c.parsed.x)} 毛利率:${c.parsed.y.toFixed(1)}%` } }
          },
          scales: {
            x: { title: { display: true, text: '銷量 (Qty)',     color: MUTED }, grid: baseGrid, ticks: baseTicks },
            y: { title: { display: true, text: '毛利率 (%)',     color: MUTED }, grid: baseGrid, ticks: baseTicks }
          }
        },
        plugins: [bcgQuadrants(xMid, yMid)]
      });
    }

    // 7. Seasonality heatmap (matrix-style via grouped bars stacked – fallback)
    const seasEl = document.getElementById('seasonalityChart');
    if (seasEl && data.seasonalityData && data.seasonalityData.matrix) {
      const cats = data.seasonalityData.categories;
      const months = data.seasonalityData.months;
      // build datasets: one per category
      const datasets = cats.map((cat, i) => ({
        label: cat,
        data: data.seasonalityData.matrix[i] || [],
        backgroundColor: PALETTE[i % PALETTE.length],
        borderRadius: 3
      }));
      new Chart(seasEl, {
        type: 'bar',
        data: { labels: months, datasets },
        options: {
          responsive: true, maintainAspectRatio: false,
          plugins: { legend: { position: 'right', labels: { color: INK, font: { size: 10 }, boxWidth: 10 } } },
          scales: {
            x: { stacked: true, grid: { display: false }, ticks: baseTicks },
            y: { stacked: true, grid: baseGrid, ticks: { ...baseTicks, callback: (v) => fmtMoney(v) } }
          }
        }
      });
    }

    // 8. Marketing — discount + coupon
    if (data.marketingData) {
      if (data.marketingData.discount) {
        horizontalBar(document.getElementById('mktDiscountChart'),
          data.marketingData.discount.labels, data.marketingData.discount.values,
          '折扣業績', fmtMoney);
      }
      if (data.marketingData.coupon) {
        horizontalBar(document.getElementById('mktCouponChart'),
          data.marketingData.coupon.labels, data.marketingData.coupon.values,
          '折價券業績', fmtMoney);
      }
    }

    // 9. Time-dimension trends
    if (data.monthlyData) {
      lineTrend(document.getElementById('monthlyChart'),
        data.monthlyData.labels, data.monthlyData.values, '月業績', fmtMoney);
    }
    if (data.weeklyData) {
      lineTrend(document.getElementById('weeklyChart'),
        data.weeklyData.labels, data.weeklyData.values, '週業績', fmtMoney);
    }
    if (data.dowData) {
      verticalBar(document.getElementById('dowChart'),
        data.dowData.labels, data.dowData.values, '日業績', fmtMoney);
    }
    if (data.hourlyData) {
      verticalBar(document.getElementById('hourlyChart'),
        data.hourlyData.labels, data.hourlyData.values, '時業績', fmtMoney);
    }

    // 10. Heatmap (DOW × Hour) — stacked bar fallback
    const hmEl = document.getElementById('heatmapChart');
    if (hmEl && data.heatmapData && data.heatmapData.matrix) {
      const dows  = data.heatmapData.dows  || ['週一','週二','週三','週四','週五','週六','週日'];
      const hours = data.heatmapData.hours || Array.from({length: 24}, (_, i) => `${i}:00`);
      const datasets = hours.map((h, i) => ({
        label: h,
        data: data.heatmapData.matrix.map(row => row[i] || 0),
        backgroundColor: mix(ACCENT, Math.max(8, (i / 24) * 80)),
        stack: 'hm'
      }));
      new Chart(hmEl, {
        type: 'bar',
        data: { labels: dows, datasets },
        options: {
          responsive: true, maintainAspectRatio: false,
          plugins: { legend: { display: false }, tooltip: { callbacks: { label: (c) => `${c.dataset.label}: ${fmtMoney(c.parsed.y)}` } } },
          scales: {
            x: { stacked: true, grid: { display: false }, ticks: baseTicks },
            y: { stacked: true, grid: baseGrid, ticks: { ...baseTicks, callback: (v) => fmtMoney(v) } }
          }
        }
      });
    }
  };

  // ─── YoY ───────────────────────────────────────────────
  let yoyChart = null;
  window.loadYoYData = function () {
    const y1 = document.getElementById('yoy-year1').value;
    const y2 = document.getElementById('yoy-year2').value;
    const m  = document.getElementById('yoy-metric').value;
    fetch(`/api/yoy?year1=${y1}&year2=${y2}&metric=${m}&${window.location.search.slice(1)}`)
      .then(r => r.json())
      .then(d => {
        document.getElementById('yoy-year1-label').textContent = `${y1}年`;
        document.getElementById('yoy-year2-label').textContent = `${y2}年`;
        document.getElementById('yoy-year1-value').textContent = fmtMoney(d.total1 || 0);
        document.getElementById('yoy-year2-value').textContent = fmtMoney(d.total2 || 0);
        const growth = d.growth || 0;
        const card = document.getElementById('yoy-growth-card');
        card.classList.toggle('is-decline', growth < 0);
        const arrow = growth >= 0 ? 'up' : 'down';
        document.getElementById('yoy-growth-value').innerHTML =
          `<i class="fas fa-arrow-${arrow}"></i> ${growth.toFixed(1)}%`;

        const ctx = document.getElementById('yoy-chart');
        if (yoyChart) yoyChart.destroy();
        yoyChart = new Chart(ctx, {
          type: 'line',
          data: {
            labels: d.labels || [],
            datasets: [
              { label: `${y1}年`, data: d.values1 || [], borderColor: MUTED,
                backgroundColor: mix(MUTED, 8), tension: 0.3, fill: false, borderWidth: 2 },
              { label: `${y2}年`, data: d.values2 || [], borderColor: ACCENT,
                backgroundColor: mix(ACCENT, 12), tension: 0.3, fill: true, borderWidth: 2.5 }
            ]
          },
          options: {
            responsive: true, maintainAspectRatio: false,
            plugins: { legend: { position: 'top', labels: { color: INK, boxWidth: 12 } } },
            scales: {
              x: { grid: { display: false }, ticks: baseTicks },
              y: { grid: baseGrid, ticks: { ...baseTicks, callback: (v) => fmtMoney(v) } }
            }
          }
        });
      })
      .catch(e => console.warn('[yoy] fetch failed', e));
  };

  // ─── DataTable ─────────────────────────────────────────
  const initDataTable = () => {
    const $tbl = window.jQuery && jQuery('#dataTable');
    if (!$tbl || !$tbl.length || !jQuery.fn.DataTable) return;
    const url = '/api/sales_table?' + window.location.search.slice(1);
    $tbl.DataTable({
      ajax: { url, dataSrc: 'data' },
      processing: true, serverSide: false,
      pageLength: 25, lengthMenu: [10, 25, 50, 100],
      order: [[$tbl.find('thead th').length - 1, 'desc']],
      language: { url: '//cdn.datatables.net/plug-ins/1.11.5/i18n/zh-HANT.json' },
      columnDefs: [{ targets: '_all', defaultContent: '—' }]
    });
  };

  // ─── Boot ──────────────────────────────────────────────
  const boot = () => {
    initFlatpickr();
    const data = readData();
    if (data) buildCharts(data);
    initDataTable();
    if (typeof window.loadYoYData === 'function' && document.getElementById('yoy-chart')) {
      try { window.loadYoYData(); } catch (e) { /* silent */ }
    }
    // tooltips
    if (window.bootstrap) {
      document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => new bootstrap.Tooltip(el));
    }
    hideLoading();
  };

  // Show loading on form submit
  document.addEventListener('submit', (e) => {
    if (e.target.matches('form[action="/sales_analysis"]')) showLoading('正在查詢...');
  });

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', boot);
  } else {
    boot();
  }
})();
