<?php
/**
 * Unit tests for PlanInboundIds + migration logic.
 * Run on server: php wizwizxui-timebot/scripts/test-plan-inbound-ids.php
 */
declare(strict_types=1);

require_once dirname(__DIR__) . '/services/PlanInboundIds.php';

$passed = 0;
$failed = 0;

function assertEq(string $label, $expected, $actual): void
{
    global $passed, $failed;
    if ($expected === $actual) {
        $passed++;
        echo "OK   $label\n";
        return;
    }
    $failed++;
    echo "FAIL $label\n";
    echo "     expected: " . json_encode($expected) . "\n";
    echo "     actual:   " . json_encode($actual) . "\n";
}

// --- parse / encode ---
assertEq('parse legacy single id', [5], PlanInboundIds::parse(null, 5));
assertEq('parse empty legacy', [], PlanInboundIds::parse(null, 0));
assertEq('parse json array', [1, 3, 5], PlanInboundIds::parse('[1,3,5]', 0));
assertEq('parse json ignores legacy when json set', [2], PlanInboundIds::parse('[2]', 99));
assertEq('parse empty json falls back legacy', [7], PlanInboundIds::parse('[]', 7));
assertEq('parseFromRow new schema', [1, 2], PlanInboundIds::parseFromRow(['inbound_ids' => '[1,2]', 'inbound_id' => 1]));
assertEq('parseFromRow old schema only', [4], PlanInboundIds::parseFromRow(['inbound_id' => 4]));
assertEq('parseFromRow dedicated plan', [], PlanInboundIds::parseFromRow(['inbound_id' => 0, 'inbound_ids' => null]));

assertEq('encode sorts unique', '[1,3,5]', PlanInboundIds::encode([5, 1, 3, 1]));
assertEq('legacyInboundId first', 3, PlanInboundIds::legacyInboundId([3, 7]));
assertEq('legacyInboundId empty', 0, PlanInboundIds::legacyInboundId([]));

// --- plan type detection ---
assertEq('planUsesInbounds multi json', true, PlanInboundIds::planUsesInbounds(['inbound_ids' => '[1,2]', 'inbound_id' => 1]));
assertEq('planUsesInbounds legacy', true, PlanInboundIds::planUsesInbounds(['inbound_id' => 3]));
assertEq('planUsesInbounds dedicated', false, PlanInboundIds::planUsesInbounds(['inbound_id' => 0, 'inbound_ids' => null]));

// --- sync with live panel ---
assertEq('intersect removes deleted', [1, 3], PlanInboundIds::intersectWithLive([1, 2, 3], [1, 3, 9]));
assertEq('intersect all gone', [], PlanInboundIds::intersectWithLive([2, 4], [1, 3]));
assertEq('intersect empty input', [], PlanInboundIds::intersectWithLive([], [1, 2]));

// --- migration simulation (what ensureSchema UPDATE does) ---
$oldRows = [
    ['id' => 1, 'inbound_id' => 0, 'inbound_ids' => null],
    ['id' => 2, 'inbound_id' => 5, 'inbound_ids' => null],
    ['id' => 3, 'inbound_id' => 12, 'inbound_ids' => null],
];
foreach ($oldRows as &$row) {
    if ((int) $row['inbound_id'] > 0 && ($row['inbound_ids'] === null || $row['inbound_ids'] === '' || $row['inbound_ids'] === '[]')) {
        $row['inbound_ids'] = '[' . (int) $row['inbound_id'] . ']';
    }
}
unset($row);
assertEq('migration row dedicated unchanged', null, $oldRows[0]['inbound_ids']);
assertEq('migration row single inbound', '[5]', $oldRows[1]['inbound_ids']);
assertEq('migration parsed multi-ready', [5], PlanInboundIds::parseFromRow($oldRows[1]));

// --- after admin selects multiple inbounds ---
$multi = PlanInboundIds::encode([1, 3, 7]);
$rowMulti = ['inbound_ids' => $multi, 'inbound_id' => PlanInboundIds::legacyInboundId([1, 3, 7])];
assertEq('multi save legacy first id', 1, $rowMulti['inbound_id']);
assertEq('multi save json', '[1,3,7]', $rowMulti['inbound_ids']);
assertEq('multi parse count', 3, count(PlanInboundIds::parseFromRow($rowMulti)));

// --- after inbound 3 deleted from panel ---
$afterSync = PlanInboundIds::intersectWithLive(PlanInboundIds::parseFromRow($rowMulti), [1, 7, 9]);
assertEq('after panel delete inbound 3', [1, 7], $afterSync);

echo "\n";
if ($failed === 0) {
    echo "All $passed tests passed.\n";
    exit(0);
}
echo "$failed failed, $passed passed.\n";
exit(1);
