<?php

namespace Tests\Feature;

use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\SiteURI;
use CodeIgniter\HTTP\UserAgent;
use CodeIgniter\Test\CIUnitTestCase;
use Config\App;
use Config\Services;

/**
 * The in-text links in the Import field guides.
 *
 * Every one of them used to point at the route that serves the list as JSON —
 * `lists/domains` is Lists\Domains::json, not a page — so clicking "domain list
 * IDs" opened a tab full of raw JSON. The pages are the Lists hub tabs, and
 * Lists::tabUrl() is the app's own way of naming them. Asserted on the rendered
 * markup, because the difference is invisible at every other level: both spellings
 * are valid routes that answer 200.
 */
final class FieldGuideLinksTest extends CIUnitTestCase
{
    private int $obLevel = 0;

    protected function setUp(): void
    {
        parent::setUp();
        $this->obLevel = ob_get_level();
    }

    protected function tearDown(): void
    {
        while (ob_get_level() > $this->obLevel) {
            ob_end_clean();
        }
        parent::tearDown();
    }

    private function render(string $partial): string
    {
        helper(['utils', 'auth']);

        $config = config(App::class);
        Services::injectMock('request', new IncomingRequest(
            $config,
            new SiteURI($config, 'import-export/import'),
            null,
            new UserAgent()
        ));

        return view('import-export/partials/' . $partial);
    }

    public function testListIdColumnsLinkToTheListsHubNotTheJsonEndpoint(): void
    {
        $html = $this->render('fields_campaigns');

        foreach (['domains', 'keyword-lists', 'sources'] as $tab) {
            $this->assertStringContainsString('?tab=' . $tab . '"', $html, $tab . ' must link to its hub tab');
        }

        // The JSON routes, as hrefs. `lists?tab=` is fine; `lists/domains"` is not.
        foreach (['lists/domains"', 'lists/keyword-lists"', 'lists/sources"'] as $jsonRoute) {
            $this->assertStringNotContainsString($jsonRoute, $html);
        }
    }

    public function testRetargetingPixelIdsAreLinked(): void
    {
        $html = $this->render('fields_campaigns');

        $this->assertMatchesRegularExpression(
            '~<a href="[^"]*conversion-tracking[^"]*\#retargeting"[^>]*>Retargeting Pixel IDs</a>~',
            $html
        );
    }

    public function testTheOtherIdColumnsLinkToWhereThoseIdsComeFrom(): void
    {
        $campaigns = $this->render('fields_campaigns');
        $creatives = $this->render('fields_creatives');

        $this->assertStringContainsString('>creative IDs</a>', $campaigns);
        $this->assertStringContainsString('>Brand Keyword IDs</a>', $campaigns);
        $this->assertStringContainsString('>campaign IDs</a>', $creatives);
    }

    public function testEveryLinkInTheGuidesResolvesToAPage(): void
    {
        // A guard against the next one: no href in either guide may point at a route
        // whose controller answers with JSON.
        $jsonRoutes = ['lists/domains', 'lists/keyword-lists', 'lists/keywords', 'lists/sources'];

        foreach (['fields_campaigns', 'fields_creatives'] as $partial) {
            preg_match_all('/href="([^"]+)"/', $this->render($partial), $matches);
            foreach ($matches[1] as $href) {
                $path = parse_url($href, PHP_URL_PATH) ?? '';
                $path = trim(preg_replace('#^.*/\?/#', '', (string) $path), '/');
                $this->assertNotContains($path, $jsonRoutes, $href . ' serves JSON, not a page');
            }
        }
    }

    public function testTheFrequencyRowDocumentsTheRangeThatIsActuallyEnforced(): void
    {
        $html = $this->render('fields_campaigns');

        $this->assertStringContainsString('32767', $html);
        // The claim QA reopened this on. There is no 100 minimum, in this app or in
        // legacy — 100 is the campaign form's default for a new display campaign.
        $this->assertStringNotContainsString('min 100', $html);
        $this->assertStringContainsString('a default, not a minimum', $html);
    }
}
