<?php
/**
 * Slice 8O-ManualCostMargin · MANUAL bid source computes bid from cost + margin.
 *
 *  1) Schema: manual_cost + manual_margin_pct columns
 *  2) MANUAL + cost=1,000,000 + margin=20% → submission_amount = 1,200,000
 *  3) MANUAL + cost=0 does NOT overwrite an existing submission_amount (guard against blank cost wiping bid)
 *  4) PRICING_TAB source ignores manual_cost / manual_margin_pct entirely
 *  5) Both columns are persisted verbatim for audit even in PRICING_TAB mode
 *  6) Round-trip: post → find returns same numbers
 *  7) View surface: manual_cost + manual_margin_pct + manual_bid_preview inputs present
 *  8) View surface: applyManualBidVisibility + recomputeManualBid JS present
 *  9) POST payload wired: view POSTs manual_cost + manual_margin_pct
 * 10) Model: Tenders::saveSubmissionDetails accepts + computes
 */
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 ?? [];
require_once ROOT . DS . 'app' . DS . 'models' . DS . 'Tenders.php';

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();
$tm = new Tenders();
$uid = 144; $unm = 'Verify 8O';

/* ── 0. Anchor + snapshot ──────────────────────────────────────────── */
h('0. Anchor tender + snapshot for restore');
$row = $db->mySelect("SELECT c0d, submission_amount, submission_method, bid_price_source, manual_cost, manual_margin_pct, tender_stage FROM tender_tracker WHERE deleted=0 ORDER BY c0d ASC LIMIT 1", []);
if (empty($row)) boom('no tender');
$tid  = (int)$row[0]['c0d'];
$snap = $row[0];
p("anchor tender #$tid · current submission_amount = {$snap['submission_amount']}");

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

/* ── 2. MANUAL: cost 1,000,000 · margin 20% → bid 1,200,000 ────────── */
h('2. MANUAL + cost + margin → bid');
$tm->saveSubmissionDetails($tid, [
    'bid_price_source' => 'MANUAL',
    'manual_cost'      => 1000000,
    'manual_margin_pct'=> 20,
    // Even if submission_amount is posted, it should be overwritten by the computed value
    'submission_amount'=> 999999,
], $uid, $unm);
$r = $tm->find($tid);
p("after save: submission_amount = {$r['submission_amount']} · manual_cost = {$r['manual_cost']} · manual_margin_pct = {$r['manual_margin_pct']}");
ok((float)$r['submission_amount'] === 1200000.00, 'submission_amount computed = 1,200,000');
ok((float)$r['manual_cost']       === 1000000.00, 'manual_cost persisted = 1,000,000');
ok((float)$r['manual_margin_pct'] === 20.000,     'manual_margin_pct persisted = 20');
ok((string)$r['bid_price_source'] === 'MANUAL',   'bid_price_source persisted = MANUAL');

/* ── 3. MANUAL + cost=0: does NOT overwrite existing submission_amount ── */
h('3. MANUAL + cost=0 · guard against wiping bid');
$tm->saveSubmissionDetails($tid, [
    'bid_price_source' => 'MANUAL',
    'manual_cost'      => 0,
    'manual_margin_pct'=> 15,
    'submission_amount'=> 800000, // Explicit override should stick when cost=0
], $uid, $unm);
$r2 = $tm->find($tid);
ok((float)$r2['submission_amount'] === 800000.00, 'submission_amount = 800000 (posted value kept because cost=0)');
ok((float)$r2['manual_cost'] === 0.0, 'manual_cost persisted as 0');
ok((float)$r2['manual_margin_pct'] === 15.0, 'manual_margin_pct persisted as 15');

/* ── 4. PRICING_TAB: ignores manual_cost/margin ────────────────────── */
h('4. PRICING_TAB ignores manual_cost/margin');
$tm->saveSubmissionDetails($tid, [
    'bid_price_source' => 'PRICING_TAB',
    'submission_amount'=> 555000,
    'manual_cost'      => 9000000,   // should NOT be used for computation
    'manual_margin_pct'=> 99,
], $uid, $unm);
$r3 = $tm->find($tid);
ok((float)$r3['submission_amount'] === 555000.00, 'submission_amount = 555000 (from posted, not derived)');
ok((string)$r3['bid_price_source'] === 'PRICING_TAB', 'source flipped to PRICING_TAB');

/* ── 5. But manual_cost/margin still persisted (audit trail) ───────── */
h('5. manual_cost/margin still persist even in PRICING_TAB mode (audit)');
ok((float)$r3['manual_cost'] === 9000000.00, 'manual_cost persisted (9,000,000)');
ok((float)$r3['manual_margin_pct'] === 99.0, 'manual_margin_pct persisted (99)');

/* ── 6. Round-trip: fractional cost + fractional margin ────────────── */
h('6. Round-trip · fractional cost/margin');
$tm->saveSubmissionDetails($tid, [
    'bid_price_source' => 'MANUAL',
    'manual_cost'      => 1234567.89,
    'manual_margin_pct'=> 22.5,
], $uid, $unm);
$r4 = $tm->find($tid);
$expected = round(1234567.89 * 1.225, 2);
p("expected {$expected} · got {$r4['submission_amount']}");
ok(abs((float)$r4['submission_amount'] - $expected) < 0.01, "submission_amount ≈ $expected");

/* ── 7. View surface ───────────────────────────────────────────────── */
h('7. View surface');
$vBody = (string)file_get_contents(ROOT . DS . 'app' . DS . 'views' . DS . 'Tenders' . DS . 'view.php');
ok(strpos($vBody, 'id="manual_cost"')       !== false, 'manual_cost input present');
ok(strpos($vBody, 'id="manual_margin_pct"') !== false, 'manual_margin_pct input present');
ok(strpos($vBody, 'id="manual_bid_preview"')!== false, 'manual_bid_preview readonly input present');
ok(strpos($vBody, 'id="manual_cost_panel"') !== false, 'manual_cost_panel wrapper present');
ok(strpos($vBody, 'applyManualBidVisibility') !== false, 'applyManualBidVisibility() JS defined');
ok(strpos($vBody, 'recomputeManualBid')       !== false, 'recomputeManualBid() JS defined');
ok(strpos($vBody, 'cost × (1 + margin/100)')  !== false, 'formula caption present');

/* POST payload wired */
ok(strpos($vBody, 'manual_cost:') !== false && strpos($vBody, 'manual_margin_pct:') !== false, 'POST payload includes manual_cost + manual_margin_pct');

/* ── Z. Restore anchor ─────────────────────────────────────────────── */
h('Z. Restore');
$db->insertUpdate(
    "UPDATE tender_tracker SET
       submission_amount = :sa, bid_price_source = :bps, manual_cost = :mc, manual_margin_pct = :mm,
       tender_stage = :ts
     WHERE c0d = :id",
    [
        ':sa'  => (float)$snap['submission_amount'],
        ':bps' => (string)($snap['bid_price_source'] ?? 'MANUAL'),
        ':mc'  => (float)($snap['manual_cost'] ?? 0),
        ':mm'  => (float)($snap['manual_margin_pct'] ?? 0),
        ':ts'  => (string)$snap['tender_stage'],
        ':id'  => $tid,
    ]
);
p('anchor restored to pre-verify state');

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