import { resources, elements } from "./planetEconomy.js";

// ── Sort state (resources) ────────────────────────────────────────────────────

/** 0=Ressource, 1=Rareté, 2=Valeur, 3=Revenu/s */
let _sortCol = 3;
let _sortDir = "desc";

export function setEconSort(col, dir) {
  _sortCol = col;
  _sortDir = dir;
}

export function getEconSort() {
  return { col: _sortCol, dir: _sortDir };
}

// ── Sort state (elements) ─────────────────────────────────────────────────────

/** 0=Élément, 1=Valeur/élément, 2=Bonus % */
let _elemSortCol = 2;
let _elemSortDir = "desc";

export function setElemSort(col, dir) {
  _elemSortCol = col;
  _elemSortDir = dir;
}

export function getElemSort() {
  return { col: _elemSortCol, dir: _elemSortDir };
}

// ── Label → resource key lookup ───────────────────────────────────────────────

/** Map from French label string → { cat: "common"|"rare", key: string } */
const LABEL_TO_RESOURCE = (() => {
  const map = new Map();
  for (const [cat, entries] of Object.entries(resources)) {
    for (const [key, label] of Object.entries(entries)) {
      map.set(label, { cat, key });
    }
  }
  return map;
})();

// ── Income calculation ────────────────────────────────────────────────────────

/**
 * Compute income per second for a team based on their discovered planets.
 *
 * @param {string} team - "blue" or "red"
 * @param {Map<string, { discoveredBy: string, hasPlanet: boolean, planet: object|null }>} cells
 * @param {object} resourceWorth - { common: { rock: 1, ... }, rare: { rock: 3, ... } }
 * @returns {{ total: number, byResource: Map<string, number> }}
 *   byResource keys are resource label strings (French names), values are credits/sec
 */
export function computeTeamIncome(team, cells, resourceWorth) {
  /** @type {Map<string, number>} label → cumulative income/sec */
  const byResource = new Map();
  let total = 0;

  for (const [, meta] of cells) {
    if (meta.discoveredBy !== team) continue;
    if (!meta.hasPlanet || !meta.planet) continue;
    const { naturalResources } = meta.planet;
    if (!naturalResources) continue;

    for (const [label, pct] of Object.entries(naturalResources)) {
      const info = LABEL_TO_RESOURCE.get(label);
      if (!info) continue;
      const worth = resourceWorth?.[info.cat]?.[info.key] ?? 0;
      if (worth === 0) continue;
      const income = (pct / 100) * worth;
      byResource.set(label, (byResource.get(label) ?? 0) + income);
      total += income;
    }
  }

  return { total, byResource };
}

// ── Element bonus calculation ─────────────────────────────────────────────────

/**
 * Reverse map: French element label → config key
 * e.g. "Matières premières" → "common", "Hydrocarbures" → "petrol"
 */
const ELEMENT_LABEL_TO_KEY = Object.fromEntries(
  Object.entries(elements).map(([key, label]) => [label, key])
);

/**
 * Compute cumulative element bonus for a team based on their planets' production.
 * planet.production stores French label strings as keys (values from elements const).
 * bonus = sum_over_planets( sum_over_elements( elementShare% / 100 * elementWorth[key] ) )
 *
 * @param {string} team
 * @param {Map<string, { discoveredBy: string, hasPlanet: boolean, planet: object|null }>} cells
 * @param {object} elementWorth - { common: 1, petrol: 3, ... }
 * @returns {number} bonus value (use as %)
 */
export function computeTeamElementBonus(team, cells, elementWorth) {
  let bonus = 0;
  for (const [, meta] of cells) {
    if (meta.discoveredBy !== team) continue;
    if (!meta.hasPlanet || !meta.planet) continue;
    const { production } = meta.planet;
    if (!production) continue;
    for (const [elementLabel, pct] of Object.entries(production)) {
      // production keys are French labels; map back to config key
      const elementKey = ELEMENT_LABEL_TO_KEY[elementLabel] ?? elementLabel;
      const worth = elementWorth?.[elementKey] ?? 0;
      if (worth === 0) continue;
      bonus += (pct / 100) * worth;
    }
  }
  return bonus;
}

/**
 * Compute per-element bonus breakdown for a team.
 *
 * @param {string} team
 * @param {Map<string, { discoveredBy: string, hasPlanet: boolean, planet: object|null }>} cells
 * @param {object} elementWorth - { common: 1, petrol: 3, ... }
 * @returns {{ total: number, byElement: Map<string, number> }}
 *   byElement keys are French element label strings, values are cumulative bonus %
 */
export function computeTeamElementBonusDetailed(team, cells, elementWorth) {
  const byElement = new Map();
  let total = 0;
  for (const [, meta] of cells) {
    if (meta.discoveredBy !== team) continue;
    if (!meta.hasPlanet || !meta.planet) continue;
    const { production } = meta.planet;
    if (!production) continue;
    for (const [elementLabel, pct] of Object.entries(production)) {
      const elementKey = ELEMENT_LABEL_TO_KEY[elementLabel] ?? elementLabel;
      const worth = elementWorth?.[elementKey] ?? 0;
      if (worth === 0) continue;
      const bonus = (pct / 100) * worth;
      byElement.set(elementLabel, (byElement.get(elementLabel) ?? 0) + bonus);
      total += bonus;
    }
  }
  return { total, byElement };
}

