/**
 * MGT2 Commerce – Parseur UWP (Universal World Profile)
 *
 * Format standard :  SAAHPGL-T
 * Exemples :          A788899-C   B200400-A
 *
 *   S = Astroport    (A B C D E X)
 *   A = Taille       (0–A hex, 0–10)
 *   A = Atmosphère   (0–F hex, 0–15)
 *   H = Hydrographie (0–A hex, 0–10)
 *   P = Population   (0–C hex, 0–12)
 *   G = Gouvernement (0–F hex, 0–15)
 *   L = Niveau de loi(0–J hex, 0–19)
 *   T = Niveau tech  (0–F hex, 0–15) — après le tiret
 */

import { TRADE_CODES } from './data/tradeTables.js';

/**
 * Convertit un caractère de code UWP en valeur numérique.
 * Utilise la base 16 pour les chiffres 0–9 et lettres A–F.
 * Pour le Niveau de loi : G=16, H=17, J=18 (pas de I).
 */
function uwpCharToInt(char) {
  if (!char) return 0;
  const c = char.toUpperCase();
  if (c === 'G') return 16;
  if (c === 'H') return 17;
  if (c === 'J') return 18;
  const n = parseInt(c, 16);
  return isNaN(n) ? 0 : n;
}

/**
 * Parse une chaîne UWP et retourne un objet avec tous les attributs.
 * @param {string} uwp  Ex. "A788899-C"
 * @returns {{
 *   raw: string,
 *   valid: boolean,
 *   error: string|null,
 *   starport: string,
 *   size: number,
 *   atmosphere: number,
 *   hydrographics: number,
 *   population: number,
 *   government: number,
 *   lawLevel: number,
 *   techLevel: number,
 *   tradeCodes: string[],
 *   zone: string,
 * }}
 */
export function parseUWP(uwp, zone = 'normal') {
  const result = {
    raw: uwp,
    valid: false,
    error: null,
    starport: '',
    size: 0,
    atmosphere: 0,
    hydrographics: 0,
    population: 0,
    government: 0,
    lawLevel: 0,
    techLevel: 0,
    tradeCodes: [],
    zone,
  };

  if (!uwp || typeof uwp !== 'string') {
    result.error = 'UWP manquant';
    return result;
  }

  // Normalise : retire espaces, met en majuscules
  const s = uwp.trim().toUpperCase();

  // Accepte SAAHPGL-T ou SAAHPGL (sans tech level)
  const match = s.match(/^([ABCDEX])([0-9A-F])([0-9A-F])([0-9A])([0-9A-C])([0-9A-F])([0-9A-J])(?:-([0-9A-F]))?$/i);
  if (!match) {
    result.error = `Format UWP invalide : "${uwp}". Attendu : SAAHPGL-T (ex. A788899-C)`;
    return result;
  }

  result.starport      = match[1];
  result.size          = uwpCharToInt(match[2]);
  result.atmosphere    = uwpCharToInt(match[3]);
  result.hydrographics = uwpCharToInt(match[4]);
  result.population    = uwpCharToInt(match[5]);
  result.government    = uwpCharToInt(match[6]);
  result.lawLevel      = uwpCharToInt(match[7]);
  result.techLevel     = match[8] ? uwpCharToInt(match[8]) : 0;
  result.valid         = true;

  result.tradeCodes = deriveTradeCodes(result);
  return result;
}

/**
 * Dérive les codes commerciaux d'un monde à partir de ses attributs UWP.
 * @param {object} w  Objet retourné par parseUWP
 * @returns {string[]}
 */
