<?php
/**
 * Slice 8N-PricingMode · PER_ITEM vs LUMPSUM.
 *
 *  1) Schema: pricing_mode ENUM + lumpsum_amount + lumpsum_notes columns exist
 *  2) Fresh draft defaults to PER_ITEM with lumpsum_amount = 0
 *  3) updateVersionHeader accepts pricing_mode + lumpsum_amount + lumpsum_notes
 *  4) updateVersionHeader coerces bad pricing_mode back to PER_ITEM
 *  5) rollupVersion in PER_ITEM = SUM(lines) + prelims (unchanged behaviour)
 *  6) rollupVersion in LUMPSUM = lumpsum_amount (buyer sees one number)
 *  7) sum_cost still tracks internal breakdown in LUMPSUM (needed for margin)
 *  8) Toggling PER_ITEM → LUMPSUM flips sum_price without recomputing lines
 *  9) Toggling back LUMPSUM → PER_ITEM restores SUM(lines) + prelims
 * 10) View surface: mode toggle buttons + LUMPSUM notes field + Vue setMode method
 */
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';
$_SESSION = $_SESSION ?? [];
foreach (['Tenders.php','TenderPricing.php','TenderItems.php'] as $m) require_once ROOT . DS . 'app' . DS . 'models' . DS . $m;

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

$db = new DB();
$tp = new TenderPricing();
$ti = new TenderItems();
$uid = 133; $unm = 'Verify 8N';

/* ── 0. Anchor + purge ─────────────────────────────────────────────── */
h('0. Anchor tender + prep');
$row = $db->mySelect("SELECT c0d FROM tender_tracker WHERE deleted=0 ORDER BY c0d ASC LIMIT 1", []);
if (empty($row)) boom('no tender');
$tenderId = (int)$row[0]['c0d'];
p("anchor tender #$tenderId");

$db->insertUpdate("DELETE FROM tender_items WHERE tender_id = :t AND description LIKE '8N-VERIFY%'", [':t' => $tenderId]);

// Seed 2 items so we can build a small breakdown
$ti->add($tenderId, ['description' => '8N-VERIFY item alpha', 'qty' => 10, 'uom' => 'ea'], $uid, $unm);
$ti->add($tenderId, ['description' => '8N-VERIFY item beta',  'qty' =>  4, 'uom' => 'lot'], $uid, $unm);

/* ── 1. Schema ─────────────────────────────────────────────────────── */
h('1. Schema');
$cols = $db->mySelect("SHOW COLUMNS FROM tender_pricing_versions", []) ?: [];
$cn = array_column($cols, 'Field');
ok(in_array('pricing_mode', $cn, true),   'pricing_mode column present');
ok(in_array('lumpsum_amount', $cn, true), 'lumpsum_amount column present');
ok(in_array('lumpsum_notes',  $cn, true), 'lumpsum_notes column present');

/* ── 2. Fresh draft defaults ───────────────────────────────────────── */
h('2. Fresh draft defaults to PER_ITEM');
$existingDraft = $tp->activeDraft($tenderId);
$restoreDraftId = 0;
if ($existingDraft) {
    $restoreDraftId = (int)$existingDraft['c0d'];
    $db->insertUpdate("UPDATE tender_pricing_versions SET status='SUPERSEDED' WHERE c0d = :id", [':id' => $restoreDraftId]);
}
$vid = $tp->createVersion($tenderId, null, $uid, $unm);
$v = $tp->findVersion($vid);
ok(($v['pricing_mode'] ?? '') === 'PER_ITEM', 'default mode = PER_ITEM');
ok((float)($v['lumpsum_amount'] ?? 0) === 0.0, 'default lumpsum_amount = 0');

/* ── 3. updateVersionHeader accepts new fields ─────────────────────── */
h('3. updateVersionHeader accepts mode + lumpsum');
$tp->updateVersionHeader($vid, [
    'version_label' => 'v-8N', 'vat_pct' => 18, 'contingency_pct' => 0,
    'prelims_amount' => 5000, 'default_markup_pct' => 20,
    'pricing_mode' => 'LUMPSUM', 'lumpsum_amount' => 250000, 'lumpsum_notes' => 'All-in fixed price',
], $uid);
$v2 = $tp->findVersion($vid);
ok($v2['pricing_mode'] === 'LUMPSUM', 'mode saved as LUMPSUM');
ok((float)$v2['lumpsum_amount'] === 250000.0, 'lumpsum_amount saved (250000)');
ok((string)$v2['lumpsum_notes'] === 'All-in fixed price', 'lumpsum_notes saved');

/* ── 4. Bad mode is coerced to PER_ITEM ────────────────────────────── */
h('4. Bad mode → coerced to PER_ITEM');
$tp->updateVersionHeader($vid, ['pricing_mode' => 'GARBAGE', 'lumpsum_amount' => 250000], $uid);
$v3 = $tp->findVersion($vid);
ok($v3['pricing_mode'] === 'PER_ITEM', 'bad mode fell back to PER_ITEM');

