<?php

declare(strict_types=1);

/**
 * @deprecated APO-170 retires direct navigation header override writes. Use MyronTemplateChromeAssignmentRepository.
 */
final class MyronNavigationHeaderOverrideRepository
{
    private const DEFAULTS = [
        'header_variant' => 'inherit',
        'primary_menu_visibility' => 'inherit',
        'utility_actions_visibility' => 'inherit',
        'brand_visibility' => 'inherit',
    ];

    private const OPTIONS = [
        'header_variant' => ['inherit', 'full', 'minimal', 'hidden'],
        'primary_menu_visibility' => ['inherit', 'show', 'hide'],
        'utility_actions_visibility' => ['inherit', 'show', 'hide'],
        'brand_visibility' => ['inherit', 'show', 'hide'],
    ];

    private const SCOPE_TYPES = ['page', 'template'];

    public function __construct(private readonly PDO $pdo)
    {
    }

    /**
     * @return array<string, list<string>>
     */
    public function optionSets(): array
    {
        return self::OPTIONS;
    }

    /**
     * @return array<string, string>
     */
    public function defaults(): array
    {
        return self::DEFAULTS;
    }

    /**
     * @return list<array<string, mixed>>
     */
    public function listOverrides(?string $scopeType = null): array
    {
        $sql = 'SELECT * FROM navigation_header_overrides';
        $params = [];
        if ($scopeType !== null && trim($scopeType) !== '') {
            $sql .= ' WHERE scope_type = :scope_type';
            $params[':scope_type'] = $this->normalizeScopeType($scopeType);
        }
        $sql .= ' ORDER BY scope_type ASC, scope_key ASC';

        $statement = $this->pdo->prepare($sql);
        $statement->execute($params);

        $overrides = [];
        foreach ($statement->fetchAll() as $row) {
            if (is_array($row)) {
                $overrides[] = $this->hydrate($row);
            }
        }

        return $overrides;
    }

    public function findOverride(string $scopeType, string $scopeKey): ?array
    {
        $normalizedType = $this->normalizeScopeType($scopeType);
        $normalizedKey = $this->normalizeScopeKey($normalizedType, $scopeKey);
        if ($normalizedKey === '') {
            return null;
        }

        $statement = $this->pdo->prepare(
            'SELECT *
             FROM navigation_header_overrides
             WHERE scope_type = :scope_type
               AND scope_key = :scope_key
             LIMIT 1'
        );
        $statement->execute([
            ':scope_type' => $normalizedType,
            ':scope_key' => $normalizedKey,
        ]);
        $row = $statement->fetch();

        return is_array($row) ? $this->hydrate($row) : null;
    }

