import { useMemo, useState, useRef, useEffect } from 'react';

/* ── Constantes ─────────────────────────────────────────────── */
const GOLD   = '#4fa8e8';   // bleu ciel — accord avec le thème navy du site
const BG     = '#070c15';
const GRID   = 'rgba(255,255,255,0.055)';
const LABEL  = '#4a5568';

const RANGES = ['1J', '7J', '1M', '3M', 'YTD', '1A', 'TOUT'];

const MOIS_COURT = ['jan.','fév.','mar.','avr.','mai','juin','juil.','août','sep.','oct.','nov.','déc.'];

/* ── Helpers ────────────────────────────────────────────────── */
function fmtK(v) {
  if (v === 0) return '0 €';
  const abs = Math.abs(v);
  if (abs >= 1000) return (v / 1000).toLocaleString('fr-FR', { maximumFractionDigits: 0 }) + ' k €';
  return v.toLocaleString('fr-FR', { maximumFractionDigits: 0 }) + ' €';
}

function fmtAxisDate(dateStr, range) {
  const d = new Date(dateStr + 'T00:00:00');
  const day = String(d.getDate()).padStart(2, '0');
  const mon = MOIS_COURT[d.getMonth()];
  const yr  = d.getFullYear();
  if (range === '1J' || range === '7J') return `${day}/${String(d.getMonth()+1).padStart(2,'0')}`;
  if (range === '1M')  return `${day} ${mon}`;
  if (range === '3M')  return `${day} ${mon}`;
  return `${day}/${String(d.getMonth()+1).padStart(2,'0')}/${String(yr).slice(2)}`;
}

function fmtValueDisplay(v) {
  return v.toLocaleString('fr-FR', { minimumFractionDigits: 0, maximumFractionDigits: 0 }) + ' €';
}

function fmtTodayFull() {
  return new Date().toLocaleDateString('fr-FR', { day: '2-digit', month: 'long', year: 'numeric' });
}

