// Utilidades compartidas para vistas que consumen el backend FastAPI.
// window.API_BASE is set by src/config.js (loaded before this file).

window.hsQ = function(hsCodes) {
  if (!hsCodes || hsCodes.length === 0) return "hs=0210";
  if (hsCodes.length === 1 && hsCodes[0].length === 4) return `hs=${hsCodes[0]}`;
  return `hs_codes=${hsCodes.join(",")}`;
};

// Hook fetch con cancelación. Deps es array de dependencias para useEffect.
// Si url es null/undefined, devuelve estado idle sin llamar a fetch.
function useApi(url, deps) {
  const [state, setState] = React.useState({ status: "loading", data: null, error: null });
  React.useEffect(() => {
    if (!url) {
      setState({ status: "idle", data: null, error: null });
      return;
    }
    let cancelled = false;
    setState({ status: "loading", data: null, error: null });
    fetch(url)
      .then(r => r.ok ? r.json() : Promise.reject(new Error("HTTP " + r.status)))
      .then(data => { if (!cancelled) setState({ status: "ok", data, error: null }); })
      .catch(err  => { if (!cancelled) setState({ status: "error", data: null, error: String(err.message || err) }); });
    return () => { cancelled = true; };
  }, deps);
  return state;
}

// Chart de dos líneas — solo renderiza el gráfico, sin controles.
// El botón de ampliar vive en EvolucionPanel (cabecera del panel).
function DualLineChart({ vol, val, granularity }) {
  return <DualLineChartInner vol={vol} val={val} granularity={granularity} height={300} />;
}

// Panel de evolución reutilizable. Acepta:
//   country="FR"          → filtra a un país destino (ISO-2)
//   continent="Europa"    → filtra al continente (requiere country.continent backfilled en BD)
//   sin ninguno           → global
function EvolucionPanel({ hs, hsCodes, metric, years, country, continent }) {
  const CF = window.CF;
  const lo = Math.min(...years), hi = Math.max(...years);
  const [gran, setGran]         = React.useState("month");
  const [expanded, setExpanded] = React.useState(false);

  const hsParam = hsCodes ? window.hsQ(hsCodes) : `hs=${hs}`;
  const qs = [
    hsParam, `from=${lo}`, `to=${hi}`, `granularity=${gran}`,
    country   ? `country=${country}`     : null,
    continent ? `continent=${encodeURIComponent(continent)}` : null,
  ].filter(Boolean).join("&");

  const depKey = hsCodes ? hsCodes.join(",") : hs;
  const s = window.useApi(`${window.API_BASE}/api/series?${qs}`, [depKey, lo, hi, gran, country, continent]);

  const loading = s.status === "loading";
  const rows    = s.data?.rows || [];
  const volS = rows.map(r => ({ period: r.period, year: r.year, month: r.month, value: r.tonnes }));
  const valS = rows.map(r => ({ period: r.period, year: r.year, month: r.month, value: r.eur   }));

  const lastYr = rows.filter(r => r.year === hi);
  const prevYr = rows.filter(r => r.year === hi - 1);
  const sumEur = (arr) => arr.reduce((a, r) => a + r.eur, 0);
  const yoy = prevYr.length && sumEur(prevYr) > 0
    ? (sumEur(lastYr) - sumEur(prevYr)) / sumEur(prevYr) : null;

  const scopeLabel = country ? country : continent ? continent : "global";

  return (
    <div className="cf-panel">
      <div className="cf-panel-head">
        <div>
          <h2>Evolución {continent ? "regional" : country ? `· ${country}` : "global"}</h2>
          <p>{lo} – {hi} · {CF.metricLabel(metric)}</p>
        </div>
        <div className="cf-panel-tools" style={{display:"flex", gap:8, alignItems:"center"}}>
          {yoy != null && <span className="cf-tag"><I.TrendingUp size={12}/>{CF.fmtDelta(yoy)} YoY {hi}</span>}
          <div className="cf-seg">
            <button className={gran === "year"  ? "on" : ""} onClick={() => setGran("year")}>Anual</button>
            <button className={gran === "month" ? "on" : ""} onClick={() => setGran("month")}>Mensual</button>
          </div>
          <button className="cf-btn" onClick={() => setExpanded(true)} title="Ver en pantalla completa">
            <I.Expand size={13} /> Ampliar
          </button>
        </div>
      </div>

      {loading && <div style={{padding:"24px 0", textAlign:"center", color:"var(--xn-fg-3)", fontSize:13}}>Cargando…</div>}
      {!loading && s.status === "error" && <div style={{padding:12, color:"var(--xn-danger)", fontSize:12}}>{s.error}</div>}
      {!loading && s.status === "ok" && rows.length === 0 && (
        <div style={{padding:"16px 0", color:"var(--xn-fg-3)", fontSize:13}}>
          Sin datos para este filtro.
          {continent && <span> (Requiere backfill de <code>country.continent</code> en la BD)</span>}
        </div>
      )}
      {!loading && s.status === "ok" && rows.length > 0 && (
        <>
          <div className="cf-chart-legend" style={{marginBottom:6}}>
            <div className="it"><span className="sw" style={{background:"var(--xn-blue-500)"}} /><span><strong>Volumen</strong> · toneladas</span></div>
            <div className="it"><span className="sw" style={{background:"var(--xn-blue-900)", height:3, borderStyle:"dashed"}} /><span><strong>Valor</strong> · miles €</span></div>
          </div>
          <DualLineChart vol={volS} val={valS} granularity={gran} />
        </>
      )}
      {expanded && rows.length > 0 && (
        <ChartModal vol={volS} val={valS} granularity={gran} onClose={() => setExpanded(false)} />
      )}
    </div>
  );
}

