<?php
declare(strict_types=1);

require_once __DIR__ . '/config.php';

if (!class_exists('CMSMySQLiResultCompat')) {
    class CMSMySQLiResultCompat
    {
        public int $num_rows;
        private array $rows;
        private int $index = 0;

        public function __construct(array $rows)
        {
            $this->rows = array_values($rows);
            $this->num_rows = count($this->rows);
        }

        public function fetch_assoc(): ?array
        {
            if (!isset($this->rows[$this->index])) {
                return null;
            }

            return $this->rows[$this->index++];
        }
    }
}

if (!class_exists('CMSMySQLiStmtCompat')) {
    class CMSMySQLiStmtCompat
    {
        private PDO $pdo;
        private PDOStatement $statement;
        private array $boundValues = [];
        private array $rows = [];

        public function __construct(PDO $pdo, string $sql)
        {
            $this->pdo = $pdo;
            $this->statement = $pdo->prepare($sql);
        }

        public function bind_param(string $types, &...$values): bool
        {
            $this->boundValues = [];
            foreach ($values as &$value) {
                $this->boundValues[] = &$value;
            }

            return true;
        }

        public function execute(?array $params = null): bool
        {
            $executeParams = $params ?? $this->boundValues;
            $result = $this->statement->execute($executeParams);
            $this->rows = $this->statement->fetchAll(PDO::FETCH_ASSOC);

            return $result;
        }

        public function get_result(): CMSMySQLiResultCompat
        {
            return new CMSMySQLiResultCompat($this->rows);
        }

        public function close(): bool
        {
            $this->statement->closeCursor();
            return true;
        }
    }
}

if (!class_exists('CMSMySQLiCompat')) {
    class CMSMySQLiCompat
    {
        public string $connect_error = '';
        private PDO $pdo;

        public function __construct(PDO $pdo)
        {
            $this->pdo = $pdo;
        }

        public function prepare(string $sql): CMSMySQLiStmtCompat
        {
            return new CMSMySQLiStmtCompat($this->pdo, $sql);
        }

        public function query(string $sql): CMSMySQLiResultCompat
        {
            $statement = $this->pdo->query($sql);
            $rows = $statement ? $statement->fetchAll(PDO::FETCH_ASSOC) : [];

            return new CMSMySQLiResultCompat($rows);
        }
    }
}

if (!class_exists('CMSQueryBuilder')) {
    class CMSQueryBuilder
    {
        private PDO $pdo;
        private string $table;
        private array $columns = ['*'];
        private array $whereParts = [];
        private array $params = [];
        private array $orderParts = [];
        private ?int $limitValue = null;

        public function __construct(PDO $pdo, string $table)
        {
            $this->pdo = $pdo;
            $this->table = preg_replace('/[^a-zA-Z0-9_]/', '', $table) ?: $table;
        }

        public function select(array $columns = ['*']): self
        {
            $this->columns = $columns === [] ? ['*'] : $columns;
            return $this;
        }

        public function where(string $column, $value, string $operator = '='): self
        {
            $safeColumn = preg_replace('/[^a-zA-Z0-9_]/', '', $column) ?: $column;
            $paramKey = ':w_' . count($this->params);
            $this->whereParts[] = $safeColumn . ' ' . $operator . ' ' . $paramKey;
            $this->params[$paramKey] = $value;

            return $this;
        }

        public function orderBy(string $column, string $direction = 'ASC'): self
        {
            $safeColumn = preg_replace('/[^a-zA-Z0-9_]/', '', $column) ?: $column;
            $safeDirection = strtoupper($direction) === 'DESC' ? 'DESC' : 'ASC';
            $this->orderParts[] = $safeColumn . ' ' . $safeDirection;

            return $this;
        }

        public function limit(int $limit): self
        {
            $this->limitValue = max(1, $limit);
            return $this;
        }

        public function get(): array
        {
            $sql = 'SELECT ' . implode(', ', $this->columns) . ' FROM ' . $this->table;
            if ($this->whereParts !== []) {
                $sql .= ' WHERE ' . implode(' AND ', $this->whereParts);
            }
            if ($this->orderParts !== []) {
                $sql .= ' ORDER BY ' . implode(', ', $this->orderParts);
            }
            if ($this->limitValue !== null) {
                $sql .= ' LIMIT ' . $this->limitValue;
            }

            return db_all($sql, $this->params);
        }

        public function first(): ?array
        {
            $this->limit(1);
            $rows = $this->get();

            return $rows[0] ?? null;
        }
    }
}

