<?php

declare(strict_types=1);

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

    public function get(): array
    {
        $this->ensureRow();
        $statement = $this->pdo->query('SELECT * FROM blog_comment_settings WHERE id = 1 LIMIT 1');
        $row = $statement ? $statement->fetch(PDO::FETCH_ASSOC) : false;
        return is_array($row) ? $this->hydrate($row) : $this->defaults();
    }

    public function update(array $data, ?string $actorId = null): array
    {
        $this->ensureRow();
        $settings = array_merge($this->get(), $data);
        $notificationEmailId = $this->nullableNotificationEmailId($settings['notification_email_id'] ?? null);
        $this->assertVerifiedNotificationEmail($notificationEmailId);
        $statement = $this->pdo->prepare(
            'UPDATE blog_comment_settings
             SET comments_enabled = :comments_enabled,
                 default_post_comments_enabled = :default_post_comments_enabled,
                 moderation_required = :moderation_required,
                 notification_email_id = :notification_email_id,
                 updated_by = :updated_by,
                 updated_at = :updated_at
             WHERE id = 1'
        );
        $statement->execute([
            ':comments_enabled' => !empty($settings['comments_enabled']) ? 1 : 0,
            ':default_post_comments_enabled' => !empty($settings['default_post_comments_enabled']) ? 1 : 0,
            ':moderation_required' => !empty($settings['moderation_required']) ? 1 : 0,
            ':notification_email_id' => $notificationEmailId,
            ':updated_by' => $actorId !== null ? trim($actorId) : null,
            ':updated_at' => myronNow(),
        ]);
        return $this->get();
    }

    private function ensureRow(): void
    {
        $statement = $this->pdo->prepare(
            'INSERT INTO blog_comment_settings (
                id, comments_enabled, default_post_comments_enabled, moderation_required,
                notification_email_id, updated_by, updated_at
             )
             SELECT 1, 1, 1, 1, NULL, NULL, :updated_at
             WHERE NOT EXISTS (SELECT 1 FROM blog_comment_settings WHERE id = 1)'
        );
        $statement->execute([':updated_at' => myronNow()]);
    }

    private function nullableNotificationEmailId(mixed $value): ?string
    {
        $value = trim((string) ($value ?? ''));
        return $value === '' || $value === 'none' ? null : $value;
    }

    private function assertVerifiedNotificationEmail(?string $id): void
    {
        if ($id === null) {
            return;
        }

        $statement = $this->pdo->prepare(
            'SELECT verified_at FROM notification_emails WHERE id = :id LIMIT 1'
        );
        $statement->execute([':id' => $id]);
        $verifiedAt = trim((string) ($statement->fetchColumn() ?: ''));
        if ($verifiedAt === '') {
            throw new InvalidArgumentException('Choose a verified destination or leave comment notifications disabled.');
        }
    }

    private function hydrate(array $row): array
    {
        return [
            'comments_enabled' => (int) ($row['comments_enabled'] ?? 1) === 1,
            'default_post_comments_enabled' => (int) ($row['default_post_comments_enabled'] ?? 1) === 1,
            'moderation_required' => (int) ($row['moderation_required'] ?? 1) === 1,
            'notification_email_id' => (string) ($row['notification_email_id'] ?? ''),
            'updated_by' => (string) ($row['updated_by'] ?? ''),
            'updated_at' => (string) ($row['updated_at'] ?? ''),
        ];
    }

    private function defaults(): array
    {
        return [
            'comments_enabled' => true,
            'default_post_comments_enabled' => true,
            'moderation_required' => true,
            'notification_email_id' => '',
            'updated_by' => '',
            'updated_at' => '',
        ];
    }
}