// Modal de pantalla completa para el chart. Se cierra con Escape o haciendo clic fuera.
function ChartModal({ vol, val, granularity, onClose }) {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, []);

  return ReactDOM.createPortal(
    <div
      onClick={onClose}
      style={{
        position:"fixed", inset:0, zIndex:10000,
        background:"rgba(4,10,22,0.88)",
        display:"flex", flexDirection:"column",
        alignItems:"center", justifyContent:"center",
        padding:32,
        backdropFilter:"blur(4px)",
      }}
    >
      <div
        className="cf-panel"
        onClick={e => e.stopPropagation()}
        style={{
          width:"100%", maxWidth:1200,
          margin:0,
          boxShadow:"0 24px 80px rgba(0,0,0,0.5)",
        }}
      >
        <div style={{display:"flex", justifyContent:"space-between", alignItems:"center", marginBottom:16}}>
          <div className="cf-chart-legend" style={{margin:0}}>
            <div className="it"><span className="sw" style={{background:"var(--xn-blue-500)"}} /><span><strong>Volumen</strong> · toneladas</span></div>
            <div className="it"><span className="sw" style={{background:"var(--xn-blue-900)", height:3, borderStyle:"dashed"}} /><span><strong>Valor</strong> · miles €</span></div>
          </div>
          <button
            onClick={onClose}
            style={{
              background:"none", border:"1px solid rgba(255,255,255,0.15)",
              color:"var(--xn-fg-2)", borderRadius:6, padding:"4px 12px",
              cursor:"pointer", fontSize:13,
            }}
          >
            Cerrar ✕
          </button>
        </div>
        <DualLineChartInner vol={vol} val={val} granularity={granularity} height={480} />
      </div>
    </div>,
    document.body
  );
}

