<?php

declare(strict_types=1);

/**
 * @deprecated APO-170 keeps this repository as a compatibility wrapper for legacy tests/callers.
 * New chrome orchestration work should use MyronNavigationDesignRepository.
 */
final class MyronNavigationDesignSettingsRepository
{
    private const DEFAULTS = [
        'desktop_alignment' => 'split',
        'menu_alignment' => 'right',
        'brand_display' => 'title',
        'brand_subtitle' => '',
        'logo_url' => '',
        'logo_light_url' => '',
        'logo_dark_url' => '',
        'logo_alt' => '',
        'utility_actions_display' => 'auto',
        'appearance_mode_policy' => 'auto',
        'density' => 'comfortable',
        'mobile_mode' => 'takeover',
        'surface_treatment' => 'bordered',
        'position_behavior' => 'static',
    ];

    private const OPTIONS = [
        'desktop_alignment' => ['split', 'centered', 'end'],
        'menu_alignment' => ['left', 'center', 'right'],
        'brand_display' => ['title', 'title-subtitle', 'logo', 'lockup'],
        'utility_actions_display' => ['auto', 'show', 'hide'],
        'appearance_mode_policy' => ['auto', 'light', 'dark'],
        'density' => ['compact', 'comfortable', 'spacious'],
        'mobile_mode' => ['takeover'],
        'surface_treatment' => ['plain', 'bordered', 'elevated'],
        'position_behavior' => ['static', 'sticky'],
    ];

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

    /**
     * @return array<string, string>
     */
    public function getSettings(): array
    {
        if ($this->tableExists('navigation_designs') && function_exists('myronNavigationDesignRepository')) {
            $default = myronNavigationDesignRepository()->getDefault();
            return $this->normalizeSettings($default);
        }

        $this->ensureDefaultRow();

        $statement = $this->pdo->query('SELECT * FROM navigation_design_settings WHERE id = 1 LIMIT 1');
        $row = $statement ? $statement->fetch() : false;

        return $this->normalizeSettings(is_array($row) ? $row : []);
    }

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

    /**
     * @param array<string, mixed> $input
     * @return array<string, string>
     */
    public function saveSettings(array $input, string $updatedByUserId): array
    {
        if ($this->tableExists('navigation_designs') && function_exists('myronNavigationDesignRepository')) {
            $repo = myronNavigationDesignRepository();
            $default = $repo->getDefault();
            $repo->saveVersion((string) ($default['id'] ?? ''), array_merge($default, $input), $updatedByUserId);
            return $this->getSettings();
        }

        $this->ensureDefaultRow();
        $settings = $this->normalizeSettings($input, true);
        $now = myronNow();

        $statement = $this->pdo->prepare(
            'UPDATE navigation_design_settings
                 SET desktop_alignment = :desktop_alignment,
                     menu_alignment = :menu_alignment,
                     brand_display = :brand_display,
                     brand_subtitle = :brand_subtitle,
                     logo_url = :logo_url,
                     logo_light_url = :logo_light_url,
                     logo_dark_url = :logo_dark_url,
                     logo_alt = :logo_alt,
                 utility_actions_display = :utility_actions_display,
                 appearance_mode_policy = :appearance_mode_policy,
                 density = :density,
                 mobile_mode = :mobile_mode,
                 surface_treatment = :surface_treatment,
                 position_behavior = :position_behavior,
                 updated_by_user_id = :updated_by_user_id,
                 updated_at = :updated_at
             WHERE id = 1'
        );

        $statement->execute([
            ':desktop_alignment' => $settings['desktop_alignment'],
            ':menu_alignment' => $settings['menu_alignment'],
            ':brand_display' => $settings['brand_display'],
            ':brand_subtitle' => $settings['brand_subtitle'],
            ':logo_url' => $settings['logo_url'],
            ':logo_light_url' => $settings['logo_light_url'],
            ':logo_dark_url' => $settings['logo_dark_url'],
            ':logo_alt' => $settings['logo_alt'],
            ':utility_actions_display' => $settings['utility_actions_display'],
            ':appearance_mode_policy' => $settings['appearance_mode_policy'],
            ':density' => $settings['density'],
            ':mobile_mode' => $settings['mobile_mode'],
            ':surface_treatment' => $settings['surface_treatment'],
            ':position_behavior' => $settings['position_behavior'],
            ':updated_by_user_id' => $updatedByUserId,
            ':updated_at' => $now,
        ]);

        return $this->getSettings();
    }

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

