<?php

declare(strict_types=1);

namespace App\Infrastructure\Settings;

use App\Domain\Settings\AppSettings;
use App\Domain\Time\Clock;
use App\Infrastructure\Db\RepositoryBase;
use Doctrine\DBAL\Connection;

/**
 * `app_settings` is a tiny key/value table. Booleans are stored as
 * `'1'` / `'0'` strings to keep the column type uniform across drivers.
 */
final class DbAppSettings extends RepositoryBase implements AppSettings
{
    public function __construct(
        Connection $connection,
        private readonly Clock $clock,
    ) {
        parent::__construct($connection);
    }

    public function getBool(string $key, bool $default): bool
    {
        $value = $this->connection()->fetchOne(
            'SELECT value FROM app_settings WHERE key = :key',
            ['key' => $key],
        );
        if ($value === false || $value === null) {
            return $default;
        }

        return (string) $value === '1';
    }

    public function setBool(string $key, bool $value): void
    {
        $now = $this->clock->now()->format('Y-m-d H:i:s');
        $stored = $value ? '1' : '0';

        $exists = (int) $this->connection()->fetchOne(
            'SELECT COUNT(*) FROM app_settings WHERE key = :key',
            ['key' => $key],
        );
        if ($exists > 0) {
            $this->connection()->executeStatement(
                'UPDATE app_settings SET value = :value, updated_at = :updated_at WHERE key = :key',
                ['value' => $stored, 'updated_at' => $now, 'key' => $key],
            );

            return;
        }

        $this->connection()->executeStatement(
            'INSERT INTO app_settings (key, value, updated_at) VALUES (:key, :value, :updated_at)',
            ['key' => $key, 'value' => $stored, 'updated_at' => $now],
        );
    }

    public function all(): array
    {
        $rows = $this->connection()->fetchAllAssociative(
            'SELECT key, value FROM app_settings',
        );
        $out = [];
        foreach ($rows as $row) {
            $out[(string) $row['key']] = $row['value'] === null ? '' : (string) $row['value'];
        }

        return $out;
    }
}
