<?php

declare(strict_types=1);

namespace App\Framework\Database\MaterializedViews;

use App\Framework\Database\Schema\MaterializedView;
use PDO;

/**
 * Service für PostgreSQL Materialized Views Runtime-Operationen
 */
final readonly class MaterializedViewService
{
    public function __construct(
        private PDO $connection
    ) {}

    /**
     * Erstellt eine Materialized View
     */
    public function create(MaterializedView $view): void
    {
        $this->connection->exec($view->toSql());
    }

    /**
     * Refreshed eine Materialized View
     *
     * @param string $name View-Name
     * @param bool $concurrently Concurrent refresh (erfordert UNIQUE index)
     */
    public function refresh(string $name, bool $concurrently = false): void
    {
        $view = new MaterializedView($name, ''); // Query nicht benötigt für refresh
        $this->connection->exec($view->refreshSql($concurrently));
    }

    /**
     * Dropped eine Materialized View
     */
    public function drop(string $name, bool $ifExists = true): void
    {
        $view = new MaterializedView($name, '');
        $this->connection->exec($view->dropSql($ifExists));
    }

    /**
     * Prüft ob eine Materialized View existiert
     */
    public function exists(string $name): bool
    {
        $stmt = $this->connection->prepare("
            SELECT EXISTS (
                SELECT 1
                FROM pg_matviews
                WHERE matviewname = :name
            ) as exists
        ");
        $stmt->execute(['name' => $name]);

        return (bool) $stmt->fetch(PDO::FETCH_ASSOC)['exists'];
    }

    /**
     * Gibt alle Materialized Views zurück
     *
     * @return array<array{name: string, definition: string, has_indexes: bool}>
     */
    public function listAll(): array
    {
        $stmt = $this->connection->query("
            SELECT
                matviewname as name,
                definition,
                hasindexes as has_indexes
            FROM pg_matviews
            ORDER BY matviewname
        ");

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}
