<?php

namespace Tests\Feature;

use App\Domain\Shared\Branding\ColorRamp;
use Tests\TestCase;

/**
 * The portal is rendered in whatever colour a tenant picked, so its legibility
 * cannot be checked by looking at one screen — it has to hold for the whole
 * range of colours a tenant can pick.
 *
 * These are the brands that used to break it: a navy so dark that every shade
 * from 500 up collapsed onto the text colour, a yellow so light that the same
 * shades disappeared into the page, and the semantic amber, which is perfect as
 * a fill and about 2:1 as text.
 */
class PortalBrandContrastTest extends TestCase
{
    private const BRANDS = [
        'oc sport navy' => '#0c1236',
        'gold' => '#fbcf0a',
        'shipped blue' => '#2563eb',
        'green' => '#10b981',
        'red' => '#ef4444',
        'amber' => '#f59e0b',
        'near black' => '#000000',
        'near white' => '#ffffff',
    ];

    public function test_the_interactive_colour_is_legible_on_both_surfaces(): void
    {
        foreach (self::BRANDS as $name => $hex) {
            $ramp = ColorRamp::fromHex($hex);

            $this->assertGreaterThanOrEqual(
                4.5,
                ColorRamp::contrastRatio($ramp->interactive, '#ffffff'),
                "{$name}: link colour {$ramp->interactive} is not readable on a light card",
            );

            $this->assertGreaterThanOrEqual(
                4.5,
                ColorRamp::contrastRatio($ramp->interactiveOnDark, ColorRamp::DARK_SURFACE),
                "{$name}: dark-mode link colour {$ramp->interactiveOnDark} is not readable on a dark card",
            );
        }
    }

    /**
     * A link that passes contrast by being black is not a link. The point of
     * the colour is that a member can tell it apart from the paragraph it sits
     * in, which is what shade 600 could not do for a dark brand.
     */
    public function test_the_interactive_colour_is_distinguishable_from_body_text(): void
    {
        // --portal-ink, oklch(0.22 0.02 265).
        $bodyInk = '#161b24';

        foreach (['oc sport navy' => '#0c1236', 'shipped blue' => '#2563eb'] as $name => $hex) {
            $ramp = ColorRamp::fromHex($hex);

            $this->assertGreaterThan(
                1.6,
                ColorRamp::contrastRatio($ramp->interactive, $bodyInk),
                "{$name}: link colour {$ramp->interactive} is indistinguishable from body text",
            );
        }
    }

    public function test_semantic_colours_are_legible_as_text_and_keep_their_fills(): void
    {
        foreach (['#10b981', '#f59e0b', '#ef4444'] as $hex) {
            $this->assertGreaterThanOrEqual(
                4.5,
                ColorRamp::contrastRatio(ColorRamp::ink($hex), '#ffffff'),
                "{$hex} as text on a light card",
            );

            $this->assertGreaterThanOrEqual(
                4.5,
                ColorRamp::contrastRatio(ColorRamp::ink($hex, ColorRamp::DARK_SURFACE), ColorRamp::DARK_SURFACE),
                "{$hex} as text on a dark card",
            );

            // …and the same colour filled, with whatever foreground it was
            // given. White on amber was the failure this pins.
            [$r, $g, $b] = ColorRamp::hexToRgb($hex);
            $this->assertGreaterThanOrEqual(
                4.5,
                ColorRamp::contrastRatio(ColorRamp::readableForeground($r, $g, $b), $hex),
                "text drawn on a filled {$hex}",
            );
        }
    }

    /**
     * portal.css is built with `source(none)`, so a template that is not named
     * in an @source line contributes no utilities at all. The layouts were not
     * named: the header, the tab bar and the centred column silently lost every
     * class they alone used, which is how a 32px logo rendered at 500px and
     * pushed every screen sideways.
     */
    public function test_the_portal_stylesheet_scans_its_own_layouts(): void
    {
        $css = file_get_contents(resource_path('css/portal.css'));

        $this->assertStringContainsString('source(none)', $css, 'the premise of this test changed');

        foreach (['layouts/portal.blade.php', 'layouts/portal-public.blade.php'] as $layout) {
            $this->assertStringContainsString(
                "@source '../views/{$layout}'",
                $css,
                "{$layout} is rendered by the portal but is not scanned for utilities",
            );
        }
    }
}