export function deriveTradeCodes(w) {
  const codes = [];

  // Ag – Agricole : Atm 4–9, Hyd 4–8, Pop 5–7
  if (w.atmosphere >= 4 && w.atmosphere <= 9 &&
      w.hydrographics >= 4 && w.hydrographics <= 8 &&
      w.population >= 5 && w.population <= 7) {
    codes.push('Ag');
  }

  // As – Astéroïdes : Taille 0, Atm 0, Hyd 0
  if (w.size === 0 && w.atmosphere === 0 && w.hydrographics === 0) {
    codes.push('As');
  }

  // Ba – Stérile : Pop 0, Gov 0, Loi 0
  if (w.population === 0 && w.government === 0 && w.lawLevel === 0) {
    codes.push('Ba');
  }

  // De – Désert : Atm 2+, Hyd 0
  if (w.atmosphere >= 2 && w.hydrographics === 0) {
    codes.push('De');
  }

  // Fl – Océans fluides : Atm A (10)+, Hyd 1+
  if (w.atmosphere >= 10 && w.hydrographics >= 1) {
    codes.push('Fl');
  }

  // Ga – Jardin : Taille 6–8, Atm 5 ou 6 ou 8, Hyd 5–7
  if (w.size >= 6 && w.size <= 8 &&
      [5, 6, 8].includes(w.atmosphere) &&
      w.hydrographics >= 5 && w.hydrographics <= 7) {
    codes.push('Ga');
  }

  // Hi – Pop. élevée : Pop A (10)+
  if (w.population >= 10) {
    codes.push('Hi');
  }

  // Ht – Haute tech : TL C (12)+
  if (w.techLevel >= 12) {
    codes.push('Ht');
  }

  // IC – Calotte glaciaire : Atm 0–1, Hyd 1+
  if (w.atmosphere <= 1 && w.hydrographics >= 1) {
    codes.push('IC');
  }

  // In – Industriel : Atm ∈ {0,1,2,4,7,9}, Pop 9+
  if ([0, 1, 2, 4, 7, 9].includes(w.atmosphere) && w.population >= 9) {
    codes.push('In');
  }

  // Lo – Pop. basse : Pop 1–3
  if (w.population >= 1 && w.population <= 3) {
    codes.push('Lo');
  }

  // Lt – Basse tech : TL ≤ 5
  if (w.techLevel <= 5) {
    codes.push('Lt');
  }

  // Na – Non-Agricole : Atm 0–3, Hyd 0–3, Pop 6+
  if (w.atmosphere <= 3 && w.hydrographics <= 3 && w.population >= 6) {
    codes.push('Na');
  }

  // Ni – Non-Industriel : Pop 4–6
  if (w.population >= 4 && w.population <= 6) {
    codes.push('Ni');
  }

  // Po – Pauvre : Atm 2–5, Hyd 0–3
  if (w.atmosphere >= 2 && w.atmosphere <= 5 && w.hydrographics <= 3) {
    codes.push('Po');
  }

  // Ri – Riche : Gov ∈ {4,5,6,10}, Pop 6–8, Atm ∈ {6,8}
  if ([4, 5, 6, 10].includes(w.government) &&
      w.population >= 6 && w.population <= 8 &&
      [6, 8].includes(w.atmosphere)) {
    codes.push('Ri');
  }

  // Wa – Monde aquatique : Hyd A (10)
  if (w.hydrographics === 10) {
    codes.push('Wa');
  }

  // Va – Vide : Atm 0
  if (w.atmosphere === 0) {
    codes.push('Va');
  }

  return codes;
}

/**
 * Retourne le modificateur d'astroport pour les tables de trafic.
 * @param {string} starport  'A'|'B'|'C'|'D'|'E'|'X'
 * @param {string} table     'passenger'|'cargo'|'supplier'
 * @returns {number}
 */
export function starportModifier(starport, table = 'passenger') {
  if (table === 'supplier') {
    return { A: 6, B: 4, C: 2, D: 0, E: 0, X: 0 }[starport] ?? 0;
  }
  // passenger & cargo
  return { A: 2, B: 1, C: 0, D: 0, E: -1, X: -3 }[starport] ?? 0;
}

/**
 * Retourne le modificateur de population pour les tables de trafic.
 * @param {number} pop  Valeur numérique de la population
 * @param {string} table 'passenger'|'cargo'
 * @returns {number}
 */
export function populationModifier(pop, table = 'passenger') {
  if (table === 'cargo') {
    if (pop <= 1) return -4;
    if (pop >= 6 && pop <= 7) return 2;
    if (pop >= 8) return 4;
    return 0;
  }
  // passenger
  if (pop <= 1) return -4;
  if (pop >= 6 && pop <= 7) return 1;
  if (pop >= 8) return 3;
  return 0;
}

/**
 * Retourne le modificateur de zone (Ambre/Rouge/Normal) pour les tables de trafic.
 * @param {string} zone  'normal'|'amber'|'red'
 * @param {string} table 'passenger'|'cargo'
 * @returns {number}
 */
export function zoneModifier(zone, table = 'passenger') {
  if (table === 'cargo') {
    return { normal: 0, amber: -2, red: -6 }[zone] ?? 0;
  }
  return { normal: 0, amber: 1, red: -4 }[zone] ?? 0;
}
