// Gráfico avançado: comparativos de períodos, tipos (linhas/barras/pizza) e filtros
// initAdvancedChart(state, { fmtBRL })

export function initAdvancedChart(state, { fmtBRL }){
  const el = {
    type: document.getElementById('gaType'),
    preset: document.getElementById('gaPreset'),
    start: document.getElementById('gaStart'),
    end: document.getElementById('gaEnd'),
    product: document.getElementById('gaProduct'),
    region: document.getElementById('gaRegion'),
    seller: document.getElementById('gaSeller'),
    apply: document.getElementById('gaApply'),
    canvas: document.getElementById('gaCanvas'),
    status: document.getElementById('gaStatus'),
  };

  if (state?.filters?.start && el.start) el.start.value = state.filters.start;
  if (state?.filters?.end && el.end) el.end.value = state.filters.end;

  let abort = null;

  function pad(n){ return n<10 ? '0'+n : ''+n; }
  function fmtDate(d){ return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`; }

  function presetToRanges(){
    const today = new Date();
    const y = today.getFullYear(), m = today.getMonth();
    const firstDayOfMonth = new Date(y, m, 1);
    const firstPrevMonth = new Date(y, m-1, 1);
    const firstCurQuarter = new Date(y, Math.floor(m/3)*3, 1);
    const firstPrevQuarter = new Date(y, Math.floor(m/3)*3 - 3, 1);
    const firstYear = new Date(y, 0, 1);
    const firstPrevYear = new Date(y-1, 0, 1);
    if (el.preset.value === 'month'){
      return { aStart: firstDayOfMonth, aEnd: today, bStart: firstPrevMonth, bEnd: new Date(y, m, 0) };
    }
    if (el.preset.value === 'quarter'){
      return { aStart: firstCurQuarter, aEnd: today, bStart: firstPrevQuarter, bEnd: new Date(firstCurQuarter.getFullYear(), firstCurQuarter.getMonth(), 0) };
    }
    if (el.preset.value === 'year'){
      return { aStart: firstYear, aEnd: today, bStart: firstPrevYear, bEnd: new Date(y-1, 11, 31) };
    }
    // custom
    const parseBR = (s)=>{
      if (!s) return null;
      try {
        if (typeof window !== 'undefined' && typeof window.parseDateBR === 'function') {
          const d = window.parseDateBR(s); if (d) return d;
        }
      } catch(_){}
      const d = new Date(s); return isNaN(d) ? null : d;
    };
    const aStart = el.start?.value ? (parseBR(el.start.value) || new Date(y, m, 1)) : new Date(y, m, 1);
    const aEnd = el.end?.value ? (parseBR(el.end.value) || today) : today;
    const delta = Math.max(1, Math.floor((aEnd - aStart)/(1000*60*60*24)));
    const bEnd = new Date(aStart); bEnd.setDate(bEnd.getDate()-1);
    const bStart = new Date(bEnd); bStart.setDate(bEnd.getDate()-delta);
    return { aStart, aEnd, bStart, bEnd };
  }

  function setStatus(msg){
    if (!el.status) return;
    el.status.textContent = String(msg||'');
    el.status.style.display = msg ? 'block' : 'none';
  }

  async function fetchJson(url, { signal }){
    try {
      // Preferir helper global apiRequest que injeta Authorization e x-tenant-id automaticamente
      const useApiReq = (typeof window !== 'undefined' && typeof window.apiRequest === 'function');
      const res = useApiReq
        ? await window.apiRequest(url, { signal, credentials: 'include', cache: 'no-store' })
        : await fetch(url, { credentials: 'include', signal, cache: 'no-store' });
      if (!res) return { error: 'network' };
      if (res.status === 401) { return { error: 401 }; }
      if (!res.ok) { return { error: res.status }; }
      return await res.json();
    } catch(e){
      return { error: 'network' };
    }
  }

  async function populateFilters(){
    // Tenta endpoint agregado; fallback para listas vazias
    let data = { products: [], regions: [], sellers: [] };
    try {
      const useApiReq = (typeof window !== 'undefined' && typeof window.apiRequest === 'function');
      const res = useApiReq
        ? await window.apiRequest('/api/sales/filters', { credentials: 'include', cache: 'no-store' })
        : await fetch('/api/sales/filters', { credentials: 'include', cache: 'no-store' });
      if (res && res.ok) { data = await res.json(); }
    } catch(_) {}
    const applyOptions = (select, items, labelKey = 'name', valueKey = 'id', firstLabel = 'Todos') => {
      if (!select) return;
      const cur = select.value;
      const opts = [ { [labelKey]: firstLabel, [valueKey]: '' }, ...(Array.isArray(items) ? items : []) ];
      select.innerHTML = opts.map(it => `<option value="${String(it[valueKey] ?? '')}">${String(it[labelKey] ?? it[valueKey] ?? '')}</option>`).join('');
      // restaura valor se possível
      if (cur && Array.from(select.options).some(o => o.value === cur)) select.value = cur;
    };
    applyOptions(el.product, data.products || data.produtos || data.items_products, 'name', 'id', 'Todos os produtos');
    applyOptions(el.region, data.regions || data.regioes || data.items_regions, 'name', 'id', 'Todas as regiões');
    applyOptions(el.seller, data.sellers || data.vendedores || data.items_sellers, 'name', 'id', 'Todos os vendedores');
  }

  function groupDaily(items){
    const m = new Map();
    for (const it of (items||[])){
      const day = (it.date || it.day || '').slice(0,10);
      const v = it.amount_cents ? it.amount_cents/100 : (it.total || it.amount || 0);
      m.set(day, (m.get(day)||0) + (v||0));
    }
    const arr = Array.from(m.entries()).sort((a,b)=>a[0].localeCompare(b[0]));
    return { labels: arr.map(x=>x[0]), values: arr.map(x=>x[1]) };
  }

  function draw(canvas, type, seriesA, seriesB){
    const ctx = canvas.getContext('2d');
    const W = canvas.width, H = canvas.height;
    ctx.clearRect(0,0,W,H);
    const pad = 40;
    const hasA = Array.isArray(seriesA.values) && seriesA.values.length > 0;
    const hasB = Array.isArray(seriesB.values) && seriesB.values.length > 0;
    const max = Math.max(1, ...(hasA?seriesA.values:[0]), ...(hasB?seriesB.values:[0]));
    const empty = !hasA && !hasB;
    if (empty){
      ctx.fillStyle = '#666';
      ctx.font = '14px system-ui, -apple-system, Segoe UI, Roboto';
      ctx.fillText('Sem dados para o período/filtros selecionados.', pad, H/2);
      return;
    }
    // axes
    ctx.strokeStyle = '#ddd'; ctx.lineWidth = 1; ctx.beginPath();
    ctx.moveTo(pad, pad); ctx.lineTo(pad, H-pad); ctx.lineTo(W-pad, H-pad); ctx.stroke();
    const xCount = hasB ? Math.max(seriesA.labels.length, seriesB.labels.length) : seriesA.labels.length;
    const step = (W - pad*2) / Math.max(1, xCount-1);

    if (type === 'line' || type === 'bar'){
      const colorA = '#3b82f6';
      const colorB = '#f97316';
      if (type === 'line'){
        // A
        ctx.strokeStyle = colorA; ctx.lineWidth = 2; ctx.beginPath();
        seriesA.values.forEach((v,i) => {
          const x = pad + i*step;
          const y = H - pad - (H - pad*2) * (v / max);
          if (i===0) ctx.moveTo(x,y); else ctx.lineTo(x,y);
        });
        ctx.stroke();
        // B (tracejado) apenas se houver dados
        if (hasB){
          ctx.setLineDash([6,6]); ctx.strokeStyle = colorB; ctx.beginPath();
          seriesB.values.forEach((v,i) => {
            const x = pad + i*step;
            const y = H - pad - (H - pad*2) * (v / max);
            if (i===0) ctx.moveTo(x,y); else ctx.lineTo(x,y);
          });
          ctx.stroke(); ctx.setLineDash([]);
        }
      } else {
        // bar agrupado
        const barW = Math.max(10, step * 0.35);
        seriesA.values.forEach((v,i) => {
          const x = pad + i*step - barW*0.55;
          const h = (H - pad*2) * (v / max);
          ctx.fillStyle = colorA; ctx.fillRect(x, H-pad-h, barW, h);
        });
        if (hasB){
          seriesB.values.forEach((v,i) => {
            const x = pad + i*step + barW*0.2;
            const h = (H - pad*2) * (v / max);
            ctx.fillStyle = colorB; ctx.fillRect(x, H-pad-h, barW, h);
          });
        }
      }
      // legenda
      ctx.fillStyle = '#444'; ctx.font = '12px system-ui, -apple-system, Segoe UI, Roboto';
      ctx.fillText('Período A', pad, pad-10);
      if (hasB) ctx.fillText('Período B', pad+80, pad-10);

      // Tooltip PT-BR para linhas/barras
      let tip;
      const ddmmyyyy = (iso)=>{ try { const d=new Date(iso); const dd=String(d.getDate()).padStart(2,'0'); const mm=String(d.getMonth()+1).padStart(2,'0'); const yy=d.getFullYear(); return `${dd}-${mm}-${yy}`; } catch(_){ return iso; } };
      const showTip = (text, mx, my) => {
        if (!tip) { tip = document.createElement('div'); tip.style.position='absolute'; tip.style.background='#111'; tip.style.color='#fff'; tip.style.padding='6px 8px'; tip.style.borderRadius='6px'; tip.style.fontSize='12px'; tip.style.pointerEvents='none'; tip.style.boxShadow='0 4px 16px rgba(0,0,0,0.2)'; canvas.parentNode.appendChild(tip); }
        tip.textContent = text; const rect = canvas.getBoundingClientRect(); tip.style.left = (mx - rect.left + 12) + 'px'; tip.style.top = (my - rect.top - 24) + 'px'; tip.style.display='block';
      };
      const hideTip = ()=>{ if (tip) tip.style.display='none'; };
      const xCount = hasB ? Math.max(seriesA.labels.length, seriesB.labels.length) : seriesA.labels.length;
      const stepX = (W - pad*2) / Math.max(1, xCount-1);
      canvas.onmousemove = (e)=>{
        const rect = canvas.getBoundingClientRect(); const mx = e.clientX; const my = e.clientY;
        const xIn = mx - rect.left; const yIn = my - rect.top;
        // índice aproximado
        let i = Math.round((xIn - pad) / stepX);
        i = Math.max(0, Math.min(i, (seriesA.labels.length-1)));
        const label = seriesA.labels[i] || seriesB.labels[i] || '';
        const vA = seriesA.values[i]; const vB = hasB ? seriesB.values[i] : undefined;
        if (typeof vA === 'number') {
          showTip(`${ddmmyyyy(label)} • Período A: ${fmtBRL(vA)}${typeof vB==='number'?` • Período B: ${fmtBRL(vB)}`:''}`, mx, my);
        } else if (typeof vB === 'number') {
          showTip(`${ddmmyyyy(label)} • Período B: ${fmtBRL(vB)}`, mx, my);
        } else {
          hideTip();
        }
      };
      canvas.onmouseleave = hideTip;
    } else if (type === 'pie'){
      // Pie usa série A como breakdown
      const sum = seriesA.values.reduce((a,b)=>a+b,0) || 1;
      const cx = W/2, cy = H/2, r = Math.min(W,H)/3;
      let ang = -Math.PI/2;
      const colors = ['#2563eb','#ef4444','#10b981','#eab308','#06b6d4','#8b5cf6','#f97316'];
      seriesA.values.forEach((v,i) => {
        const frac = v / sum; const a2 = ang + frac * Math.PI*2;
        ctx.beginPath(); ctx.moveTo(cx,cy); ctx.fillStyle = colors[i % colors.length];
        ctx.arc(cx,cy,r,ang,a2); ctx.closePath(); ctx.fill(); ang = a2;
      });
      // legenda compacta e tooltip PT-BR
      ctx.fillStyle = '#444'; ctx.font = '12px system-ui, -apple-system, Segoe UI, Roboto';
      seriesA.labels.slice(0,6).forEach((l,i) => {
        ctx.fillStyle = colors[i % colors.length]; ctx.fillRect(10, 10 + i*16, 10, 10);
        ctx.fillStyle = '#444'; ctx.fillText(String(l).slice(0,20), 26, 20 + i*16);
      });

      let tip;
      const showTip = (text, mx, my) => {
        if (!tip) { tip = document.createElement('div'); tip.style.position='absolute'; tip.style.background='#111'; tip.style.color='#fff'; tip.style.padding='6px 8px'; tip.style.borderRadius='6px'; tip.style.fontSize='12px'; tip.style.pointerEvents='none'; tip.style.boxShadow='0 4px 16px rgba(0,0,0,0.2)'; canvas.parentNode.appendChild(tip); }
        tip.textContent = text; const rect = canvas.getBoundingClientRect(); tip.style.left = (mx - rect.left + 12) + 'px'; tip.style.top = (my - rect.top - 24) + 'px'; tip.style.display='block';
      };
      const hideTip = ()=>{ if (tip) tip.style.display='none'; };
      canvas.onmousemove = (e)=>{
        const rect = canvas.getBoundingClientRect(); const mx = e.clientX; const my = e.clientY; const x=mx-rect.left, y=my-rect.top;
        const cx = W/2, cy = H/2, r = Math.min(W,H)/3;
        const dx=x-cx, dy=y-cy; const dist=Math.sqrt(dx*dx+dy*dy);
        if (dist>r) { hideTip(); return; }
        let angAcc=-Math.PI/2; const sum = seriesA.values.reduce((a,b)=>a+b,0)||1;
        for(let i=0;i<seriesA.values.length;i++){
          const frac = seriesA.values[i]/sum; const a2 = angAcc + frac*Math.PI*2;
          let ang = Math.atan2(dy,dx);
          if (ang < -Math.PI/2) ang += Math.PI*2;
          if (ang>=angAcc && ang<=a2){
            showTip(`${String(seriesA.labels[i]||'-')}: ${fmtBRL(seriesA.values[i]||0)}`, mx, my);
            return;
          }
          angAcc=a2;
        }
        hideTip();
      };
      canvas.onmouseleave = hideTip;
    }
  }

  async function load(){
    if (abort) abort.abort();
    abort = new AbortController();
    const { aStart, aEnd, bStart, bEnd } = presetToRanges();
    const params = new URLSearchParams();
    params.set('start', fmtDate(aStart));
    params.set('end', fmtDate(aEnd));
    params.set('compare_start', fmtDate(bStart));
    params.set('compare_end', fmtDate(bEnd));
    if (el.product?.value) params.set('product', el.product.value);
    if (el.region?.value) params.set('region', el.region.value);
    if (el.seller?.value) params.set('seller', el.seller.value);
    params.set('group_by', 'day');
    setStatus('');
    let json = await fetchJson(`/api/sales/advanced?${params.toString()}`, { signal: abort.signal });
    if (json && json.error === 401){
      setStatus('Sessão expirada — faça login para ver dados.');
      draw(el.canvas, el.type?.value || 'line', { labels: [], values: [] }, { labels: [], values: [] });
      return;
    }
    if (!json || (!json.current && !json.a) && (!json.previous && !json.b)){
      // Tentativa de fallback sem filtros
      const noFilter = new URLSearchParams(params);
      ['product','region','seller'].forEach(k=>noFilter.delete(k));
      json = await fetchJson(`/api/sales/advanced?${noFilter.toString()}`, { signal: abort.signal });
      if (json && json.error === 401){
        setStatus('Sessão expirada — faça login para ver dados.');
        draw(el.canvas, el.type?.value || 'line', { labels: [], values: [] }, { labels: [], values: [] });
        return;
      }
    }
    const a = json.current || json.a || { items: [] };
    const b = json.previous || json.b || { items: [] };
    const seriesA = groupDaily(a.items || a);
    const seriesB = groupDaily(b.items || b);
    const hasA = Array.isArray(seriesA.values) && seriesA.values.length > 0;
    const hasB = Array.isArray(seriesB.values) && seriesB.values.length > 0;
    if (!hasA && !hasB){
      setStatus('Sem dados para o período/filtros selecionados.');
    } else if (hasA && !hasB){
      setStatus('Sem comparação disponível para o período anterior.');
    } else {
      setStatus('');
    }
    draw(el.canvas, el.type?.value || 'line', seriesA, seriesB);
  }

  el.apply?.addEventListener('click', load);
  el.type?.addEventListener('change', load);
  el.preset?.addEventListener('change', load);

  // Preenche filtros e então carrega o gráfico
  populateFilters().finally(load);
}