    private function ensureDefaultRow(): void
    {
        $now = myronNow();
        $statement = $this->pdo->prepare(
            'INSERT INTO navigation_design_settings (
                id,
                desktop_alignment,
                menu_alignment,
                brand_display,
                brand_subtitle,
                logo_url,
                logo_light_url,
                logo_dark_url,
                logo_alt,
                utility_actions_display,
                appearance_mode_policy,
                density,
                mobile_mode,
                surface_treatment,
                position_behavior,
                updated_by_user_id,
                created_at,
                updated_at
             )
             SELECT
                1,
                :desktop_alignment,
                :menu_alignment,
                :brand_display,
                :brand_subtitle,
                :logo_url,
                :logo_light_url,
                :logo_dark_url,
                :logo_alt,
                :utility_actions_display,
                :appearance_mode_policy,
                :density,
                :mobile_mode,
                :surface_treatment,
                :position_behavior,
                \'\',
                :created_at,
                :updated_at
             WHERE NOT EXISTS (
                SELECT 1 FROM navigation_design_settings WHERE id = 1
             )'
        );
        $statement->execute([
            ':desktop_alignment' => self::DEFAULTS['desktop_alignment'],
            ':menu_alignment' => self::DEFAULTS['menu_alignment'],
            ':brand_display' => self::DEFAULTS['brand_display'],
            ':brand_subtitle' => self::DEFAULTS['brand_subtitle'],
            ':logo_url' => self::DEFAULTS['logo_url'],
            ':logo_light_url' => self::DEFAULTS['logo_light_url'],
            ':logo_dark_url' => self::DEFAULTS['logo_dark_url'],
            ':logo_alt' => self::DEFAULTS['logo_alt'],
            ':utility_actions_display' => self::DEFAULTS['utility_actions_display'],
            ':appearance_mode_policy' => self::DEFAULTS['appearance_mode_policy'],
            ':density' => self::DEFAULTS['density'],
            ':mobile_mode' => self::DEFAULTS['mobile_mode'],
            ':surface_treatment' => self::DEFAULTS['surface_treatment'],
            ':position_behavior' => self::DEFAULTS['position_behavior'],
            ':created_at' => $now,
            ':updated_at' => $now,
        ]);
    }

    private function tableExists(string $table): bool
    {
        $driver = (string) $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
        if ($driver === 'sqlite') {
            $statement = $this->pdo->prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = :table");
            $statement->execute([':table' => $table]);
            return $statement->fetchColumn() !== false;
        }

        $statement = $this->pdo->prepare('SHOW TABLES LIKE :table');
        $statement->execute([':table' => $table]);
        return $statement->fetchColumn() !== false;
    }

    /**
     * @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 (isset(self::OPTIONS[$key]) && !in_array($value, self::OPTIONS[$key], true)) {
                if ($strict) {
                    throw new InvalidArgumentException('Navigation setting `' . $key . '` is invalid.');
                }
                $value = $default;
            }
            if (in_array($key, ['brand_subtitle', 'logo_url', 'logo_light_url', 'logo_dark_url', 'logo_alt'], true)) {
                $value = $this->normalizeTextSetting($key, $value, $strict);
            }
            $settings[$key] = $value;
        }

        $hasModeLogoInput = $strict && (array_key_exists('logo_light_url', $row) || array_key_exists('logo_dark_url', $row));
        if (!$hasModeLogoInput && $settings['logo_url'] !== '') {
            $settings['logo_light_url'] = $settings['logo_light_url'] !== '' ? $settings['logo_light_url'] : $settings['logo_url'];
            $settings['logo_dark_url'] = $settings['logo_dark_url'] !== '' ? $settings['logo_dark_url'] : $settings['logo_url'];
        }
        if ($settings['logo_url'] === '' && $settings['logo_light_url'] !== '') {
            $settings['logo_url'] = $settings['logo_light_url'];
        }

        return $settings;
    }

    private function normalizeTextSetting(string $key, string $value, bool $strict): string
    {
        $limits = [
            'brand_subtitle' => 120,
            'logo_url' => 500,
            'logo_light_url' => 500,
            'logo_dark_url' => 500,
            'logo_alt' => 160,
        ];
        $limit = $limits[$key] ?? 255;
        if (strlen($value) > $limit) {
            if ($strict) {
                throw new InvalidArgumentException('Navigation setting `' . $key . '` is too long.');
            }
            $value = substr($value, 0, $limit);
        }

        if (in_array($key, ['logo_url', 'logo_light_url', 'logo_dark_url'], true) && $value !== '' && !$this->isAllowedLogoUrl($value)) {
            if ($strict) {
                throw new InvalidArgumentException('Logo URL must be a site-relative path or http(s) image URL.');
            }
            return '';
        }

        return $value;
    }

    private function isAllowedLogoUrl(string $value): bool
    {
        if (str_starts_with($value, '/') && !str_starts_with($value, '//')) {
            return true;
        }

        $parts = parse_url($value);
        if (!is_array($parts)) {
            return false;
        }

        $scheme = strtolower((string) ($parts['scheme'] ?? ''));
        return in_array($scheme, ['http', 'https'], true) && trim((string) ($parts['host'] ?? '')) !== '';
    }
}
