#!/usr/bin/env bash
# ============================================================================
# TC-06 — Acteur Commerce
# Usage: ./tc-06-acteur-commerce.sh [--navigate]
#   --navigate : force navigation + login
#   Env: URL, PASS (admin password)
#
# Atomic single evaluate_script: no cross-call races.
# ============================================================================
set -uo pipefail

URL="${URL:-https://localhost:31000}"
PASS="${PASS:-}"
NAVIGATE="${1:-}"
PASSED=0; FAILED=0

die()    { echo "  ✖ $*"; exit 1; }
pass()   { echo "  ✔ $1"; PASSED=$((PASSED+1)); }
fail()   { echo "  ✘ $1"; FAILED=$((FAILED+1)); }

jse_get() { chrome-devtools evaluate_script "() => $1" 2>/dev/null | sed -n '/^```json$/{n;p;}'; }

jse_wait_ready() {
	local t="${1:-60}" p="${2:-1000}"
	chrome-devtools evaluate_script "async () => {
		for(let i=0;i<$t*1000/$p;i++){ if(typeof game!=='undefined'&&game.ready) return 'ready'; await new Promise(r=>setTimeout(r,$p)); }
		return 'timeout';
	}" 2>/dev/null | sed -n '/^```json$/{n;p;}' | tr -d '"\n'
}

echo ""
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║   TC-06 — Acteur Commerce                                  ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""

R=$(jse_wait_ready 15 2)
if [ "$R" != "ready" ] && [ "$NAVIGATE" = "--navigate" ]; then
	[ -z "$PASS" ] && die "PASS=..."
	echo "→ Navigating ..."
	chrome-devtools new_page "$URL" --background false --timeout 15000 --isolatedContext "rdd-tc06" >/dev/null 2>&1; sleep 3
	PW=$(jse_get "window.location.pathname" | tr -d '"\n')
	case "$PW" in
		*/join) chrome-devtools evaluate_script "() => {
			const s=document.querySelector('select[name=userid]'); if(s){ const o=Array.from(s.options); const g=o.find(x=>x.text==='Gamemaster'); const p=g||o.find(x=>x.value&&!x.disabled)||o.find(x=>x.value); if(p) s.value=p.value; }
			const a=document.querySelector('input[name=adminPassword]'); if(a) a.value='$PASS';
			const b=document.querySelector('button[name=join]'); if(b) b.click();
		}" >/dev/null 2>&1 || true ;;
		*/setup) chrome-devtools evaluate_script "() => {
			document.querySelectorAll('[data-action=worldLaunch]').forEach(l=>{ const li=l.closest('li.package.world'); if(li&&li.querySelector('.package-title')?.textContent==='Reve de Dragon') l.click(); });
		}" >/dev/null 2>&1 || true ;;
		*/auth) chrome-devtools evaluate_script "() => {
			const i=document.querySelector('input[type=password]'); if(i) i.value='$PASS';
			const b=document.querySelector('form button,button[type=submit]'); if(b) b.click();
		}" >/dev/null 2>&1 || true ;;
	esac
	echo "→ Waiting..."; R=$(jse_wait_ready 60 2)
fi

[ "$R" != "ready" ] && die "Game not ready"
echo "  ✓ Game ready"; echo ""