export { elements };

// ── Resource table for the sidebar ───────────────────────────────────────────

/**
 * Renders the resource overview table for the economy panel.
 *
 * @param {object} resourceWorth - { common: {…}, rare: {…} }
 * @param {Map<string, number>} teamByResource - income/sec per label for current team
 * @returns {string} HTML string
 */
export function renderResourceTable(resourceWorth, teamByResource) {
  const rows = [];

  for (const [cat, entries] of Object.entries(resources)) {
    for (const [key, label] of Object.entries(entries)) {
      const worth = resourceWorth?.[cat]?.[key] ?? 0;
      const income = teamByResource?.get(label) ?? 0;
      const incomeStr = income > 0 ? `+${income.toFixed(3)}/s` : "—";
      const catLabel = cat === "rare" ? "Rare" : "Commun";
      rows.push({ label, catLabel, worth, income, incomeStr });
    }
  }

  // Sort by selected column
  const mult = _sortDir === "asc" ? 1 : -1;
  rows.sort((a, b) => {
    if (_sortCol === 0) return mult * a.label.localeCompare(b.label, "fr");
    if (_sortCol === 1) return mult * a.catLabel.localeCompare(b.catLabel, "fr");
    if (_sortCol === 2) return mult * (a.worth - b.worth);
    if (_sortCol === 3) return mult * (a.income - b.income);
    return b.income - a.income || b.worth - a.worth;
  });

  const tableRows = rows
    .map(({ label, catLabel, worth, incomeStr, income }) => {
      const incomeClass = income > 0 ? " econ-income--positive" : "";
      return `<tr>
        <td class="econ-label">${label}</td>
        <td class="econ-cat econ-cat--${catLabel.toLowerCase()}">${catLabel}</td>
        <td class="econ-worth">${worth}</td>
        <td class="econ-income${incomeClass}">${incomeStr}</td>
      </tr>`;
    })
    .join("");

  const thLabels = ["Ressource", "Rareté", "Valeur", "Revenu/s"];
  const headers = thLabels
    .map((lbl, i) => {
      const isActive = i === _sortCol;
      const indicator = isActive ? (_sortDir === "asc" ? " ▲" : " ▼") : " ⇅";
      const activeClass = isActive ? " econTh--active" : "";
      return `<th class="econTh${activeClass}" data-sort-col="${i}">${lbl}<span class="econSortIcon">${indicator}</span></th>`;
    })
    .join("");

  return `<table class="econTable">
    <thead><tr>${headers}</tr></thead>
    <tbody>${tableRows}</tbody>
  </table>`;
}

// ── Element bonus table for the sidebar ──────────────────────────────────────

/**
 * Renders the element bonus breakdown table.
 *
 * @param {object} elementWorth - { common: 1, petrol: 3, ... }
 * @param {Map<string, number>} teamByElement - bonus per element label for current team
 * @returns {string} HTML string
 */
export function renderElementBonusTable(elementWorth, teamByElement) {
  const rows = [];

  for (const [key, label] of Object.entries(elements)) {
    const worth = elementWorth?.[key] ?? 0;
    const bonus = teamByElement?.get(label) ?? 0;
    const bonusStr = bonus > 0 ? `+${bonus.toFixed(3)}%` : "—";
    rows.push({ label, worth, bonus, bonusStr });
  }

  const mult = _elemSortDir === "asc" ? 1 : -1;
  rows.sort((a, b) => {
    if (_elemSortCol === 0) return mult * a.label.localeCompare(b.label, "fr");
    if (_elemSortCol === 1) return mult * (a.worth - b.worth);
    if (_elemSortCol === 2) return mult * (a.bonus - b.bonus);
    return b.bonus - a.bonus || b.worth - a.worth;
  });

  if (rows.every(r => r.bonus === 0)) {
    return `<p class="econEmpty">Aucune tuile conquise avec des éléments de production.</p>`;
  }

  const tableRows = rows
    .map(({ label, worth, bonus, bonusStr }) => {
      const bonusClass = bonus > 0 ? " econ-income--positive" : "";
      return `<tr>
        <td class="econ-label">${label}</td>
        <td class="econ-worth">${worth}</td>
        <td class="econ-income${bonusClass}">${bonusStr}</td>
      </tr>`;
    })
    .join("");

  const thLabels = ["Élément", "Val./élément", "Bonus %"];
  const headers = thLabels
    .map((lbl, i) => {
      const isActive = i === _elemSortCol;
      const indicator = isActive ? (_elemSortDir === "asc" ? " ▲" : " ▼") : " ⇅";
      const activeClass = isActive ? " econTh--active" : "";
      return `<th class="econTh${activeClass}" data-elem-sort-col="${i}">${lbl}<span class="econSortIcon">${indicator}</span></th>`;
    })
    .join("");

  return `<table class="econTable">
    <thead><tr>${headers}</tr></thead>
    <tbody>${tableRows}</tbody>
  </table>`;
}