<?php
/**
 * Persistent Bricks design convention storage (B6).
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks\Support;

/**
 * Stores the site design convention outside Lola memory budget.
 */
final class DesignConventionStore
{
    public const OPTION = 'lolacore_bricks_design_convention';

    /**
     * @return array<string, mixed>
     */
    public static function get(): array
    {
        $stored = get_option(self::OPTION, []);
        if (is_array($stored) && $stored !== []) {
            return self::normalize($stored);
        }

        $legacy = get_option(SystemVocabulary::CONVENTION_OPTION, '');
        if (is_string($legacy) && $legacy !== '') {
            return self::normalize(['naming_pattern' => $legacy]);
        }

        return self::defaults();
    }

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    public static function save(array $input): array
    {
        $current  = self::get();
        $merged   = array_merge($current, array_intersect_key($input, array_flip(array_keys(self::defaults()))));
        $merged   = self::normalize($merged);
        $saved    = update_option(self::OPTION, $merged);

        if ($saved && !empty($merged['naming_pattern'])) {
            update_option(SystemVocabulary::CONVENTION_OPTION, (string) $merged['naming_pattern']);
        }

        return $merged;
    }

    public static function hasConvention(): bool
    {
        $convention = self::get();

        return trim((string) ($convention['naming_pattern'] ?? '')) !== ''
            || trim((string) ($convention['variable_policy'] ?? '')) !== ''
            || trim((string) ($convention['external_framework'] ?? '')) !== '';
    }

    /**
     * @return array{total: int, matching: int, percent: int}
     */
    public static function classComplianceStats(): array
    {
        $pattern = trim((string) (self::get()['naming_pattern'] ?? ''));
        $classes = self::loadActiveClassNames();
        $total   = count($classes);

        if ($total === 0 || $pattern === '') {
            return [
                'total'    => $total,
                'matching' => 0,
                'percent'  => $total === 0 ? 100 : 0,
            ];
        }

        $matching = 0;
        foreach ($classes as $name) {
            if (@preg_match($pattern, $name) === 1) {
                ++$matching;
            }
        }

        return [
            'total'    => $total,
            'matching' => $matching,
            'percent'  => (int) round(($matching / $total) * 100),
        ];
    }

    /**
     * @return string[]
     */
    private static function loadActiveClassNames(): array
    {
        $raw = get_option(BricksMetaKeys::OPTION_GLOBAL_CLASSES, []);
        if (!is_array($raw)) {
            return [];
        }

        $names = [];
        foreach ($raw as $class) {
            if (!is_array($class)) {
                continue;
            }

            $name = trim((string) ($class['name'] ?? ''));
            if ($name !== '') {
                $names[] = $name;
            }
        }

        return $names;
    }

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    private static function normalize(array $input): array
    {
        $defaults = self::defaults();
        $merged   = array_merge($defaults, $input);

        $merged['naming_pattern'] = trim((string) ($merged['naming_pattern'] ?? ''));
        $merged['variable_policy'] = trim((string) ($merged['variable_policy'] ?? ''));
        $merged['external_framework'] = trim((string) ($merged['external_framework'] ?? ''));
        $merged['notes'] = trim((string) ($merged['notes'] ?? ''));

        $merged['examples_valid'] = array_values(array_filter(array_map(
            'strval',
            is_array($merged['examples_valid'] ?? null) ? $merged['examples_valid'] : []
        )));
        $merged['examples_invalid'] = array_values(array_filter(array_map(
            'strval',
            is_array($merged['examples_invalid'] ?? null) ? $merged['examples_invalid'] : []
        )));
        $merged['protected_prefixes'] = array_values(array_filter(array_map(
            'strval',
            is_array($merged['protected_prefixes'] ?? null) ? $merged['protected_prefixes'] : []
        )));

        return $merged;
    }

    /**
     * @return array<string, mixed>
     */
    private static function defaults(): array
    {
        return [
            'naming_pattern'      => '',
            'variable_policy'     => '',
            'external_framework'  => '',
            'protected_prefixes'  => [],
            'notes'               => '',
            'examples_valid'      => [],
            'examples_invalid'    => [],
        ];
    }
}
