/* ============================================================
   CPU OPPONENT — pure beslislogica (geen React/state).
   App drijft dit aan met visuele vertragingen; hier alleen
   "gegeven de wereld, wat zou de computer doen".
   ============================================================ */

// dichtstbijzijnde vijand (schip of squadron) t.o.v. een unit
function cpuNearest(unit, foes) {
  let best = null, bd = Infinity;
  foes.forEach((f) => { const d = worldDist(unit, f); if (d < bd) { bd = d; best = f; } });
  return best;
}

// ---- command-fase: welke dials plant de CPU voor een schip ----
function cpuPlanCommands(ship, need, enemies) {
  const out = [];
  const nearest = cpuNearest(ship, enemies);
  const dist = nearest ? worldDist(ship, nearest) : Infinity;
  const shieldsLow = ARCS.reduce((n, a) => n + (ship.maxShields[a] - ship.shields[a]), 0) >= 2;
  const hurt = ship.hull < ship.maxHull || shieldsLow;
  for (let i = 0; i < need; i++) {
    if (i === 0 && hurt && dist <= RANGE_DIST.medium) out.push("repair");
    else if (dist > RANGE_DIST.close) out.push("navigate");   // dichterbij komen
    else out.push("cf");                                        // in gevecht: extra vuurkracht
  }
  return out;
}

// ---- ship-fase: kies welk eigen schip als eerste activeert ----
// hoeveel dice kan `s` maximaal op `t` gooien, over alle arcs die `t` legaal zien?
function cpuBestArcDice(s, t, range) {
  return firingArcsAgainst(s, t, BASE_SIZES)
    .reduce((n, arc) => Math.max(n, poolSize(gatherArcDice(s, arc, range))), 0);
}

// voorkeur: schip dat al kan schieten, anders dat het dichtst bij een vijand staat
function cpuPickShip(mine, enemies) {
  let best = mine[0], bestScore = -Infinity;
  mine.forEach((s) => {
    const t = cpuNearest(s, enemies);
    if (!t) return;
    const r = rangeBetween(s, t);
    const canShoot = r && cpuBestArcDice(s, t, r) > 0;
    const score = (canShoot ? 1000 : 0) - worldDist(s, t) * 0.01;
    if (score > bestScore) { bestScore = score; best = s; }
  });
  return best;
}

// ---- ship-fase: beste manoeuvre (yaw + snelheid) om te kunnen vuren / dichterbij ----
function cpuPlanShipMove(ship, enemies, nav) {
  const target = cpuNearest(ship, enemies);
  const base = { yaw: [0, 0, 0, 0], speedDelta: 0, end: { x: ship.x, y: ship.y, facing: ship.facing }, score: -Infinity };
  if (!target) return base;
  const deltas = nav ? [-1, 0, 1] : [0];
  const yawOpts = [-2, -1, 0, 1, 2];
  let best = base;
  deltas.forEach((sd) => {
    const sp = ship.speed + sd;
    if (sp < 0 || sp > 4) return;
    yawOpts.forEach((y) => {
      const yaw = [y, y, y, y];
      const m = computeManeuver(ship, yaw, sd);
      const end = m.end;
      const endShip = { ...ship, x: end.x, y: end.y, facing: end.facing };
      const r = rangeBetween(endShip, target);
      const dice = r ? cpuBestArcDice(endShip, target, r) : 0;
      let score = -worldDist(end, target) * 0.02;
      if (r && dice > 0) score += 60 + dice * 4 + (r === "close" ? 18 : r === "medium" ? 9 : 0);
      if (score > best.score) best = { yaw, speedDelta: sd, end, score };
    });
  });
  return best;
}

// ---- ship-fase: beste (arc,doel) voor één aanval, arcs uit `firedArcs` uitgesloten ----
function cpuBestAttack(ship, enemies, firedArcs) {
  let best = null, bestScore = -Infinity;
  ARCS.forEach((arc) => {
    if (firedArcs.includes(arc)) return;
    if (poolSize(ship.attackDice[arc]) === 0) return;
    enemies.forEach((e) => {
      if (e.destroyed) return;
      const r = rangeBetween(ship, e);
      if (!r) return;
      // legaliteit vanaf de fysieke hull-zone-rand — dezelfde regel als voor de mens
      const zones = targetableZones(ship, arc, e, BASE_SIZES);
      // same-hull-zone-regel: niet twee keer dezelfde vijandelijke hull zone deze activatie
      const used = ship.attackedZones || [];
      const free = upgradeAllowsSameZone(ship) ? zones : zones.filter((z) => !used.includes(e.id + ":" + z));
      if (!free.length) return;
      const dice = poolSize(gatherArcDice(ship, arc, r));
      if (dice === 0) return;
      // mik op de zwakste van de legale zones (minste schilden), bij gelijke stand de dichtstbijzijnde
      const zone = free.reduce((bz, z) => (e.shields[z] < e.shields[bz] ? z : bz), nearestZone(ship, e, free, BASE_SIZES));
      const score = dice * 10 + (r === "close" ? 6 : r === "medium" ? 3 : 0) - e.hull * 0.5;
      if (score > bestScore) { bestScore = score; best = { arc, target: e, range: r, hitZone: zone }; }
    });
  });
  return best;
}

// resolve een CPU-aanval headless (geen defense-token-UI): rol dice, pas schade toe
function cpuResolveAttack(attacker, target, arc, range, hitZone) {
  const pool = gatherArcDice(attacker, arc, range);
  if (attacker.revealedDial === "cf") {
    const c = DICE_ORDER.find((col) => pool[col] > 0 && dieAllowed(col, range));
    if (c) pool[c] += 1;
  }
  const dice = rollPool(pool);
  const tally = dice.reduce((a, d) => { const v = FACE_VALUE[d.face]; a.dmg += v.dmg; a.crit += v.crit; return a; }, { dmg: 0, crit: 0 });
  const hitArc = hitZone || nearestZone(attacker, target, targetableZones(attacker, arc, target, BASE_SIZES), BASE_SIZES) || "front";
  const res = resolveDamage(target, hitArc, tally.dmg, null);
  return { hitArc, dmg: tally.dmg, crit: tally.crit, shields: res.shields, hull: res.hull, destroyed: res.destroyed };
}

// squadron-worp → schade-tally
function cpuRollSquadron(pool) {
  const dice = rollPool(pool);
  return dice.reduce((a, d) => { const v = FACE_VALUE[d.face]; a.dmg += v.dmg; a.crit += v.crit; return a; }, { dmg: 0, crit: 0 });
}

Object.assign(window, {
  cpuNearest, cpuPlanCommands, cpuPickShip, cpuPlanShipMove,
  cpuBestAttack, cpuResolveAttack, cpuRollSquadron,
});
