<?php

namespace App\Support\Color;

final class AutoContrast
{
    /**
     * Returns true if a color is "dark" based on relative luminance.
     * Accepts "#rgb", "#rrggbb", "rgb(r,g,b)", "rgba(r,g,b,a)".
     */
    public static function isDark(string $color): bool
    {
        [$r, $g, $b] = self::toRgb($color) ?? [0, 0, 0];
        $luminance = self::relativeLuminance($r, $g, $b);

        // 0..1 scale. 0.45 is a pragmatic cut for UI surfaces.
        return $luminance < 0.45;
    }

    public static function readableTextColor(
        string $backgroundColor,
        string $lightText = '#ffffff',
        string $darkText = '#111827',
    ): string {
        return self::isDark($backgroundColor) ? $lightText : $darkText;
    }

    /**
     * Returns "rgba(r, g, b, a)" for a hex color and alpha.
     */
    public static function rgba(string $color, float $alpha): ?string
    {
        $rgb = self::toRgb($color);
        if (! $rgb) {
            return null;
        }

        [$r, $g, $b] = $rgb;
        $a = max(0, min(1, $alpha));

        return "rgba({$r}, {$g}, {$b}, {$a})";
    }

    /**
     * @return array{0:int,1:int,2:int}|null
     */
    private static function toRgb(string $color): ?array
    {
        $value = trim($color);

        if ($value === '') {
            return null;
        }

        if (preg_match('/^#([0-9a-f]{3})$/i', $value, $m)) {
            $hex = strtolower($m[1]);
            $r = hexdec(str_repeat($hex[0], 2));
            $g = hexdec(str_repeat($hex[1], 2));
            $b = hexdec(str_repeat($hex[2], 2));
            return [$r, $g, $b];
        }

        if (preg_match('/^#([0-9a-f]{6})$/i', $value, $m)) {
            $hex = strtolower($m[1]);
            $r = hexdec(substr($hex, 0, 2));
            $g = hexdec(substr($hex, 2, 2));
            $b = hexdec(substr($hex, 4, 2));
            return [$r, $g, $b];
        }

        if (preg_match('/^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*([01](?:\.\d+)?))?\s*\)$/i', $value, $m)) {
            $r = (int) $m[1];
            $g = (int) $m[2];
            $b = (int) $m[3];
            return [max(0, min(255, $r)), max(0, min(255, $g)), max(0, min(255, $b))];
        }

        return null;
    }

    private static function relativeLuminance(int $r, int $g, int $b): float
    {
        $rs = $r / 255;
        $gs = $g / 255;
        $bs = $b / 255;

        $rLin = $rs <= 0.03928 ? $rs / 12.92 : pow(($rs + 0.055) / 1.055, 2.4);
        $gLin = $gs <= 0.03928 ? $gs / 12.92 : pow(($gs + 0.055) / 1.055, 2.4);
        $bLin = $bs <= 0.03928 ? $bs / 12.92 : pow(($bs + 0.055) / 1.055, 2.4);

        return (0.2126 * $rLin) + (0.7152 * $gLin) + (0.0722 * $bLin);
    }
}

