#!/usr/bin/env bash
# ============================================================================
# TC-07 — Feuilles d'Item (44 types)
# Usage: ./tc-07-feuilles-item.sh [--navigate]
#   --navigate : force navigation + login
#   Env: URL, PASS (admin password)
# ============================================================================
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-07 — Feuilles d'Item (44 types)                       ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""

R=$(jse_wait_ready 15 2)
if [ "$R" != "ready" ] && [ "$NAVIGATE" = "--navigate" ]; then
	[ -z "$PASS" ] && die "PASS=..." 
	chrome-devtools new_page "$URL" --background false --timeout 15000 --isolatedContext "rdd-tc07" >/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 ;;
	esac
	R=$(jse_wait_ready 60 2)
fi

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

# ============================================================================
# Atomic test: all items in one evaluate_script
# ============================================================================
RESULT=$(chrome-devtools evaluate_script "async () => {
  if (typeof game === 'undefined' || !game.ready) return {error: 'NOT_READY'};
  const out = {};
  const ok = []; const fail = [];

  // Item types with dedicated sheets (from registerAll)
  const TYPES = [
    'arme', 'armure', 'blessure', 'casetmr', 'chant', 'competence',
    'competencecreature', 'conteneur', 'danse', 'empoignade', 'extraitpoetique',
    'faune', 'gemme', 'herbe', 'ingredient', 'jeu', 'livre', 'maladie',
    'meditation', 'monnaie', 'munition', 'musique', 'nombreastral',
    'nourritureboisson', 'objet', 'oeuvre', 'ombre', 'plante', 'poison',
    'possession', 'potion', 'queue', 'race', 'recettealchimique',
    'recettecuisine', 'rencontre', 'service', 'signedraconique', 'sort',
    'sortreserve', 'souffle', 'tache', 'tarot', 'tete'
  ];

  const MIN_TYPES = 15; // plan de test: 15 types principaux listes

  // Create a test actor for owner-bound items
  const [actor] = await Actor.createDocuments([{type: 'personnage', name: 'TC-07 Support'}]);
  out.actorCreated = !!actor;
  out.sheets = {};

  for (const type of TYPES) {
    try {
      const data = {type, name: 'TC-07 ' + type};
      // Add minimal system data for types that need it
      if (type === 'arme') data.system = {categorie: 'cac', degats: '1d6', mains: 1, encombrement: 2};
      if (type === 'armure') data.system = {protection: 5, encombrement: 3};
      if (type === 'competence') data.system = {categorie: 'physique', carac: 'force'};
      if (type === 'competencecreature') data.system = {categorie: 'naturelle', isnaturelle: true, dommages: 6};
      if (type === 'sort') data.system = {niveau: 1, voie: 'feu'};
      if (type === 'blessure') data.system = {gravite: 2};
      if (type === 'possession') data.system = {entiteid: 'test', victimeid: 'test'};

      // Create item (standalone or on actor depending on type)
      let item;
      const needsActor = ['blessure', 'possession', 'competencecreature'];
      if (needsActor.includes(type)) {
        [item] = await actor.createEmbeddedDocuments('Item', [data]);
      } else {
        item = await Item.create(data);
      }
      if (!item) { fail.push(type + ':null'); continue; }

      const sheet = await item.sheet.render(true);
      await new Promise(r => setTimeout(r, 500));

      const sn = sheet.constructor.name;
      const html = sheet.element;
      // Check scrollable: .sheet-body with overflow-y:auto is the scroll mechanism
      let scrollOk = false;
      if (html) {
        const sb = html.querySelector('.sheet-body');
        if (sb) {
          const cs = window.getComputedStyle(sb);
          scrollOk = cs.overflowY === 'auto' || cs.overflowY === 'scroll';
        }
        // Also check the content-area class uses the item-type-content pattern
        const wc = html.querySelector('.window-content');
        if (wc && wc.className.includes(type + '-content')) scrollOk = true;
      }

      await sheet.close();

      // Wait a tick after close
      await new Promise(r => setTimeout(r, 200));

      // Delete standalone items
      if (!needsActor.includes(type)) {
        await item.delete();
      }

      ok.push(type + ':' + sn + (scrollOk ? '+scroll' : ''));
      out.sheets[type] = {sheetName: sn, hasScrollableBody: scrollOk};
    } catch(e) {
      fail.push(type + ':' + (e?.message || String(e)).substring(0, 80));
    }
  }

  // Cleanup actor and its embedded items
  if (actor) await actor.delete();

  out.ok = ok;
  out.fail = fail;
  out.totalOk = ok.length;
  out.totalFail = fail.length;

  // TC-07-016: scroll test details
  out.scrollCount = Object.values(out.sheets).filter(s => s.hasScrollableBody).length;
  out.scrollableTypes = Object.entries(out.sheets).filter(([,s]) => s.hasScrollableBody).map(([t]) => t);

  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-07-001 a 015: Creation + ouverture feuilles ---"

OK_LIST=$(eval_ok ok)
FAIL_LIST=$(eval_ok fail)
TOTAL_OK=$(eval_ok totalOk)
TOTAL_FAIL=$(eval_ok totalFail)

[ "$TOTAL_OK" -ge 15 ] && pass "TC-07-001: $TOTAL_OK types cree + sheet ouverte (≥15 attendus)" || fail "TC-07-001: seulement $TOTAL_OK OK (attendu ≥15)"

# Print details
echo "$RESULT" | python3 -c "
import sys, json
d = json.load(sys.stdin)
sheets = d.get('sheets', {})
for t, info in sorted(sheets.items()):
    sn = info.get('sheetName', '?')
    sc = '📜' if info.get('hasScrollableBody') else ''
    print(f'       {t}: {sn} {sc}')
fails = d.get('fail', [])
for f in fails:
    print(f'       ✘ {f}')
" 2>/dev/null

echo ""
echo "--- TC-07-016: Scrollable body ---"

SCROLL_CNT=$(eval_ok scrollCount)
SCROLL_TYPES=$(eval_ok scrollableTypes)

[ "$SCROLL_CNT" -gt 0 ] 2>/dev/null && pass "TC-07-016: $SCROLL_CNT types avec .item-sheet-scrollable-body" || fail "TC-07-016: aucun scrollable"

echo ""
echo "--- Cleanup ---"
CLEANUP=$(chrome-devtools evaluate_script "async () => {
  const a = game.actors.getName('TC-07 Support');
  if (a) await a.delete();
  // Clean up any standalone items left
  const items = game.items.filter(i => i.name && i.name.startsWith('TC-07 '));
  for (const it of items) await it.delete();
  return 'ok';
}" 2>/dev/null | sed -n '/^```json$/{n;p;}' | tr -d '"\n')
[ "$CLEANUP" = "ok" ] && pass "Cleanup: done" || fail "Cleanup: $CLEANUP"

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
