<?php
/**
 * Cloudflare 域名自动化回归（CLI 输出 JSON，Mock HTTP）
 */
$root = dirname(__DIR__);
require_once $root . '/cong.php';
require_once $root . '/lib/Cloak/DomainRepository.php';
require_once $root . '/lib/Cloak/CloudflareConfig.php';
require_once $root . '/lib/Cloak/CloudflareClient.php';
require_once $root . '/lib/Cloak/DomainProvisioningService.php';

class MockCloudflareClient extends CloudflareClient
{
    public $zoneStatus   = 'pending';
    public $deleteCalled = false;
    public $upsertCalls  = [];

    public function __construct()
    {
    }

    public function createZone($hostname)
    {
        return [
            'ok'     => true,
            'result' => [
                'id'            => 'zone_mock_' . md5($hostname),
                'name_servers'  => ['ada.ns.cloudflare.com', 'bob.ns.cloudflare.com'],
            ],
        ];
    }

    public function getZone($zoneId)
    {
        return [
            'ok'     => true,
            'result' => [
                'id'            => $zoneId,
                'status'        => $this->zoneStatus,
                'name_servers'  => ['ada.ns.cloudflare.com', 'bob.ns.cloudflare.com'],
            ],
        ];
    }

    public function deleteZone($zoneId)
    {
        $this->deleteCalled = true;
        return ['ok' => true, 'result' => ['id' => $zoneId]];
    }

    public function upsertARecord($zoneId, $fqdn, $ip, $proxied = true)
    {
        $this->upsertCalls[] = compact('zoneId', 'fqdn', 'ip', 'proxied');
        return ['ok' => true, 'result' => ['id' => 'rec_' . md5($fqdn)]];
    }

    public function setSslFlexible($zoneId)
    {
        return ['ok' => true];
    }

    public function setAlwaysHttps($zoneId)
    {
        return ['ok' => true];
    }
}

$tests = [];
$host  = 'cf-mock-' . substr(md5((string) microtime(true)), 0, 8) . '.test';

try {
    $pdo = DomainRepository::pdo();
    DomainRepository::ensureTable($pdo);

    // 未启用 CF：添加后 cf_status=local
    CloudflareConfig::clearTestOverrides();
    DomainProvisioningService::clearClientOverride();
    $addLocal = DomainProvisioningService::provisionOnAdd($pdo, $host);
    $rowLocal = DomainRepository::findById($pdo, (int) ($addLocal['id'] ?? 0));
    $tests['add_local_cf_status'] = ($addLocal['ok'] ?? false) === true
        && ($addLocal['cf_status'] ?? '') === 'local'
        && ($rowLocal['cf_status'] ?? '') === 'local';
    DomainRepository::deleteById($pdo, (int) $addLocal['id']);

    // Mock：pending_ns → ready
    CloudflareConfig::setTestOverrides(['enabled' => true, 'server_ip' => '203.0.113.10']);
    $mock = new MockCloudflareClient();
    DomainProvisioningService::setClientOverride($mock);

    $addCf = DomainProvisioningService::provisionOnAdd($pdo, $host);
    $domainId = (int) ($addCf['id'] ?? 0);
    $tests['add_cf_pending_ns'] = ($addCf['ok'] ?? false) === true
        && ($addCf['cf_status'] ?? '') === 'pending_ns'
        && count($addCf['nameservers'] ?? []) === 2;

    $pending = DomainProvisioningService::checkAndProvision($pdo, $domainId);
    $tests['check_pending_ns'] = ($pending['ok'] ?? false) === true
        && ($pending['status'] ?? '') === 'pending_ns';

    $mock->zoneStatus = 'active';
    $ready = DomainProvisioningService::checkAndProvision($pdo, $domainId);
    $rowReady = DomainRepository::findById($pdo, $domainId);
    $tests['check_ready'] = ($ready['ok'] ?? false) === true
        && ($ready['status'] ?? '') === 'ready'
        && ($rowReady['cf_status'] ?? '') === 'ready'
        && count($mock->upsertCalls) === 2;

    $del = DomainProvisioningService::deleteWithCloudflare($pdo, $domainId);
    $tests['delete_calls_zone'] = ($del['ok'] ?? false) === true && $mock->deleteCalled === true;
    $tests['delete_row_gone']   = DomainRepository::findById($pdo, $domainId) === null;
} catch (Throwable $e) {
    $tests['exception'] = false;
    $tests['error']     = $e->getMessage();
} finally {
    CloudflareConfig::clearTestOverrides();
    DomainProvisioningService::clearClientOverride();
}

$ok = !in_array(false, $tests, true) && !isset($tests['error']);
echo json_encode(['ok' => $ok, 'tests' => $tests], JSON_UNESCAPED_UNICODE) . "\n";