// DualLineChart interno sin el wrapper de modal — renderiza solo el SVG.
function DualLineChartInner({ vol, val, granularity, height }) {
  const CF = window.CF;
  const H = height || 300;
  const W = 900, PL = 64, PR = 64, PT = 20, PB = 36;
  const innerW = W - PL - PR, innerH = H - PT - PB;
  const n = vol.length;
  if (n === 0) return <div style={{padding:24, color:"var(--xn-fg-3)"}}>Sin datos en el período.</div>;

  const volMax = Math.max(...vol.map(p => p.value)) * 1.1 || 1;
  const valMax = Math.max(...val.map(p => p.value)) * 1.1 || 1;
  const x    = (i) => PL + (i / Math.max(1, n - 1)) * innerW;
  const yVol = (v) => PT + innerH - (v / volMax) * innerH;
  const yVal = (v) => PT + innerH - (v / valMax) * innerH;
  const volPath = vol.map((p, i) => `${i===0?"M":"L"} ${x(i)} ${yVol(p.value)}`).join(" ");
  const valPath = val.map((p, i) => `${i===0?"M":"L"} ${x(i)} ${yVal(p.value)}`).join(" ");
  const volArea = `${volPath} L ${x(n-1)} ${PT+innerH} L ${x(0)} ${PT+innerH} Z`;

  const xTicks = [];
  if (granularity === "month") {
    vol.forEach((p, i) => { if (p.month === 1) xTicks.push({ i, label: String(p.year) }); });
  } else {
    vol.forEach((p, i) => xTicks.push({ i, label: String(p.year) }));
  }

  const [hoverIdx, setHoverIdx] = React.useState(null);
  const [tipPos,   setTipPos]   = React.useState({ x: 0, y: 0 });
  const showDots = n <= 24;

  function onMouseMove(e) {
    const svg = e.currentTarget;
    const pt = svg.createSVGPoint();
    pt.x = e.clientX; pt.y = e.clientY;
    const lp = pt.matrixTransform(svg.getScreenCTM().inverse());
    const i = Math.round(((lp.x - PL) / innerW) * (n - 1));
    if (i >= 0 && i < n) { setHoverIdx(i); setTipPos({ x: e.clientX, y: e.clientY }); }
  }

  return (
    <div className="cf-chart-wrap">
      <svg className="cf-chart-svg" viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet"
           onMouseMove={onMouseMove} onMouseLeave={() => setHoverIdx(null)}>
        {[0, 0.25, 0.5, 0.75, 1].map(t => {
          const y = PT + innerH * (1 - t);
          return (
            <g key={t}>
              <line className="grid" x1={PL} x2={W-PR} y1={y} y2={y} />
              <text className="axis-lbl" x={PL-8} y={y+4} textAnchor="end" style={{fill:"var(--xn-blue-500)"}}>{CF.fmtVal(volMax*t,"vol")}</text>
              <text className="axis-lbl" x={W-PR+8} y={y+4} textAnchor="start" style={{fill:"var(--xn-blue-900)"}}>{CF.fmtVal((valMax*t)/1000,"val")}</text>
            </g>
          );
        })}
        {xTicks.map(t => (
          <g key={t.i}>
            {granularity==="month" && <line className="grid" x1={x(t.i)} x2={x(t.i)} y1={PT} y2={PT+innerH} strokeDasharray="2 4" opacity="0.4" />}
            <text className="axis-lbl" x={x(t.i)} y={H-10} textAnchor="middle">{t.label}</text>
          </g>
        ))}
        <path className="area"     d={volArea} fill="var(--xn-blue-500)" />
        <path className="line-vol" d={volPath} />
        {showDots && vol.map((p,i) => <circle key={"v"+i} cx={x(i)} cy={yVol(p.value)} r="4" fill="var(--xn-blue-500)" />)}
        <path className="line-val" d={valPath} />
        {showDots && val.map((p,i) => <circle key={"e"+i} cx={x(i)} cy={yVal(p.value)} r="4" fill="var(--xn-blue-900)" />)}
        {hoverIdx != null && (
          <g>
            <line x1={x(hoverIdx)} x2={x(hoverIdx)} y1={PT} y2={PT+innerH} stroke="var(--xn-blue-700)" strokeWidth="1" strokeDasharray="3 3" opacity="0.6" />
            <circle cx={x(hoverIdx)} cy={yVol(vol[hoverIdx].value)} r="6" fill="white" stroke="var(--xn-blue-500)" strokeWidth="2.5" />
            <circle cx={x(hoverIdx)} cy={yVal(val[hoverIdx].value)} r="6" fill="white" stroke="var(--xn-blue-900)" strokeWidth="2.5" />
          </g>
        )}
      </svg>
      {hoverIdx != null && (
        <div className="cf-chart-tip" style={{left: Math.min(tipPos.x+14, window.innerWidth-220), top: tipPos.y-70}}>
          <div className="yr">{vol[hoverIdx].period}</div>
          <div className="row"><span className="dot" style={{background:"var(--xn-blue-500)"}} /><span style={{opacity:.65}}>Volumen</span><span style={{fontWeight:600,marginLeft:"auto"}}>{CF.fmtVal(vol[hoverIdx].value,"vol")}</span></div>
          <div className="row"><span className="dot" style={{background:"var(--xn-blue-900)"}} /><span style={{opacity:.65}}>Valor</span><span style={{fontWeight:600,marginLeft:"auto"}}>{CF.fmtVal(val[hoverIdx].value/1000,"val")}</span></div>
        </div>
      )}
    </div>
  );
}

// ─── Helpers de datos ────────────────────────────────────────────────────────

// Normaliza una fila de /api/countries al shape interno del frontend.
// - iso:  ISO3 cuando está disponible (compatibilidad con mapa y navegación)
// - value: toneladas si metric='vol', k€ si metric='val' (CF.fmtVal espera k€)
function normalizeCountryRow(row, metric) {
  return {
    iso:       row.iso3 || row.iso2,
    iso2:      row.iso2,
    name:      row.name || row.iso2,
    continent: row.continent || "Otros",
    eu:        !!row.eu_member,
    value:     metric === "vol" ? row.tonnes : row.eur / 1000,
    tonnes:    row.tonnes,
    eur:       row.eur,
  };
}