/* ── Composant ──────────────────────────────────────────────── */
export default function SoldeChart({ rows }) {
  const [range,    setRange]    = useState('TOUT');
  const [hover,    setHover]    = useState(null);   // { x, y, value, date }
  const svgRef = useRef(null);
  const wrapRef = useRef(null);

  /* ── 1. Cumul complet (toutes les données) ── */
  const allPoints = useMemo(() => {
    if (!rows?.length) return [];
    const byDate = {};
    for (const r of rows) {
      const d = r.date_operation.slice(0, 10);
      byDate[d] = (byDate[d] || 0) + (r.type === 'depot' ? r.montant : -r.montant);
    }
    let cum = 0;
    return Object.keys(byDate).sort().map(date => {
      cum += byDate[date];
      return { date, value: cum };
    });
  }, [rows]);

  const todayStr  = new Date().toISOString().slice(0, 10);
  const currentValue = allPoints.length ? allPoints[allPoints.length - 1].value : 0;

  /* ── 2. Filtrage par plage ── */
  const points = useMemo(() => {
    if (!allPoints.length) return [];
    if (range === 'TOUT') {
      const pts = [...allPoints];
      if (pts[pts.length - 1].date < todayStr) pts.push({ date: todayStr, value: pts[pts.length - 1].value });
      return pts;
    }
    const now = new Date();
    let fromDate = new Date(now);
    switch (range) {
      case '1J':  fromDate.setDate(now.getDate() - 1);         break;
      case '7J':  fromDate.setDate(now.getDate() - 7);         break;
      case '1M':  fromDate.setMonth(now.getMonth() - 1);       break;
      case '3M':  fromDate.setMonth(now.getMonth() - 3);       break;
      case 'YTD': fromDate = new Date(now.getFullYear(), 0, 1); break;
      case '1A':  fromDate.setFullYear(now.getFullYear() - 1); break;
    }
    const fromStr = fromDate.toISOString().slice(0, 10);
    const before  = allPoints.filter(p => p.date < fromStr);
    const startV  = before.length ? before[before.length - 1].value : 0;
    const after   = allPoints.filter(p => p.date >= fromStr);
    const pts     = [{ date: fromStr, value: startV }, ...after];
    if (pts[pts.length - 1].date < todayStr) pts.push({ date: todayStr, value: pts[pts.length - 1].value });
    return pts;
  }, [allPoints, range, todayStr]);

  /* ── 3. SVG dimensions ── */
  const W = 900, H = 260;
  const PAD = { top: 16, right: 16, bottom: 32, left: 70 };
  const plotW = W - PAD.left - PAD.right;
  const plotH = H - PAD.top - PAD.bottom;

  /* ── 4. Échelles ── */
  const { xScale, yScale, yTicks, xTicks, minDate, maxDate, yZero } = useMemo(() => {
    if (points.length < 2) return {};
    const vals    = points.map(p => p.value);
    const dataMin = Math.min(...vals);
    const dataMax = Math.max(...vals);
    // Inclure 0 pour ancrer l'axe ; ajouter 10 % de padding
    const lo      = Math.min(0, dataMin);
    const hi      = Math.max(0, dataMax);
    const pad     = (hi - lo) * 0.1 || 10;
    const scaleLo = lo - (lo < 0 ? pad : 0);
    const scaleHi = hi + (hi > 0 ? pad : pad);
    const valRange = scaleHi - scaleLo || 1;

    const ts     = points.map(p => new Date(p.date + 'T00:00:00').getTime());
    const minDt  = ts[0];
    const maxDt  = ts[ts.length - 1];
    const dtRange = maxDt - minDt || 1;

    const xScale = d => PAD.left + ((new Date(d + 'T00:00:00').getTime() - minDt) / dtRange) * plotW;
    const yScale = v => PAD.top  + plotH - ((v - scaleLo) / valRange) * plotH;

    // Y ticks : 5 niveaux couvrant la plage réelle
    const step   = (scaleHi - scaleLo) / 4;
    const yTicks = Array.from({ length: 5 }, (_, i) => ({ v: scaleLo + step * i, y: yScale(scaleLo + step * i) }));

    // X ticks : max 8
    const nX = Math.min(8, points.length);
    const xTicks = Array.from({ length: nX }, (_, i) => {
      const idx = Math.round((i / (nX - 1)) * (points.length - 1));
      return points[idx];
    });

    return { xScale, yScale, yTicks, xTicks, minDate: minDt, maxDate: maxDt, yZero: yScale(0) };
  }, [points, plotW, plotH, PAD]);

  /* ── 5. Chemins SVG ── */
  const { linePath, areaPath } = useMemo(() => {
    if (!xScale || points.length < 2) return { linePath: '', areaPath: '' };
    let line = `M ${xScale(points[0].date).toFixed(1)},${yScale(points[0].value).toFixed(1)}`;
    for (let i = 1; i < points.length; i++) {
      line += ` H ${xScale(points[i].date).toFixed(1)} V ${yScale(points[i].value).toFixed(1)}`;
    }
    // Refermer l'aire sur la ligne zéro (et non le bas du chart)
    const zeroY = yZero?.toFixed(1) ?? (PAD.top + plotH).toFixed(1);
    const area  = `${line} V ${zeroY} H ${PAD.left} Z`;
    return { linePath: line, areaPath: area };
  }, [points, xScale, yScale, yZero, PAD, plotH]);

  /* ── 6. Hover ── */
  const handleMouseMove = (e) => {
    if (!svgRef.current || !xScale || points.length < 2) return;
    const rect = svgRef.current.getBoundingClientRect();
    const svgX  = ((e.clientX - rect.left) / rect.width) * W;
    const t     = minDate + ((svgX - PAD.left) / plotW) * (maxDate - minDate);
    // Find nearest point
    let nearest = points[0], minDiff = Infinity;
    for (const p of points) {
      const diff = Math.abs(new Date(p.date + 'T00:00:00').getTime() - t);
      if (diff < minDiff) { minDiff = diff; nearest = p; }
    }
    setHover({
      x:     xScale(nearest.date),
      y:     yScale(nearest.value),
      value: nearest.value,
      date:  nearest.date,
    });
  };

  /* ── Tooltip flottant : DOIT être avant tout return conditionnel (Rules of Hooks) ── */
  const tooltipStyle = useMemo(() => {
    if (!hover) return null;
    const xPct = (hover.x / W) * 100;
    const yPct = (hover.y / H) * 100;
    const anchorRight = xPct > 65;
    return {
      position:  'absolute',
      top:       `calc(${yPct}% - 64px)`,
      left:      anchorRight ? 'auto' : `calc(${xPct}% + 12px)`,
      right:     anchorRight ? `calc(${100 - xPct}% + 12px)` : 'auto',
      transform: 'none',
      pointerEvents: 'none',
    };
  }, [hover]);

  if (!allPoints.length) return null;

  /* ── Date affichée dans l'en-tête (hover ou aujourd'hui) ── */
  const displayDate  = hover
    ? new Date(hover.date + 'T00:00:00').toLocaleDateString('fr-FR', { day: '2-digit', month: 'long', year: 'numeric' })
    : fmtTodayFull();
  const displayValue = hover ? fmtValueDisplay(hover.value) : fmtValueDisplay(currentValue);

  const tooltipDate = hover
    ? new Date(hover.date + 'T00:00:00').toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: 'numeric' })
    : null;

  return (
    <div className="solde-chart-wrap" ref={wrapRef} style={{ position: 'relative' }}>
      {/* ── En-tête ── */}
      <div className="solde-chart-header">
        <div className="solde-chart-info">
          <div className="solde-chart-date">{displayDate}</div>
          <div className="solde-chart-value">{displayValue}</div>
        </div>
        <div className="solde-chart-controls">
          <div className="solde-chart-ranges">
            {RANGES.map(r => (
              <button key={r}
                className={`solde-range-btn${range === r ? ' active' : ''}`}
                onClick={() => { setRange(r); setHover(null); }}>
                {r}
              </button>
            ))}
          </div>
        </div>
      </div>

      {/* ── SVG ── */}
      {xScale && (
        <svg
          ref={svgRef}
          viewBox={`0 0 ${W} ${H}`}
          style={{ width: '100%', height: 'auto', display: 'block', cursor: 'crosshair' }}
          onMouseMove={handleMouseMove}
          onMouseLeave={() => setHover(null)}
        >
          <defs>
            <linearGradient id="sg-fill" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%"   stopColor={GOLD} stopOpacity="0.22" />
              <stop offset="70%"  stopColor={GOLD} stopOpacity="0.06" />
              <stop offset="100%" stopColor={GOLD} stopOpacity="0" />
            </linearGradient>
            <filter id="sg-glow">
              <feGaussianBlur stdDeviation="1.5" result="blur"/>
              <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
            </filter>
          </defs>

          {/* Grille horizontale */}
          {yTicks.map(({ v, y }) => (
            <g key={v}>
              <line x1={PAD.left} y1={y} x2={W - PAD.right} y2={y}
                stroke={GRID} strokeWidth="1" strokeDasharray="3 5" />
              <text x={PAD.left - 10} y={y + 4} textAnchor="end"
                fill={LABEL} fontSize="11" fontFamily="system-ui,sans-serif">
                {fmtK(v)}
              </text>
            </g>
          ))}

          {/* Ligne zéro */}
          {yZero && yZero > PAD.top && yZero < PAD.top + plotH && (
            <line x1={PAD.left} y1={yZero} x2={W - PAD.right} y2={yZero}
              stroke="rgba(255,255,255,0.18)" strokeWidth="1" />
          )}

          {/* Remplissage dégradé */}
          <path d={areaPath} fill="url(#sg-fill)" />

          {/* Ligne principale */}
          <path d={linePath} fill="none" stroke={GOLD} strokeWidth="1"
            filter="url(#sg-glow)" strokeLinejoin="round" />

          {/* Labels axe X */}
          {xTicks.map((p, i) => {
            const anchor = i === 0 ? 'start' : i === xTicks.length - 1 ? 'end' : 'middle';
            return (
              <text key={i} x={xScale(p.date)} y={H - 8}
                textAnchor={anchor} fill={LABEL} fontSize="10"
                fontFamily="system-ui,sans-serif">
                {fmtAxisDate(p.date, range)}
              </text>
            );
          })}

          {/* Ligne verticale + point hover */}
          {hover && (
            <g>
              <line x1={hover.x} y1={PAD.top} x2={hover.x} y2={PAD.top + plotH}
                stroke="rgba(255,255,255,0.12)" strokeWidth="1" strokeDasharray="3 4" />
              <circle cx={hover.x} cy={hover.y} r="4.5"
                fill={GOLD} stroke={BG} strokeWidth="2" />
            </g>
          )}
        </svg>
      )}

      {/* ── Tooltip flottant ── */}
      {hover && tooltipStyle && (
        <div style={tooltipStyle}>
          <div className="sg-tooltip">
            <span className="sg-tooltip-date">{tooltipDate}</span>
            <span className="sg-tooltip-value">{fmtValueDisplay(hover.value)}</span>
          </div>
        </div>
      )}
    </div>
  );
}