if (!function_exists('cms_db_connect')) {
    function cms_db_connect(?string $rootPath = null): ?PDO
    {
        static $pdo = null;

        if ($pdo instanceof PDO) {
            return $pdo;
        }

        $config = cms_load_config($rootPath);
        $host = (string) ($config['db_host'] ?? '');
        $name = (string) ($config['db_name'] ?? '');
        $user = (string) ($config['db_user'] ?? '');
        $pass = (string) ($config['db_pass'] ?? '');

        if ($host === '' || $name === '' || $user === '') {
            return null;
        }

        try {
            $pdo = new PDO(
                'mysql:host=' . $host . ';dbname=' . $name . ';charset=utf8mb4',
                $user,
                $pass,
                [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES => false,
                ]
            );
        } catch (Throwable $exception) {
            error_log('[CMS DB] Connection failed: ' . $exception->getMessage());
            return null;
        }

        return $pdo;
    }
}

if (!function_exists('cms_boot_db')) {
    function cms_boot_db(?string $rootPath = null): ?PDO
    {
        $pdo = cms_db_connect($rootPath);
        $GLOBALS['db'] = $pdo;
        $GLOBALS['db1'] = $pdo instanceof PDO ? new CMSMySQLiCompat($pdo) : null;

        if ($pdo instanceof PDO) {
            cms_db_ensure_schema($pdo);
            $config = cms_load_config($rootPath);
            if (cms_setting('site_title', '') === '') {
                cms_set_setting('site_title', (string) ($config['site_title'] ?? 'Satta4uMatka'));
            }
            if (cms_setting('active_theme', '') === '') {
                cms_set_setting('active_theme', (string) ($config['active_theme'] ?? 'default'));
            }
        }

        return $pdo;
    }
}

if (!function_exists('db_connection')) {
    function db_connection(): ?PDO
    {
        return $GLOBALS['db'] instanceof PDO ? $GLOBALS['db'] : null;
    }
}

if (!function_exists('db_cache_store')) {
    function &db_cache_store(): array
    {
        if (!isset($GLOBALS['cms_db_cache']) || !is_array($GLOBALS['cms_db_cache'])) {
            $GLOBALS['cms_db_cache'] = [];
        }

        return $GLOBALS['cms_db_cache'];
    }
}

if (!function_exists('db_cache_key')) {
    function db_cache_key(string $sql, array $params = []): string
    {
        return md5($sql . '|' . serialize($params));
    }
}

if (!function_exists('db_cache_flush')) {
    function db_cache_flush(): bool
    {
        $cache = &db_cache_store();
        $cache = [];

        return true;
    }
}

if (!function_exists('db_query')) {
    function db_query(string $sql, array $params = [], int $ttl = 0): ?PDOStatement
    {
        $pdo = db_connection();
        if (!$pdo instanceof PDO) {
            return null;
        }

        $statement = $pdo->prepare($sql);
        $statement->execute($params);

        return $statement;
    }
}

if (!function_exists('db_fetch')) {
    function db_fetch(?PDOStatement $statement): ?array
    {
        if (!$statement instanceof PDOStatement) {
            return null;
        }

        $row = $statement->fetch(PDO::FETCH_ASSOC);
        return $row === false ? null : $row;
    }
}

if (!function_exists('db_all')) {
    function db_all(string $sql, array $params = [], int $ttl = 0): array
    {
        $cacheKey = db_cache_key($sql, $params);
        $cache = &db_cache_store();

        if ($ttl > 0 && isset($cache[$cacheKey]) && $cache[$cacheKey]['expires_at'] >= time()) {
            return $cache[$cacheKey]['rows'];
        }

        $statement = db_query($sql, $params, $ttl);
        if (!$statement instanceof PDOStatement) {
            return [];
        }

        $rows = $statement->fetchAll(PDO::FETCH_ASSOC);

        if ($ttl > 0) {
            $cache[$cacheKey] = [
                'expires_at' => time() + $ttl,
                'rows' => $rows,
            ];
        }

        return $rows;
    }
}

if (!function_exists('db_table')) {
    function db_table(string $table): ?CMSQueryBuilder
    {
        $pdo = db_connection();
        if (!$pdo instanceof PDO) {
            return null;
        }

        return new CMSQueryBuilder($pdo, $table);
    }
}