// Agrupa filas normalizadas por continente.
function computeContinents(rows) {
  const acc = {};
  for (const r of rows) {
    if (!r.continent) continue;
    if (!acc[r.continent]) acc[r.continent] = { continent: r.continent, value: 0, countries: [] };
    acc[r.continent].value += r.value;
    acc[r.continent].countries.push(r);
  }
  return Object.values(acc).sort((a, b) => b.value - a.value);
}

// Cache global ISO3→ISO2, populado cuando cualquier vista llama a /api/countries.
// Permite que DrillCountry convierta drill.country (ISO3) al ISO2 que necesita /api/series.
window.__iso3toIso2 = window.__iso3toIso2 || {};
window.__countryByIso3 = window.__countryByIso3 || {};

function populateCountryCache(rows) {
  for (const r of rows) {
    if (r.iso3) {
      window.__iso3toIso2[r.iso3] = r.iso2;
      window.__countryByIso3[r.iso3] = r;
    }
  }
}

// Devuelve el ISO2 a partir de ISO3, usando el cache o la tabla estática de respaldo.
const _ISO3_FALLBACK = {
  // Europa
  FRA:"FR",DEU:"DE",GBR:"GB",PRT:"PT",ITA:"IT",NLD:"NL",BEL:"BE",POL:"PL",
  CZE:"CZ",DNK:"DK",SWE:"SE",AUT:"AT",GRC:"GR",ROU:"RO",HUN:"HU",FIN:"FI",
  CHE:"CH",NOR:"NO",IRL:"IE",ESP:"ES",SVK:"SK",SVN:"SI",HRV:"HR",BGR:"BG",
  LTU:"LT",LVA:"LV",EST:"EE",LUX:"LU",CYP:"CY",MLT:"MT",ALB:"AL",
  MKD:"MK",SRB:"RS",BIH:"BA",MNE:"ME",ISL:"IS",UKR:"UA",BLR:"BY",
  RUS:"RU",MDA:"MD",GEO:"GE",ARM:"AM",AZE:"AZ",TUR:"TR",
  // Américas
  USA:"US",MEX:"MX",CAN:"CA",BRA:"BR",CHL:"CL",ARG:"AR",PER:"PE",COL:"CO",
  ECU:"EC",BOL:"BO",PRY:"PY",URY:"UY",VEN:"VE",GTM:"GT",CRI:"CR",PAN:"PA",
  HND:"HN",SLV:"SV",NIC:"NI",CUB:"CU",DOM:"DO",JAM:"JM",TTO:"TT",
  HTI:"HT",BLZ:"BZ",GUY:"GY",SUR:"SR",
  // Asia
  JPN:"JP",CHN:"CN",KOR:"KR",TWN:"TW",HKG:"HK",SGP:"SG",PHL:"PH",
  ARE:"AE",SAU:"SA",ISR:"IL",IDN:"ID",MYS:"MY",THA:"TH",VNM:"VN",
  IND:"IN",PAK:"PK",BGD:"BD",LKA:"LK",NPL:"NP",MMR:"MM",KHM:"KH",
  LAO:"LA",BRN:"BN",TLS:"TL",MNG:"MN",KAZ:"KZ",UZB:"UZ",TKM:"TM",
  KGZ:"KG",TJK:"TJ",IRN:"IR",IRQ:"IQ",JOR:"JO",KWT:"KW",QAT:"QA",
  BHR:"BH",OMN:"OM",YEM:"YE",LBN:"LB",SYR:"SY",
  // África
  ZAF:"ZA",MAR:"MA",EGY:"EG",TUN:"TN",DZA:"DZ",LBY:"LY",NGA:"NG",
  GHA:"GH",KEN:"KE",TZA:"TZ",ETH:"ET",UGA:"UG",ZMB:"ZM",ZWE:"ZW",
  MOZ:"MZ",AGO:"AO",CMR:"CM",SEN:"SN",CIV:"CI",MLI:"ML",BFA:"BF",
  MDG:"MG",MWI:"MW",NAM:"NA",BWA:"BW",RWA:"RW",SSD:"SS",SDN:"SD",
  // Oceanía
  AUS:"AU",NZL:"NZ",PNG:"PG",FJI:"FJ",WSM:"WS",
};
function iso3toIso2(iso3) {
  return window.__iso3toIso2[iso3] || _ISO3_FALLBACK[iso3] || null;
}

window.useApi           = useApi;
window.DualLineChart    = DualLineChart;
window.DualLineChartInner = DualLineChartInner;
window.EvolucionPanel   = EvolucionPanel;
window.normalizeCountryRow = normalizeCountryRow;
window.computeContinents   = computeContinents;
window.populateCountryCache = populateCountryCache;
window.iso3toIso2          = iso3toIso2;
