<?php

declare(strict_types=1);

namespace Bot\Infrastructure\Repository\Database;

use Bot\Domain\Entity\Ad;
use Bot\Domain\Repository\AdsRepositoryInterface;
use PDO;

final class DatabaseAdsRepository implements AdsRepositoryInterface
{
    public function __construct(
        private readonly PDO $pdo,
    ) {
    }

    public function findById(int $id): ?Ad
    {
        $stmt = $this->pdo->prepare('SELECT * FROM ads WHERE id = :id');
        $stmt->execute(['id' => $id]);
        $row = $stmt->fetch();

        if ($row === false) {
            return null;
        }

        return $this->rowToAd($row);
    }

    /**
     * @return Ad[]
     */
    public function findByOwnerAdminId(int $ownerAdminId): array
    {
        $stmt = $this->pdo->prepare('SELECT * FROM ads WHERE owner_admin_id = :owner_admin_id ORDER BY id DESC');
        $stmt->execute(['owner_admin_id' => $ownerAdminId]);
        $rows = $stmt->fetchAll();

        $ads = [];
        foreach ($rows as $row) {
            $ads[] = $this->rowToAd($row);
        }

        return $ads;
    }

    /**
     * @return Ad[]
     */
    public function findEnabledByOwnerAdminId(int $ownerAdminId): array
    {
        $stmt = $this->pdo->prepare(
            'SELECT * FROM ads 
             WHERE owner_admin_id = :owner_admin_id AND enabled = 1 
             ORDER BY id DESC'
        );
        $stmt->execute(['owner_admin_id' => $ownerAdminId]);
        $rows = $stmt->fetchAll();

        $ads = [];
        foreach ($rows as $row) {
            $ads[] = $this->rowToAd($row);
        }

        return $ads;
    }

    public function save(Ad $ad): void
    {
        $id = $ad->getId();

        if ($id === 0) {
            // Insert
            $stmt = $this->pdo->prepare(
                'INSERT INTO ads (owner_admin_id, text, banner_url, frequency, enabled)
                 VALUES (:owner_admin_id, :text, :banner_url, :frequency, :enabled)'
            );
            $stmt->execute([
                'owner_admin_id' => $ad->getOwnerAdminId(),
                'text' => $ad->getText(),
                'banner_url' => $ad->getBannerUrl(),
                'frequency' => $ad->getFrequency(),
                'enabled' => $ad->isEnabled() ? 1 : 0,
            ]);
        } else {
            // Update
            $stmt = $this->pdo->prepare(
                'UPDATE ads SET
                    owner_admin_id = :owner_admin_id,
                    text = :text,
                    banner_url = :banner_url,
                    frequency = :frequency,
                    enabled = :enabled
                WHERE id = :id'
            );
            $stmt->execute([
                'id' => $id,
                'owner_admin_id' => $ad->getOwnerAdminId(),
                'text' => $ad->getText(),
                'banner_url' => $ad->getBannerUrl(),
                'frequency' => $ad->getFrequency(),
                'enabled' => $ad->isEnabled() ? 1 : 0,
            ]);
        }
    }

    public function delete(int $id): void
    {
        $stmt = $this->pdo->prepare('DELETE FROM ads WHERE id = :id');
        $stmt->execute(['id' => $id]);
    }

    /**
     * @param array<string,mixed> $row
     */
    private function rowToAd(array $row): Ad
    {
        $ad = new Ad(
            (int) $row['id'],
            (int) $row['owner_admin_id'],
            $row['text'],
            $row['banner_url'] ?? null,
            (int) $row['frequency'],
            (bool) ($row['enabled'] ?? true),
        );

        return $ad;
    }
}

