<?php
/**
 * Slice 8Z-y · Services Scope Configuration smoke test.
 * Runs against project 634 / contract 12 (Vodacom PM sample).
 */
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', dirname(__DIR__));
require_once ROOT . DS . 'config' . DS . 'config.php';
require_once ROOT . DS . 'core' . DS . 'Application.php';
require_once ROOT . DS . 'core' . DS . 'Model.php';
require_once ROOT . DS . 'core' . DS . 'DB.php';
foreach (['ServiceContracts.php','ServiceContractTemplateBindings.php','ServiceContractPacks.php','ServiceTemplatesCatalog.php'] as $m) {
    require_once ROOT . DS . 'app' . DS . 'models' . DS . $m;
}

function ok(bool $c, string $m): void { echo ($c ? "  ✓ " : "  ✗ ") . $m . "\n"; }
function h(string $t): void { echo "\n==== $t ====\n"; }

$db  = new DB();
$sc  = new ServiceContracts();
$bnd = new ServiceContractTemplateBindings();
$pk  = new ServiceContractPacks();

$cid = 12;
$c   = $sc->find($cid);
if (empty($c)) { echo "✗ service_contract 12 not found\n"; exit(1); }

/* Cleanup */
$db->insertUpdate("DELETE FROM service_contract_template_bindings WHERE contract_id = :c", [':c' => $cid]);
$db->insertUpdate("DELETE si FROM service_contract_pack_items si JOIN service_contract_packs p ON p.c0d = si.pack_id WHERE p.contract_id = :c", [':c' => $cid]);
$db->insertUpdate("DELETE FROM service_contract_packs WHERE contract_id = :c", [':c' => $cid]);
$db->insertUpdate("UPDATE service_contracts SET sites_target_confirmed = NULL, equipment_scope_confirmed_json = NULL, scope_confirmed_on = NULL WHERE c0d = :id", [':id' => $cid]);

/* ── Y-A · Confirm scope ─────────────────────────────────────────── */
h('1. Y-A · Confirm scope');
$sc->saveScopeConfirmation($cid, [
    'sites_target'   => 50,
    'equipment_json' => [
        ['type' => 'GEN', 'size' => '20-40 kVA',  'count' => 30],
        ['type' => 'GEN', 'size' => '60-100 kVA', 'count' => 20],
        ['type' => 'AC',  'size' => '18000 BTU',  'count' => 100],
        ['type' => 'UPS', 'size' => '6 kVA',      'count' => 50],
    ],
], 999, 'Smoke PM');
$c2 = $sc->find($cid);
ok((int)$c2['sites_target_confirmed'] === 50,                              'sites_target_confirmed = 50');
ok(!empty($c2['equipment_scope_confirmed_json']),                          'equipment_scope_confirmed_json set');
ok(!empty($c2['scope_confirmed_on']),                                      'scope_confirmed_on stamped');
$decoded = json_decode((string)$c2['equipment_scope_confirmed_json'], true);
ok(is_array($decoded) && count($decoded) === 4,                            '4 equipment rows persisted');
ok((int)$decoded[0]['count'] === 30 && (string)$decoded[0]['type'] === 'GEN', 'first row = GEN 20-40 kVA × 30');

/* ── Y-B · Template bindings ─────────────────────────────────────── */
h('2. Y-B · Bindings + auto-suggest');
$res = $bnd->suggestDefaults($cid, 'GEN 20-40 kVA', 30, 999);
ok($res['ok'] === true,                                                    'suggestDefaults returned ok');
ok($res['added'] > 0,                                                      "added {$res['added']} template bindings for GEN class");
ok(in_array('GEN', $res['scopes']) && in_array('SITE', $res['scopes']),    'scopes include GEN + SITE');

$before = count($bnd->listFor($cid));
// Re-run — should skip duplicates
$res2 = $bnd->suggestDefaults($cid, 'GEN 20-40 kVA', 30, 999);
ok($res2['added'] === 0,                                                   'second run adds nothing (dedup)');
ok($res2['skipped'] > 0,                                                   'reports skipped duplicates');
$after = count($bnd->listFor($cid));
ok($after === $before,                                                     'no duplicate bindings created');

// Bind AC-QTR to AC class
$res3 = $bnd->suggestDefaults($cid, 'AC 18000 BTU', 100, 999);
ok($res3['added'] > 0,                                                     "AC class got {$res3['added']} binding(s)");

$listAll = $bnd->listFor($cid);
$acBindings = array_filter($listAll, fn($b) => (string)$b['equipment_class'] === 'AC 18000 BTU');
$hasAcQtr = false;
foreach ($acBindings as $b) if ((string)$b['slug'] === 'AC-QTR') { $hasAcQtr = true; break; }
ok($hasAcQtr,                                                              'AC-QTR bound to AC 18000 BTU');

