<?php

declare(strict_types=1);

final class MyronUpdateSettingsRepository
{
    private const ROW_ID = 'default';

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

    /**
     * @return array<string, mixed>
     */
    public function get(): array
    {
        $statement = $this->pdo->prepare('SELECT * FROM application_update_settings WHERE id = :id LIMIT 1');
        $statement->execute([':id' => self::ROW_ID]);
        $row = $statement->fetch();

        if (!is_array($row)) {
            $defaults = $this->defaults();
            $this->save($defaults);
            return $defaults;
        }

        return [
            'update_channel' => (string) ($row['update_channel'] ?? 'stable'),
            'auto_check_enabled' => (int) ($row['auto_check_enabled'] ?? 1) === 1,
            'auto_check_interval_hours' => max(1, (int) ($row['auto_check_interval_hours'] ?? 24)),
            'check_on_admin_login' => (int) ($row['check_on_admin_login'] ?? 1) === 1,
            'manual_check_cooldown_seconds' => max(0, (int) ($row['manual_check_cooldown_seconds'] ?? 60)),
            'manifest_url' => (string) ($row['manifest_url'] ?? $this->defaultManifestUrl('stable')),
            'updated_at' => (string) ($row['updated_at'] ?? ''),
        ];
    }

    /**
     * @param array<string, mixed> $settings
     */
    public function save(array $settings): void
    {
        $channel = strtolower(trim((string) ($settings['update_channel'] ?? 'stable')));
        if (!in_array($channel, ['beta', 'stable'], true)) {
            $channel = 'stable';
        }

        $manifestUrl = trim((string) ($settings['manifest_url'] ?? ''));
        if ($manifestUrl === '') {
            $manifestUrl = $this->defaultManifestUrl($channel);
        }

        $sql = 'INSERT INTO application_update_settings (
            id,
            update_channel,
            auto_check_enabled,
            auto_check_interval_hours,
            check_on_admin_login,
            manual_check_cooldown_seconds,
            manifest_url,
            updated_at
        ) VALUES (
            :id,
            :update_channel,
            :auto_check_enabled,
            :auto_check_interval_hours,
            :check_on_admin_login,
            :manual_check_cooldown_seconds,
            :manifest_url,
            :updated_at
        )
        ON DUPLICATE KEY UPDATE
            update_channel = VALUES(update_channel),
            auto_check_enabled = VALUES(auto_check_enabled),
            auto_check_interval_hours = VALUES(auto_check_interval_hours),
            check_on_admin_login = VALUES(check_on_admin_login),
            manual_check_cooldown_seconds = VALUES(manual_check_cooldown_seconds),
            manifest_url = VALUES(manifest_url),
            updated_at = VALUES(updated_at)';
        if ($this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME) === 'sqlite') {
            $sql = 'INSERT INTO application_update_settings (
                id,
                update_channel,
                auto_check_enabled,
                auto_check_interval_hours,
                check_on_admin_login,
                manual_check_cooldown_seconds,
                manifest_url,
                updated_at
            ) VALUES (
                :id,
                :update_channel,
                :auto_check_enabled,
                :auto_check_interval_hours,
                :check_on_admin_login,
                :manual_check_cooldown_seconds,
                :manifest_url,
                :updated_at
            )
            ON CONFLICT(id) DO UPDATE SET
                update_channel = excluded.update_channel,
                auto_check_enabled = excluded.auto_check_enabled,
                auto_check_interval_hours = excluded.auto_check_interval_hours,
                check_on_admin_login = excluded.check_on_admin_login,
                manual_check_cooldown_seconds = excluded.manual_check_cooldown_seconds,
                manifest_url = excluded.manifest_url,
                updated_at = excluded.updated_at';
        }

        $statement = $this->pdo->prepare($sql);
        $statement->execute([
            ':id' => self::ROW_ID,
            ':update_channel' => $channel,
            ':auto_check_enabled' => !empty($settings['auto_check_enabled']) ? 1 : 0,
            ':auto_check_interval_hours' => max(1, (int) ($settings['auto_check_interval_hours'] ?? 24)),
            ':check_on_admin_login' => !empty($settings['check_on_admin_login']) ? 1 : 0,
            ':manual_check_cooldown_seconds' => max(0, (int) ($settings['manual_check_cooldown_seconds'] ?? 60)),
            ':manifest_url' => $manifestUrl,
            ':updated_at' => myronNow(),
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    private function defaults(): array
    {
        return [
            'update_channel' => 'stable',
            'auto_check_enabled' => true,
            'auto_check_interval_hours' => 24,
            'check_on_admin_login' => true,
            'manual_check_cooldown_seconds' => 60,
            'manifest_url' => $this->defaultManifestUrl('stable'),
            'updated_at' => myronNow(),
        ];
    }

    private function defaultManifestUrl(string $channel): string
    {
        $configured = trim((string) getenv('MYRON_UPDATE_API_URL'));
        return $configured !== '' ? $configured : 'https://updates.myroncms.com/api/v1/check.php';
    }
}
