<?php
/**
 * Slice 8c-Doc · self-verifying operator manual check.
 *
 * Reads docs/rsflow_works_module.md and asserts every named artefact still exists.
 * If someone renames a file or drops a table, this script trips before docs go stale.
 */
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 ?? [];

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"; }

$db = new DB();

/* ── 1. Doc file exists ─────────────────────────────────────────────── */
h('1. Doc file exists');
$doc = ROOT . DS . 'docs' . DS . 'rsflow_works_module.md';
ok(is_file($doc), 'docs/rsflow_works_module.md present');

/* ── 2. Every controller named in the doc exists on disk ───────────── */
h('2. Controllers named in the doc');
$controllers = [
    'WorksBoq','WorksPhases','WorksCrs','WorksProjectReport',
    'WorksIpcs','WorksRetention','WorksCustomerRetention','WorksAlerts',
];
foreach ($controllers as $c) {
    ok(is_file(ROOT . DS . 'app' . DS . 'controllers' . DS . $c . 'Controller.php'), "$c" . "Controller.php");
}

/* ── 3. Every model named in the doc exists on disk ────────────────── */
h('3. Models named in the doc');
$models = [
    'WorksBoq','WorksPhases','WorksCrs','WorksCrFulfilment',
    'WorksProjectReport','WorksIpcs','WorksRetention',
    'WorksCustomerRetention','WorksAlerts',
];
foreach ($models as $m) {
    ok(is_file(ROOT . DS . 'app' . DS . 'models' . DS . $m . '.php'), "$m.php");
}

/* ── 4. Every view directory named in the doc exists ───────────────── */
h('4. View directories');
$viewDirs = [
    'WorksBoq'      => ['index','view'],
    'WorksPhases'   => ['index','plan','view'],
    'WorksCrs'      => ['index','create','view','fulfil'],
    'WorksProjectReport'     => ['index','view'],
    'WorksIpcs'     => ['index','list','create','view'],
    'WorksRetention'         => ['pool'],
    'WorksCustomerRetention' => ['pool'],
    'WorksAlerts'   => ['index'],
];
foreach ($viewDirs as $d => $files) {
    foreach ($files as $f) {
        ok(is_file(ROOT . DS . 'app' . DS . 'views' . DS . $d . DS . $f . '.php'), "views/$d/$f.php");
    }
}

/* ── 5. Every table named in the doc exists in DB ──────────────────── */
h('5. Tables named in the doc');
$tables = [
    'works_boqs','works_boq_items','works_phases','works_phase_boq_items','works_phase_activities',
    'works_crs','works_cr_activities',
    'works_cr_preliminaries','works_cr_manpower','works_cr_materials','works_cr_equipment',
    'works_cr_tools','works_cr_subcontracts','works_cr_overheads',
    'works_cr_closure_variance','works_phase_items_issued',
    'works_retention_holdings','works_customer_retention_releases',
    'works_ipcs','works_ipc_lines',
    'lpos','lpo_items','payment_allocations','payments','payment_vouchers','sales','sales_items',
];
foreach ($tables as $t) {
    $r = $db->mySelect("SHOW TABLES LIKE :t", [':t' => $t]);
    ok(!empty($r), "table: $t");
}

/* ── 6. Columns added by 8c series still present ───────────────────── */
h('6. Columns added by 8c series');
$cols = [
    'works_boqs'      => ['retention_pct','dlp_days'],
    'works_crs'       => ['closed_by','closed_by_name','closed_on','close_reason'],
    'works_phases'    => ['closed_by','closed_by_name','closed_on'],
    'lpos'            => ['source_cr_id','source_cr_pillar','source_phase_id'],
    'lpo_items'       => ['source_cr_pillar','source_cr_line_id'],
    'works_ipcs'      => ['certified_gross','retention_pct','retention_amount','advance_recovery',
                          'net_amount','vat_pct','vat_amount','invoice_total','sale_id',
                          'approved_by','approved_by_name','approved_on'],
    'works_ipc_lines' => ['contract_qty','contract_rate','previous_qty','this_period_qty','cumulative_qty'],
];
foreach ($cols as $tbl => $expect) {
    $rows = $db->mySelect("SHOW COLUMNS FROM `$tbl`", []) ?: [];
    $have = array_column($rows, 'Field');
    foreach ($expect as $c) {
        ok(in_array($c, $have, true), "$tbl.$c");
    }
}

/* ── 7. Perm matrix — spot-check the ✓ actions ─────────────────────── */
h('7. Perm matrix spot-checks');
$checks = [
    ['Projects Coordinator', 'WorksCrs',    'closeAj'],
    ['Project Manager',      'WorksCrs',    'closeAj'],
    ['Administrator',        'WorksCrs',    'closeAj'],
    ['Projects Coordinator', 'WorksPhases', 'closeAj'],
    ['Projects Coordinator', 'WorksIpcs',   'approveAj'],
    ['Finance Manager',      'WorksRetention',         'releaseAj'],
    ['Administrator',        'WorksRetention',         'releaseAj'],
    ['Finance Manager',      'WorksCustomerRetention', 'recordReleaseAj'],
    ['Executive',            'WorksProjectReport',     'view'],
    ['Executive',            'WorksAlerts',            'index'],
];
foreach ($checks as $chk) {
    [$role, $ctrl, $act] = $chk;
    $rr = $db->mySelect("SELECT c0d FROM user_groups WHERE user_group_name = :n", [':n' => $role]);
    $gid = (int)($rr[0]['c0d'] ?? 0);
    $r = $db->mySelect(
        "SELECT 1 FROM user_groups_perms WHERE user_group_id = :g AND controller_allowed = :c AND action_allowed = :a LIMIT 1",
        [':g' => $gid, ':c' => $ctrl, ':a' => $act]
    );
    ok(!empty($r), "$role · $ctrl/$act");
}

/* ── 8. Verify script list matches what the doc advertises ─────────── */
h('8. Verify scripts advertised in the doc');
$scripts = [
    'slice8cSpine_e2e_verify.php',
    'slice8cSurfaces_e2e_verify.php',
    'slice8cFulfil_e2e_verify.php',
    'slice8cPayments_e2e_verify.php',
    'slice8cClose_e2e_verify.php',
    'slice8cReport_e2e_verify.php',
    'slice8cRetention_e2e_verify.php',
    'slice8cCertificate_e2e_verify.php',
    'slice8cCustomerRetention_e2e_verify.php',
    'slice8cReportPlus_e2e_verify.php',
    'slice8cAlerts_e2e_verify.php',
    'slice8cTrigger_e2e_verify.php',
];
foreach ($scripts as $s) {
    ok(is_file(ROOT . DS . 'scripts' . DS . $s), "scripts/$s");
}

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