# ============================================================================
# Single atomic evaluate_script: all sections in one call
# ============================================================================
RESULT=$(chrome-devtools evaluate_script "async () => {
  if (typeof game === 'undefined' || !game.ready) return {error: 'NOT_READY'};
  const out = {};

  // ==============================
  // Cleanup any previous TC-06 actors
  // ==============================
  for (const n of ['TC-06 Marchand', 'TC-06 Acheteur']) {
    const a = game.actors.getName(n);
    if (a) await a.delete();
  }

  // ==============================
  // TC-06-001: Commerce creation
  // ==============================
  try {
    const [actor] = await Actor.createDocuments([{type: 'commerce', name: 'TC-06 Marchand'}]);
    await actor.createEmbeddedDocuments('Item', [
      {name: 'Denier (etain)', type: 'monnaie', system: {cout: 0.01, quantite: 0}},
      {name: 'Sou (bronze)', type: 'monnaie', system: {cout: 0.05, quantite: 0}},
      {name: 'Sol (argent)', type: 'monnaie', system: {cout: 1, quantite: 0}},
      {name: 'Dragon (or)', type: 'monnaie', system: {cout: 240, quantite: 10}}
    ]);
    const sheet = await actor.sheet.render(true);
    await new Promise(r => setTimeout(r, 800));
    out.sheetName = sheet.constructor.name;
    await sheet.close();
    out.monnaieCount = actor.items.filter(i => i.type === 'monnaie').length;
    out.pourcentage = actor.system.pourcentage;
    out.c001_1 = (out.sheetName === 'RdDCommerceSheetV2');
    out.c001_2 = (out.monnaieCount >= 4);
    out.c001_3 = (out.pourcentage === 100);
    out.commerceId = actor.id;
  } catch(e) { out.c001_error = e?.message || String(e); }

  // ==============================
  // TC-06-002: Purchase simulation
  // ==============================
  try {
    const commerce = game.actors.get(out.commerceId);
    if (!commerce) { out.c002_error = 'Commerce not found'; }
    else {
      const [item] = await commerce.createEmbeddedDocuments('Item', [{
        name: 'Epee longue', type: 'objet',
        system: { cout: 50, quantite: 3, encombrement: 2 }
      }]);
      out.prixCalcule = commerce.calculerPrix(item);
      out.quantiteDispo = commerce.getQuantiteDisponible(item);

      const [buyer] = await Actor.createDocuments([{type: 'personnage', name: 'TC-06 Acheteur'}]);
      await buyer.createEmbeddedDocuments('Item', [{
        name: 'Dragon (or)', type: 'monnaie', system: { cout: 240, quantite: 5 }
      }]);

      out.peutPayer = buyer.verifierFortune(out.prixCalcule);
      const reste = await buyer.depenserSols(out.prixCalcule);
      out.resteApres = reste;
      out.c002_payeurResteOk = (reste >= 0);

      await commerce.ajouterSols(out.prixCalcule);
      await commerce.decrementerQuantiteItem(item.id, 1);
      await buyer.createEmbeddedDocuments('Item', [{
        name: item.name, type: item.type,
        system: { cout: item.system.cout, quantite: 1, encombrement: item.system.encombrement }
      }]);

      out.itemTransfere = buyer.items.filter(i => i.name === 'Epee longue').length > 0;
      out.c002_1 = (out.prixCalcule === 50);
      out.c002_2 = (out.quantiteDispo === 3);
      out.c002_3 = (out.peutPayer === true);
      out.c002_4 = (out.c002_payeurResteOk === true);
      out.c002_5 = (!(reste >= 0) || (item.system.cout === 50 && out.c002_payeurResteOk));
      out.c002_6 = (out.itemTransfere === true);
    }
  } catch(e) { out.c002_error = e?.message || String(e); }

  // ==============================
  // TC-06-003: Sell simulation
  // ==============================
  try {
    const commerce = game.actors.getName('TC-06 Marchand');
    const buyer = game.actors.getName('TC-06 Acheteur');
    if (!commerce || !buyer) { out.c003_error = 'actors not found for TC-06-003'; }
    else {
      const [item] = await buyer.createEmbeddedDocuments('Item', [{
        name: 'Potion de soin', type: 'potion',
        system: { cout: 30, quantite: 2, encombrement: 1 }
      }]);
      out.prixItem = item.calculerPrixCommercant();
      out.prixVente = Math.floor(out.prixItem / 2);
      out.commerceSuffisant = commerce.verifierFortune(out.prixVente);
      const fortuneVendeurAvant = buyer.getFortune();
      const depenseOk = await commerce.depenserSols(out.prixVente);
      await buyer.ajouterSols(out.prixVente);
      const fortuneVendeurApres = buyer.getFortune();
      out.gainReel = fortuneVendeurApres - fortuneVendeurAvant;

      out.c003_1 = (typeof out.prixItem === 'number' && out.prixItem > 0);
      out.c003_2 = (typeof out.prixVente === 'number' && out.prixVente > 0);
      out.c003_3 = (out.commerceSuffisant === true);
      out.c003_4 = (out.gainReel === out.prixVente);
    }
  } catch(e) { out.c003_error = e?.message || String(e); }

  // ==============================
  // Cleanup
  // ==============================
  for (const n of ['TC-06 Marchand', 'TC-06 Acheteur']) {
    const a = game.actors.getName(n);
    if (a) await a.delete();
  }
  out.cleaned = true;

  return out;
}" 2>/dev/null | sed -n '/^```json$/{n;p;}')

