<?php

namespace SoftminalB2B\Support;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Resolve the active theme's brand colour, so the B2B storefront can "match the
 * theme" using the merchant's OWN colour rather than a colour we picked.
 *
 * Reads the theme's colour palette — block themes / theme.json expose it via
 * wp_get_global_settings(); classic themes may via
 * add_theme_support('editor-color-palette') — and picks the most brand-like
 * entry (a primary/accent/brand slug, else the first non-neutral colour).
 * Returns '' when nothing usable is found, so callers can fall back.
 */
class ThemeColor
{
    /** Cache within a request — palette lookups aren't free. */
    private static ?string $cached = null;

    /** Slugs that read as a brand/accent colour, in preference order. */
    private const BRAND_SLUGS = ['primary', 'accent', 'brand', 'theme', 'link', 'secondary'];

    /**
     * A CSS colour VALUE for `--sb-pri` — either a real hex (block themes /
     * theme.json expose hex palettes) or a reference to the theme's palette CSS
     * variable (themes like Astra store their palette as `var(--…)`, so a hex
     * isn't available server-side but the variable resolves at runtime). Empty
     * when the theme exposes no usable colour.
     */
    public static function accent(): string
    {
        if (self::$cached !== null) {
            return self::$cached;
        }

        $colors = self::palette();

        // 1) A real hex from a brand-ish slug.
        foreach (self::BRAND_SLUGS as $slug) {
            foreach ($colors as $c) {
                if (!empty($c['slug']) && stripos((string) $c['slug'], $slug) !== false) {
                    $hex = sanitize_hex_color((string) ($c['color'] ?? ''));
                    if ($hex && !self::isNeutral($hex)) {
                        return self::$cached = $hex;
                    }
                }
            }
        }

        // 2) The first non-neutral hex in the palette.
        foreach ($colors as $c) {
            $hex = sanitize_hex_color((string) ($c['color'] ?? ''));
            if ($hex && !self::isNeutral($hex)) {
                return self::$cached = $hex;
            }
        }

        // 3) No hex (var-based palette): reference the brand slug's preset var,
        //    else the theme's first palette colour.
        $slug = self::brandSlug($colors);
        if ($slug !== '') {
            return self::$cached = 'var(--wp--preset--color--' . $slug . ', #6D5EF5)';
        }

        return self::$cached = '';
    }

    /**
     * @param array<int, array<string, mixed>> $colors
     */
    private static function brandSlug(array $colors): string
    {
        foreach (self::BRAND_SLUGS as $want) {
            foreach ($colors as $c) {
                if (!empty($c['slug']) && stripos((string) $c['slug'], $want) !== false) {
                    return self::sanitizeSlug((string) $c['slug']);
                }
            }
        }

        return !empty($colors[0]['slug']) ? self::sanitizeSlug((string) $colors[0]['slug']) : '';
    }

    private static function sanitizeSlug(string $slug): string
    {
        return (string) preg_replace('/[^a-z0-9\-]/', '', strtolower($slug));
    }

    /**
     * @return array<int, array<string, mixed>>
     */
    private static function palette(): array
    {
        $colors = [];

        if (function_exists('wp_get_global_settings')) {
            $palette = wp_get_global_settings(['color', 'palette']);
            // Theme- and user-defined colours are the merchant's brand; skip the
            // WordPress "default" palette (it isn't the theme's identity).
            foreach (['theme', 'custom'] as $origin) {
                if (!empty($palette[$origin]) && is_array($palette[$origin])) {
                    $colors = array_merge($colors, $palette[$origin]);
                }
            }
        }

        if (!$colors) {
            $support = get_theme_support('editor-color-palette');
            if (!empty($support[0]) && is_array($support[0])) {
                $colors = $support[0];
            }
        }

        return $colors;
    }

    /** White-ish, black-ish or grey (low saturation) — not a brand colour. */
    private static function isNeutral(string $hex): bool
    {
        $hex = strtolower(ltrim($hex, '#'));

        if (strlen($hex) === 3) {
            $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
        }

        if (strlen($hex) !== 6) {
            return true;
        }

        $r = hexdec(substr($hex, 0, 2));
        $g = hexdec(substr($hex, 2, 2));
        $b = hexdec(substr($hex, 4, 2));
        $max = max($r, $g, $b);
        $min = min($r, $g, $b);

        if ($max >= 245 && $min >= 245) {
            return true; // near-white
        }
        if ($max <= 20) {
            return true; // near-black
        }

        return ($max - $min) < 16; // grey
    }
}
