// HsMatrix — Tablas "dimensión × código HS" (spec §1–§7).
//
// Un único renderer compartido (HsMatrixTable) + tres wrappers que cambian la
// dimensión de fila y el endpoint:
//   WorldHsTable     → vista global, filas = continente   (agregado en cliente)
//   ContinentHsTable → vista continente, filas = país      (filtrado en cliente)
//   ProvinceHsTable  → ficha de país, filas = provincia    (endpoint propio)
//
// Nota: la spec mapeaba un componente por archivo de vista; aquí se unifican por
// DRY y se montan dentro de DrillWorld / DrillContinent / DrillCountry.

function pad2(n) { return String(n).padStart(2, "0"); }

// ─── Renderer compartido ──────────────────────────────────────────────────────
// props:
//   columns   [{code}]
//   rows      filas ya en el shape de su dimensión (ver wrappers)
//   metric    "vol" | "val"
//   dimLabel  cabecera de la primera columna ("Continente"/"País"/"Provincia")
//   onRowClick(row) | null
//   renderBadge(row) → nodo o null  (UE / nº países / —)
function HsMatrixTable({ columns, rows, metric, dimLabel, onRowClick, renderBadge, years }) {
  const CF = window.CF;
  const val = (cell) => metric === "vol" ? cell.tonnes : cell.eur / 1000;
  const rowTotal = (r) => metric === "vol" ? r.total_tonnes : r.total_eur / 1000;
  const yrs = years || [];  // modo estacional: una columna por año
  const yearVal = (r, y) => {
    const c = (r.by_year || {})[y] || { tonnes: 0, eur: 0 };
    return metric === "vol" ? c.tonnes : c.eur / 1000;
  };

  return (
    <div className="cf-hsmatrix-wrap">
      <table className="cf-hsmatrix">
        <thead>
          <tr>
            <th className="sticky-col">{dimLabel}</th>
            <th className="num total-col">Total</th>
            {yrs.map(y => (
              <th key={"y" + y} className="num total-col"><span className="cf-hsmatrix-code">{y}</span></th>
            ))}
            {columns.map(col => (
              <th key={col.code} className="num">
                <span className="cf-hsmatrix-code">{col.code}</span>
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((r, i) => (
            <tr
              key={r.key || r.iso3 || r.code}
              className={onRowClick ? "clickable" : ""}
              onClick={onRowClick ? () => onRowClick(r) : undefined}
            >
              <td className="sticky-col">
                <span className="cf-hsmatrix-rank">{pad2(i + 1)}</span>
                <span className="cf-hsmatrix-name">{r.name}</span>
                {renderBadge && renderBadge(r)}
              </td>
              <td className="num total-col">{CF.fmtVal(rowTotal(r), metric)}</td>
              {yrs.map(y => {
                const v = yearVal(r, y);
                return <td key={"y" + y} className="num total-col">{v > 0 ? CF.fmtVal(v, metric) : "—"}</td>;
              })}
              {columns.map(col => {
                const cell = r.cells[col.code] || { tonnes: 0, eur: 0 };
                const v = val(cell);
                return (
                  <td key={col.code} className="num cell">
                    {v > 0 ? CF.fmtVal(v, metric) : "—"}
                  </td>
                );
              })}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

// Excel export de la matriz visible.
// El Excel baja SIEMPRE peso (kg) y valor (eur), independientemente del filtro de métrica.
function exportHsMatrixXlsx(columns, rows, dimLabel, scopeName, lo, hi, baseLabel, cmpLabel, years) {
  const peso  = (cell) => cell.tonnes * 1000; // kg
  const valor = (cell) => cell.eur;           // eur
  const yrs = years || [];                    // modo estacional: una columna por año
  const hasEvo = !yrs.length && baseLabel && cmpLabel;  // rango con evolución dentro del filtro

  const header = [dimLabel, "Total (kg)", "Total (eur)"];
  if (yrs.length) {
    yrs.forEach(y => header.push(`${y} (kg)`, `${y} (eur)`));
  } else if (hasEvo) {
    header.push(`Evolución ${baseLabel}→${cmpLabel} (kg)`, `Evolución ${baseLabel}→${cmpLabel} (eur)`);
  } else {
    header.push("Evolución (kg)", "Evolución (eur)");
  }
  columns.forEach(c => { header.push(`${c.code} (kg)`, `${c.code} (eur)`); });

  const data = rows.map(r => {
    const cols = [r.name, r.total_tonnes * 1000, r.total_eur];
    if (yrs.length) {
      yrs.forEach(y => {
        const c = (r.by_year || {})[y] || { tonnes: 0, eur: 0 };
        cols.push(c.tonnes * 1000, c.eur);
      });
    } else if (hasEvo) {
      cols.push(
        ((r.cur_tonnes || 0) - (r.prev_tonnes || 0)) * 1000,
        (r.cur_eur || 0) - (r.prev_eur || 0),
      );
    } else {
      cols.push("—", "—");
    }
    columns.forEach(c => {
      const cell = r.cells[c.code] || { tonnes: 0, eur: 0 };
      cols.push(peso(cell), valor(cell));
    });
    return cols;
  });

  const ws = XLSX.utils.aoa_to_sheet([header, ...data]);
  const wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, "Exportaciones");
  XLSX.writeFile(wb, `${scopeName}_${lo}-${hi}.xlsx`.replace(/\s+/g, "-").toLowerCase());
}

// Envoltorio de panel + estados (loading / vacío / ok) común a las tres.
function HsMatrixPanel({ title, subtitle, status, columns, rows, metric, dimLabel, onRowClick, renderBadge, scopeName, lo, hi, baseLabel, cmpLabel, years }) {
  return (
    <div className="cf-panel" style={{ marginTop: 18 }}>
      <div className="cf-panel-head">
        <div>
          <h2>{title}</h2>
          <p>{subtitle}</p>
        </div>
        {status === "ok" && rows.length > 0 && (
          <button className="cf-btn" onClick={() => exportHsMatrixXlsx(columns, rows, dimLabel, scopeName, lo, hi, baseLabel, cmpLabel, years)}>
            <I.Download size={14} /> Excel
          </button>
        )}
      </div>

      {status === "loading" && (
        <div style={{ padding: "20px 0", color: "var(--xn-fg-3)", fontSize: 13 }}>Cargando tabla…</div>
      )}
      {status === "error" && (
        <div style={{ padding: 12, color: "var(--xn-danger)", fontSize: 12 }}>Error cargando la tabla.</div>
      )}
      {status === "ok" && rows.length === 0 && (
        <div style={{ padding: "16px 0", color: "var(--xn-fg-3)", fontSize: 13 }}>Sin datos para este filtro.</div>
      )}
      {status === "ok" && rows.length > 0 && (
        <HsMatrixTable
          columns={columns}
          rows={rows}
          metric={metric}
          dimLabel={dimLabel}
          onRowClick={onRowClick}
          renderBadge={renderBadge}
          years={years}
        />
      )}
    </div>
  );
}

// ─── WorldHsTable — filas = continente ─────────────────────────────────────────
function WorldHsTable({ hs, hsCodes, metric, years, drill, setDrill }) {
  const lo = Math.min(...years), hi = Math.max(...years);
  if (!hsCodes || hsCodes.length === 0) return null;

  const api = window.useApi(
    `${window.API_BASE}/api/countries/hs-matrix?${window.hsQ(hsCodes)}&${window.PERIOD.q}`,
    [hsCodes ? hsCodes.join(",") : hs, lo, hi]
  );
  const columns = api.data?.columns || [];
  const countryRows = api.data?.rows || [];
  const seasonYears = api.data?.years || null;   // modo estacional

  // Agregar por continente en el cliente (spec §5).
  const rows = React.useMemo(() => {
    const acc = {};
    for (const r of countryRows) {
      const k = r.continent || "Otros";
      if (!acc[k]) acc[k] = { key: k, name: k, count: 0, total_tonnes: 0, total_eur: 0,
                              cur_tonnes: 0, cur_eur: 0, prev_tonnes: 0, prev_eur: 0,
                              by_year: {}, cells: {} };
      const g = acc[k];
      g.count += 1;
      g.total_tonnes += r.total_tonnes;
      g.total_eur += r.total_eur;
      g.cur_tonnes  += r.cur_tonnes || 0;
      g.cur_eur     += r.cur_eur || 0;
      g.prev_tonnes += r.prev_tonnes || 0;
      g.prev_eur    += r.prev_eur || 0;
      if (r.by_year) {
        for (const y in r.by_year) {
          if (!g.by_year[y]) g.by_year[y] = { tonnes: 0, eur: 0 };
          g.by_year[y].tonnes += r.by_year[y].tonnes;
          g.by_year[y].eur    += r.by_year[y].eur;
        }
      }
      columns.forEach(col => {
        const cell = r.cells[col.code] || { tonnes: 0, eur: 0 };
        if (!g.cells[col.code]) g.cells[col.code] = { tonnes: 0, eur: 0 };
        g.cells[col.code].tonnes += cell.tonnes;
        g.cells[col.code].eur += cell.eur;
      });
    }
    return Object.values(acc).sort((a, b) => b.total_eur - a.total_eur);
  }, [countryRows, columns]);

  return (
    <HsMatrixPanel
      title="Detalle por continente y código HS"
      subtitle={`Global · ${window.CF.metricLabel(metric)} · ${lo}–${hi} · ${columns.length} código(s)`}
      status={api.status}
      columns={columns}
      rows={rows}
      metric={metric}
      dimLabel="Continente"
      onRowClick={(r) => setDrill({ level: "continent", continent: r.key, country: null })}
      renderBadge={(r) => <span className="cf-hsmatrix-eu">{r.count} {r.count === 1 ? "país" : "países"}</span>}
      scopeName="global"
      lo={lo} hi={hi}
      baseLabel={api.data?.prev_label} cmpLabel={api.data?.cur_label}
      years={api.data?.years}
    />
  );
}

// ─── ContinentHsTable — filas = país ───────────────────────────────────────────
function ContinentHsTable({ hs, hsCodes, metric, years, drill, setDrill }) {
  const lo = Math.min(...years), hi = Math.max(...years);
  if (!hsCodes || hsCodes.length === 0) return null;

  const api = window.useApi(
    `${window.API_BASE}/api/countries/hs-matrix?${window.hsQ(hsCodes)}&${window.PERIOD.q}`,
    [hsCodes ? hsCodes.join(",") : hs, lo, hi]
  );
  const columns = api.data?.columns || [];
  const rows = (api.data?.rows || []).filter(r => r.continent === drill.continent);

  return (
    <HsMatrixPanel
      title="Detalle por país y código HS"
      subtitle={`${drill.continent} · ${window.CF.metricLabel(metric)} · ${lo}–${hi} · ${columns.length} código(s)`}
      status={api.status}
      columns={columns}
      rows={rows}
      metric={metric}
      dimLabel="País"
      onRowClick={(r) => setDrill({ level: "country", continent: drill.continent, country: r.iso3 })}
      renderBadge={(r) => r.eu_member ? <span className="cf-hsmatrix-eu">UE</span> : null}
      scopeName={drill.continent || "continente"}
      lo={lo} hi={hi}
      baseLabel={api.data?.prev_label} cmpLabel={api.data?.cur_label}
      years={api.data?.years}
    />
  );
}

// ─── ProvinceHsTable — filas = provincia de origen (sin navegación) ─────────────
function ProvinceHsTable({ hs, hsCodes, metric, years, iso2, countryName }) {
  const lo = Math.min(...years), hi = Math.max(...years);
  if (!hsCodes || hsCodes.length === 0 || !iso2) return null;

  const api = window.useApi(
    `${window.API_BASE}/api/country/${iso2}/origin-provinces/hs-matrix?${window.hsQ(hsCodes)}&${window.PERIOD.q}`,
    [iso2, hsCodes ? hsCodes.join(",") : hs, lo, hi]
  );
  const columns = api.data?.columns || [];
  const rows = api.data?.rows || [];

  return (
    <HsMatrixPanel
      title="Detalle por provincia de origen y código HS"
      subtitle={`Origen español → ${countryName} · ${window.CF.metricLabel(metric)} · ${lo}–${hi} · ${columns.length} código(s)`}
      status={api.status}
      columns={columns}
      rows={rows}
      metric={metric}
      dimLabel="Provincia"
      onRowClick={null}
      renderBadge={null}
      scopeName={`${countryName}-provincias`}
      lo={lo} hi={hi}
      baseLabel={api.data?.prev_label} cmpLabel={api.data?.cur_label}
      years={api.data?.years}
    />
  );
}

window.WorldHsTable = WorldHsTable;
window.ContinentHsTable = ContinentHsTable;
window.ProvinceHsTable = ProvinceHsTable;