[ -z "$RESULT" ] && die "Empty result"
eval_ok() { echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$1',''))" 2>/dev/null; }

echo "--- TC-06-001: Commerce creation + sheet ---"
[ "$(eval_ok c001_1)" = "True" ] && pass "TC-06-001a: Sheet $(eval_ok sheetName)" || fail "TC-06-001a: Sheet = $(eval_ok sheetName) (expected RdDCommerceSheetV2)"
[ "$(eval_ok c001_2)" = "True" ] && pass "TC-06-001b: $(eval_ok monnaieCount) monnaies" || fail "TC-06-001b: monnaies = $(eval_ok monnaieCount) (expected ≥4)"
[ "$(eval_ok c001_3)" = "True" ] && pass "TC-06-001c: pourcentage = $(eval_ok pourcentage)" || fail "TC-06-001c: pourcentage = $(eval_ok pourcentage)"
[ -n "$(eval_ok c001_error)" ] && fail "TC-06-001: $(eval_ok c001_error)"

echo ""
echo "--- TC-06-002: Achat (simulation) ---"
[ "$(eval_ok c002_1)" = "True" ] && pass "TC-06-002a: prix = $(eval_ok prixCalcule) sols" || fail "TC-06-002a: prix = $(eval_ok prixCalcule)"
[ "$(eval_ok c002_2)" = "True" ] && pass "TC-06-002b: quantite = $(eval_ok quantiteDispo)" || fail "TC-06-002b: quantite = $(eval_ok quantiteDispo)"
[ "$(eval_ok c002_3)" = "True" ] && pass "TC-06-002c: peut payer $(eval_ok prixCalcule) sols" || fail "TC-06-002c: verifierFortune = $(eval_ok peutPayer)"
[ "$(eval_ok c002_4)" = "True" ] && pass "TC-06-002d: depenserSols (reste=$(eval_ok resteApres))" || fail "TC-06-002d: depenserSols returned $(eval_ok resteApres)"
[ "$(eval_ok c002_6)" = "True" ] && pass "TC-06-002e: item transfere" || fail "TC-06-002e: item transfere = $(eval_ok itemTransfere)"
[ -n "$(eval_ok c002_error)" ] && fail "TC-06-002: $(eval_ok c002_error)"

echo ""
echo "--- TC-06-003: Vente (simulation) ---"
[ "$(eval_ok c003_1)" = "True" ] && pass "TC-06-003a: prix item = $(eval_ok prixItem) sols" || fail "TC-06-003a: prix item = $(eval_ok prixItem)"
[ "$(eval_ok c003_2)" = "True" ] && pass "TC-06-003b: prix vente = $(eval_ok prixVente) sols" || fail "TC-06-003b: prix vente = $(eval_ok prixVente)"
[ "$(eval_ok c003_3)" = "True" ] && pass "TC-06-003c: commerce peut payer $(eval_ok prixVente)" || fail "TC-06-003c: commerceSuffisant = $(eval_ok commerceSuffisant)"
GE=$(eval_ok gainReel); PV=$(eval_ok prixVente)
[ -n "$GE" ] && [ "$GE" -ge "$PV" ] 2>/dev/null && pass "TC-06-003d: vendeur recoit $GE sols (prix vente $PV)" || fail "TC-06-003d: gain = $GE (expected >= $PV)"
[ -n "$(eval_ok c003_error)" ] && fail "TC-06-003: $(eval_ok c003_error)"

echo ""
echo "--- Cleanup ---"
[ "$(eval_ok cleaned)" = "True" ] && pass "Cleanup: done" || fail "Cleanup: not run"

echo ""
echo "--- Console errors ---"
ERRS=$(chrome-devtools list_console_messages --types error 2>/dev/null | grep -c '^msgid=' || true)
[ "$ERRS" -le 5 ] 2>/dev/null && pass "Console errors ≤5 ($ERRS)" || fail "Console errors: $ERRS"

TOTAL=$((PASSED + FAILED))
echo ""
echo "╔══════════════════════════════════════════════════════════════╗"
printf "║   %2d / %2d passed, %2d failed                              ║\n" "$PASSED" "$TOTAL" "$FAILED"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""
[ "$FAILED" -gt 0 ] && exit 1 || exit 0