if (!function_exists('cms_db_ensure_schema')) {
    function cms_db_ensure_schema(PDO $pdo): void
    {
        static $schemaReady = false;

        if ($schemaReady) {
            return;
        }

        $pdo->exec("
            CREATE TABLE IF NOT EXISTS cms_settings (
                setting_key VARCHAR(191) PRIMARY KEY,
                setting_value LONGTEXT NULL,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
            )
        ");

        $pdo->exec("
            CREATE TABLE IF NOT EXISTS cms_pages (
                id INT AUTO_INCREMENT PRIMARY KEY,
                slug VARCHAR(191) NOT NULL UNIQUE,
                title VARCHAR(255) NOT NULL,
                content LONGTEXT NULL,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
            )
        ");

        $schemaReady = true;
    }
}

if (!function_exists('cms_setting')) {
    function cms_setting(string $key, $default = null)
    {
        if (function_exists('cms_db_setting')) {
            return cms_db_setting($key, $default);
        }

        $pdo = db_connection();
        if (!$pdo instanceof PDO) {
            return $default;
        }

        $statement = db_query('SELECT setting_value FROM cms_settings WHERE setting_key = :key LIMIT 1', [':key' => $key], 30);
        $row = db_fetch($statement);

        return $row['setting_value'] ?? $default;
    }
}

if (!function_exists('cms_set_setting')) {
    function cms_set_setting(string $key, string $value): bool
    {
        if (function_exists('cms_set_db_setting')) {
            return cms_set_db_setting($key, $value);
        }

        $pdo = db_connection();
        if (!$pdo instanceof PDO) {
            return false;
        }

        $statement = $pdo->prepare("
            INSERT INTO cms_settings (setting_key, setting_value)
            VALUES (:key, :value)
            ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)
        ");

        return $statement->execute([
            ':key' => $key,
            ':value' => $value,
        ]);
    }
}

if (!function_exists('cms_get_page_by_slug')) {
    function cms_get_page_by_slug(string $slug): ?array
    {
        if (function_exists('cms_get_page_by_slug_wp')) {
            return cms_get_page_by_slug_wp($slug);
        }

        $statement = db_query(
            'SELECT id, slug, title, content FROM cms_pages WHERE slug = :slug LIMIT 1',
            [':slug' => $slug],
            30
        );

        return db_fetch($statement);
    }
}

if (!function_exists('cms_get_pages')) {
    function cms_get_pages(): array
    {
        if (function_exists('cms_get_pages_wp')) {
            return cms_get_pages_wp();
        }

        return db_all('SELECT id, slug, title, content, updated_at FROM cms_pages ORDER BY updated_at DESC', [], 15);
    }
}

if (!function_exists('cms_save_page')) {
    function cms_save_page(array $page): bool
    {
        if (function_exists('cms_save_page_wp')) {
            return cms_save_page_wp($page);
        }

        $pdo = db_connection();
        if (!$pdo instanceof PDO) {
            return false;
        }

        $id = isset($page['id']) ? (int) $page['id'] : 0;
        $slug = strtolower(trim((string) ($page['slug'] ?? '')));
        $slug = preg_replace('/[^a-z0-9\-]/', '-', $slug) ?: '';
        $title = trim((string) ($page['title'] ?? ''));
        $content = (string) ($page['content'] ?? '');

        if ($slug === '' || $title === '') {
            return false;
        }

        if ($id > 0) {
            $statement = $pdo->prepare('UPDATE cms_pages SET slug = :slug, title = :title, content = :content WHERE id = :id');
            return $statement->execute([
                ':id' => $id,
                ':slug' => $slug,
                ':title' => $title,
                ':content' => $content,
            ]);
        }

        $statement = $pdo->prepare('INSERT INTO cms_pages (slug, title, content) VALUES (:slug, :title, :content)');
        return $statement->execute([
            ':slug' => $slug,
            ':title' => $title,
            ':content' => $content,
        ]);
    }
}

if (!function_exists('cms_delete_page')) {
    function cms_delete_page(int $id): bool
    {
        if (function_exists('cms_delete_page_wp')) {
            return cms_delete_page_wp($id);
        }

        $pdo = db_connection();
        if (!$pdo instanceof PDO) {
            return false;
        }

        $statement = $pdo->prepare('DELETE FROM cms_pages WHERE id = :id');
        return $statement->execute([':id' => $id]);
    }
}

cms_boot_db(defined('CMS_ROOT') ? CMS_ROOT : dirname(__DIR__));