/* ── 5. PER_ITEM rollup = SUM(lines) + prelims ─────────────────────── */
h('5. PER_ITEM rollup = SUM(lines) + prelims');
// Seed 2 lines: 10 x 100 (markup 20%) = 1000 cost, 1200 sell
//               4 x 500 (markup 20%) = 2000 cost, 2400 sell
// Prelims = 5000 → sum_cost = 3000, sum_price = 3600 + 5000 = 8600
$secId = $tp->addSection($vid, $tenderId, "Buyer's items", 'seeded', $uid);
$tp->addLine($secId, ['item_ref'=>'A','description'=>'a','qty'=>10,'unit_cost'=>100,'markup_pct'=>20], $uid);
$tp->addLine($secId, ['item_ref'=>'B','description'=>'b','qty'=>4, 'unit_cost'=>500,'markup_pct'=>20], $uid);
$vPI = $tp->findVersion($vid);
p("PER_ITEM: sum_cost={$vPI['sum_cost']} sum_price={$vPI['sum_price']}");
ok((float)$vPI['sum_cost'] === 3000.0, 'sum_cost = 3000');
ok((float)$vPI['sum_price'] === 8600.0, 'sum_price = 3600 lines + 5000 prelims = 8600');

/* ── 6. Toggle → LUMPSUM · sum_price flips to lumpsum_amount ───────── */
h('6. Toggle → LUMPSUM · sum_price = lumpsum_amount');
$tp->updateVersionHeader($vid, ['pricing_mode' => 'LUMPSUM', 'lumpsum_amount' => 12000], $uid);
$vLS = $tp->findVersion($vid);
p("LUMPSUM: sum_cost={$vLS['sum_cost']} sum_price={$vLS['sum_price']} lumpsum={$vLS['lumpsum_amount']}");
ok((float)$vLS['sum_price'] === 12000.0, 'sum_price = lumpsum_amount (12000)');

/* ── 7. sum_cost still tracks the breakdown in LUMPSUM ─────────────── */
h('7. sum_cost still tracks breakdown in LUMPSUM');
ok((float)$vLS['sum_cost'] === 3000.0, 'sum_cost unchanged (3000) — internal breakdown still tracked');
ok((float)$vLS['sum_margin'] === 9000.0, 'margin = 12000 − 3000 = 9000');

/* ── 8. Adding a line in LUMPSUM does NOT change sum_price ─────────── */
h('8. Adding a line in LUMPSUM does not change buyer-facing sum_price');
$tp->addLine($secId, ['item_ref'=>'C','description'=>'c','qty'=>1,'unit_cost'=>7777,'markup_pct'=>10], $uid);
$vLS2 = $tp->findVersion($vid);
ok((float)$vLS2['sum_price'] === 12000.0, 'sum_price still 12000 (line addition invisible to buyer)');
ok((float)$vLS2['sum_cost']  === 10777.0, 'sum_cost updated to 10777 (3000 + 7777 new line cost)');

/* ── 9. Toggle back to PER_ITEM ────────────────────────────────────── */
h('9. Toggle back → PER_ITEM · sum_price recomputes');
$tp->updateVersionHeader($vid, ['pricing_mode' => 'PER_ITEM'], $uid);
$vPI2 = $tp->findVersion($vid);
p("PER_ITEM again: sum_cost={$vPI2['sum_cost']} sum_price={$vPI2['sum_price']}");
// 3600 (a+b sell) + 8554.7 (c sell = 7777 * 1.1) + 5000 prelims = 17154.70
$expectedSell = round(3600 + (7777 * 1.10), 2) + 5000; // 17154.70
ok(abs((float)$vPI2['sum_price'] - $expectedSell) < 0.5, "sum_price ≈ $expectedSell (got {$vPI2['sum_price']})");

/* ── 10. View surface ──────────────────────────────────────────────── */
h('10. View surface');
$vBody = (string)file_get_contents(ROOT . DS . 'app' . DS . 'views' . DS . 'Tenders' . DS . 'view.php');
ok(strpos($vBody, "setMode('PER_ITEM')") !== false, 'view has PER_ITEM toggle button');
ok(strpos($vBody, "setMode('LUMPSUM')")  !== false, 'view has LUMPSUM toggle button');
ok(strpos($vBody, 'lumpsum_amount')      !== false, 'lumpsum_amount v-model present');
ok(strpos($vBody, 'lumpsum_notes')       !== false, 'lumpsum_notes v-model present');
ok(strpos($vBody, 'setMode: function')   !== false, 'setMode() method defined in Vue root');
ok(strpos($vBody, 'modeButtonStyle')     !== false, 'modeButtonStyle() defined');
ok(strpos($vBody, "'lumpsum'")           !== false, 'totals strip surfaces lumpsum label');

/* ── Z. Restore ────────────────────────────────────────────────────── */
h('Z. Restore');
$db->insertUpdate("UPDATE tender_pricing_versions SET deleted=1 WHERE c0d = :id", [':id' => $vid]);
if ($restoreDraftId > 0) $db->insertUpdate("UPDATE tender_pricing_versions SET status='DRAFT' WHERE c0d = :id", [':id' => $restoreDraftId]);
$db->insertUpdate("DELETE FROM tender_items WHERE tender_id = :t AND description LIKE '8N-VERIFY%'", [':t' => $tenderId]);
p('anchor state restored');

echo "\n=== END ===\n";