    /**
     * @param array<string, mixed> $input
     */
    public function saveOverride(string $scopeType, string $scopeKey, array $input, string $updatedByUserId): array
    {
        $normalizedType = $this->normalizeScopeType($scopeType);
        $normalizedKey = $this->normalizeScopeKey($normalizedType, $scopeKey);
        if ($normalizedKey === '') {
            throw new InvalidArgumentException('Navigation header override scope is required.');
        }

        $settings = $this->normalizeSettings($input, true);
        $now = myronNow();
        $existing = $this->findOverride($normalizedType, $normalizedKey);

        if (is_array($existing)) {
            $statement = $this->pdo->prepare(
                'UPDATE navigation_header_overrides
                 SET header_variant = :header_variant,
                     primary_menu_visibility = :primary_menu_visibility,
                     utility_actions_visibility = :utility_actions_visibility,
                     brand_visibility = :brand_visibility,
                     updated_by_user_id = :updated_by_user_id,
                     updated_at = :updated_at
                 WHERE scope_type = :scope_type
                   AND scope_key = :scope_key'
            );
            $statement->execute([
                ':header_variant' => $settings['header_variant'],
                ':primary_menu_visibility' => $settings['primary_menu_visibility'],
                ':utility_actions_visibility' => $settings['utility_actions_visibility'],
                ':brand_visibility' => $settings['brand_visibility'],
                ':updated_by_user_id' => $updatedByUserId,
                ':updated_at' => $now,
                ':scope_type' => $normalizedType,
                ':scope_key' => $normalizedKey,
            ]);
        } else {
            $statement = $this->pdo->prepare(
                'INSERT INTO navigation_header_overrides (
                    id,
                    scope_type,
                    scope_key,
                    header_variant,
                    primary_menu_visibility,
                    utility_actions_visibility,
                    brand_visibility,
                    updated_by_user_id,
                    created_at,
                    updated_at
                 ) VALUES (
                    :id,
                    :scope_type,
                    :scope_key,
                    :header_variant,
                    :primary_menu_visibility,
                    :utility_actions_visibility,
                    :brand_visibility,
                    :updated_by_user_id,
                    :created_at,
                    :updated_at
                 )'
            );
            $statement->execute([
                ':id' => myronGenerateId('navhdr'),
                ':scope_type' => $normalizedType,
                ':scope_key' => $normalizedKey,
                ':header_variant' => $settings['header_variant'],
                ':primary_menu_visibility' => $settings['primary_menu_visibility'],
                ':utility_actions_visibility' => $settings['utility_actions_visibility'],
                ':brand_visibility' => $settings['brand_visibility'],
                ':updated_by_user_id' => $updatedByUserId,
                ':created_at' => $now,
                ':updated_at' => $now,
            ]);
        }

        $saved = $this->findOverride($normalizedType, $normalizedKey);
        if (!is_array($saved)) {
            throw new RuntimeException('Failed to save navigation header override.');
        }

        return $saved;
    }

    public function deleteOverride(string $scopeType, string $scopeKey): void
    {
        $normalizedType = $this->normalizeScopeType($scopeType);
        $normalizedKey = $this->normalizeScopeKey($normalizedType, $scopeKey);
        if ($normalizedKey === '') {
            return;
        }

        $statement = $this->pdo->prepare(
            'DELETE FROM navigation_header_overrides
             WHERE scope_type = :scope_type
               AND scope_key = :scope_key'
        );
        $statement->execute([
            ':scope_type' => $normalizedType,
            ':scope_key' => $normalizedKey,
        ]);
    }

    /**
     * @param array<string, mixed> $row
     * @return array<string, mixed>
     */
    private function hydrate(array $row): array
    {
        return array_merge(
            [
                'id' => (string) ($row['id'] ?? ''),
                'scope_type' => (string) ($row['scope_type'] ?? ''),
                'scope_key' => (string) ($row['scope_key'] ?? ''),
                'updated_by_user_id' => (string) ($row['updated_by_user_id'] ?? ''),
                'created_at' => (string) ($row['created_at'] ?? ''),
                'updated_at' => (string) ($row['updated_at'] ?? ''),
            ],
            $this->normalizeSettings($row)
        );
    }

    /**
     * @param array<string, mixed> $row
     * @return array<string, string>
     */
    private function normalizeSettings(array $row, bool $strict = false): array
    {
        $settings = [];
        foreach (self::DEFAULTS as $key => $default) {
            $value = trim((string) ($row[$key] ?? $default));
            if (!in_array($value, self::OPTIONS[$key], true)) {
                if ($strict) {
                    throw new InvalidArgumentException('Navigation header override `' . $key . '` is invalid.');
                }
                $value = $default;
            }
            $settings[$key] = $value;
        }

        return $settings;
    }

    private function normalizeScopeType(string $scopeType): string
    {
        $normalized = myronNormalizeSlug($scopeType);
        if (!in_array($normalized, self::SCOPE_TYPES, true)) {
            throw new InvalidArgumentException('Unsupported navigation header override scope.');
        }

        return $normalized;
    }

    private function normalizeScopeKey(string $scopeType, string $scopeKey): string
    {
        $normalized = trim($scopeKey);
        if ($scopeType === 'page') {
            return myronNormalizePath($normalized);
        }

        return substr($normalized, 0, 255);
    }
}