// Manual binding save + remove
$catRs = $db->mySelect("SELECT c0d FROM service_templates_catalog WHERE slug = 'SHELTER-ANNUAL' LIMIT 1", []);
$sheltId = (int)($catRs[0]['c0d'] ?? 0);
$manualRes = $bnd->save($cid, [
    'equipment_class' => 'Shelter',
    'equipment_qty'   => 50,
    'template_id'     => $sheltId,
    'notes'           => 'One per site',
], 999);
ok($manualRes['ok'] === true,                                              'manual binding save ok');
ok(($manualRes['id'] ?? 0) > 0,                                            'new binding id returned');

$bnd->remove((int)$manualRes['id']);
$after2 = $bnd->listFor($cid);
$stillThere = false;
foreach ($after2 as $b) if ((int)$b['c0d'] === (int)$manualRes['id']) { $stillThere = true; break; }
ok(!$stillThere,                                                           'binding removed cleanly');

/* ── Y-C · Spare part packs ──────────────────────────────────────── */
h('3. Y-C · Packs + items');
$packRes = $pk->save($cid, [
    'name'                 => 'Genset PM 250h kit',
    'code'                 => 'GEN-250',
    'supply_model'         => 'CLIENT',
    'linked_template_slug' => 'GEN-SVC-250',
    'notes'                => 'Client-supplied per Vodacom pack agreement',
], 999);
ok($packRes['ok'] === true,                                                'pack header saved');
$packId = (int)($packRes['id'] ?? 0);
ok($packId > 0,                                                            "pack id = {$packId}");

$items = [
    ['interval_label' => 'Per visit', 'item_name' => 'Engine oil (SAE 15W-40)', 'qty' => 30,    'uom' => 'L'],
    ['interval_label' => 'Per visit', 'item_name' => 'Oil filter',              'qty' => 1,     'uom' => 'ea'],
    ['interval_label' => 'Per visit', 'item_name' => 'Air filter',              'qty' => 1,     'uom' => 'ea'],
    ['interval_label' => 'Per visit', 'item_name' => 'Fuel filter',             'qty' => 1,     'uom' => 'ea'],
];
foreach ($items as $it) $pk->itemSave($packId, $it);
$packs = $pk->listFor($cid);
$myPack = null;
foreach ($packs as $p) if ((int)$p['c0d'] === $packId) { $myPack = $p; break; }
ok($myPack !== null,                                                       'pack appears in listFor');
ok(count($myPack['items']) === 4,                                          "pack has 4 items");
ok((float)$myPack['items'][0]['qty'] === 30.0,                             'first item qty = 30');
ok((string)$myPack['items'][0]['uom'] === 'L',                             'first item uom = L');

// Edit an item
$firstItemId = (int)$myPack['items'][0]['c0d'];
$pk->itemSave($packId, ['c0d' => $firstItemId, 'item_name' => 'Engine oil (SAE 15W-40) · Shell Rimula', 'qty' => 32, 'uom' => 'L']);
$packs2 = $pk->listFor($cid);
foreach ($packs2 as $p) if ((int)$p['c0d'] === $packId) $myPack2 = $p;
$firstItem = null; foreach ($myPack2['items'] as $it) if ((int)$it['c0d'] === $firstItemId) $firstItem = $it;
ok((float)$firstItem['qty'] === 32.0,                                      'item qty updated to 32');
ok(strpos((string)$firstItem['item_name'], 'Shell') !== false,             'item name updated');

// Remove an item
$pk->itemRemove((int)$myPack['items'][3]['c0d']);
$packs3 = $pk->listFor($cid);
foreach ($packs3 as $p) if ((int)$p['c0d'] === $packId) $myPack3 = $p;
ok(count($myPack3['items']) === 3,                                         'item removed (3 left)');

// Soft-delete the pack
$pk->remove($packId);
$packs4 = $pk->listFor($cid);
$stillThere = false;
foreach ($packs4 as $p) if ((int)$p['c0d'] === $packId) $stillThere = true;
ok(!$stillThere,                                                           'pack removed from listFor');

/* Cleanup */
$db->insertUpdate("DELETE FROM service_contract_template_bindings WHERE contract_id = :c", [':c' => $cid]);
$db->insertUpdate("DELETE si FROM service_contract_pack_items si JOIN service_contract_packs p ON p.c0d = si.pack_id WHERE p.contract_id = :c", [':c' => $cid]);
$db->insertUpdate("DELETE FROM service_contract_packs WHERE contract_id = :c", [':c' => $cid]);
$db->insertUpdate("UPDATE service_contracts SET sites_target_confirmed = NULL, equipment_scope_confirmed_json = NULL, scope_confirmed_on = NULL, scope_confirmed_by = NULL, scope_confirmed_by_name = NULL WHERE c0d = :id", [':id' => $cid]);

echo "\n=== DONE (state restored) ===\n";
