<?php

namespace Tests\Feature;

use CodeIgniter\Test\CIUnitTestCase;
use Config\Services;

/**
 * Master-advertiser resolution (qa-authorization-fixes).
 *
 * auth_master_adv_id() maps a linked sub-user's session adv_id to its parent
 * (Advertiser_info.masterid) so account-scoped reads return the master's data.
 * Runs against the dev Admin DB, which carries the State Farm triad:
 *   17237 = master (no masterid)
 *   17306 = viewer sub-user (masterid 17237)
 *   17307 = admin  sub-user (masterid 17237)
 *
 * Needs the full CI4 boot (DB + session services), so it lives in the feature
 * suite. Run with:
 *   php8.2 -d newrelic.enabled=0 -d newrelic.daemon.dont_launch=3 \
 *     vendor/bin/phpunit --bootstrap tests/feature_bootstrap.php tests/feature/AdvertiserContextTest.php
 */
final class AdvertiserContextTest extends CIUnitTestCase
{
    private const MASTER     = 17237;
    private const VIEWER_SUB = 17306;
    private const ADMIN_SUB  = 17307;
    private const OTHER_ACCT = 15196;

    protected function setUp(): void
    {
        parent::setUp();
        helper('auth');
    }

    private function login(int $advId): void
    {
        $this->mockSession();
        Services::session()->set(['logged_in' => 1, 'adv_id' => $advId, 'user_id' => $advId]);
    }

    public function testViewerSubUserResolvesToMaster(): void
    {
        $this->login(self::VIEWER_SUB);
        $this->assertSame(self::MASTER, auth_master_adv_id());
    }

    public function testAdminSubUserResolvesToMaster(): void
    {
        $this->login(self::ADMIN_SUB);
        $this->assertSame(self::MASTER, auth_master_adv_id());
    }

    public function testMasterAccountResolvesToItself(): void
    {
        $this->login(self::MASTER);
        $this->assertSame(self::MASTER, auth_master_adv_id());
    }

    public function testStandaloneAccountResolvesToItself(): void
    {
        $this->login(self::OTHER_ACCT);
        $this->assertSame(self::OTHER_ACCT, auth_master_adv_id());
    }

    public function testNoSessionFailsClosedToZero(): void
    {
        $this->mockSession();

        $this->assertSame(0, auth_master_adv_id());
    }

    public function testResolutionNeverReadsRequestInput(): void
    {
        // A spoofed adv_id in the request must be ignored — resolution is
        // session + DB only. Log in as the viewer sub-user, plant a different
        // adv_id on the request, and assert the master is still returned.
        $this->login(self::VIEWER_SUB);
        $_GET['adv_id']  = (string) self::OTHER_ACCT;
        $_POST['adv_id'] = (string) self::OTHER_ACCT;

        $this->assertSame(self::MASTER, auth_master_adv_id());

        unset($_GET['adv_id'], $_POST['adv_id']);
    }

    public function testDashboardContextResolvesSubUserToMaster(): void
    {
        // Dashboard KPI / top-campaign seam — parameterized (no session needed).
        $this->assertSame(self::MASTER, \App\Services\Dashboard\DashboardAdvertiserContext::resolveAdvId(self::VIEWER_SUB));
        $this->assertSame(self::MASTER, \App\Services\Dashboard\DashboardAdvertiserContext::resolveAdvId(self::MASTER));
        $this->assertSame(0, \App\Services\Dashboard\DashboardAdvertiserContext::resolveAdvId(0));
    }

    public function testMasterAccountNameResolvesForSubUser(): void
    {
        // Billing keys off the account-name string; a sub-user must resolve to
        // the master's name (State Farm master 17237 = 'statefarm').
        $this->login(self::VIEWER_SUB);
        $this->assertSame('statefarm', auth_master_account_name());
    }
}
