<?php


require_once __DIR__ . '/config.php';






function db(): PDO
{
    static $pdo = null;

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

    
    $dataDir = dirname(DB_PATH);
    if (!is_dir($dataDir)) {
        mkdir($dataDir, 0777, true);
    }

    $pdo = new PDO('sqlite:' . DB_PATH);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

    
    $pdo->exec('PRAGMA foreign_keys = ON');

    
    try {
        $busyTimeoutMs = defined('DB_BUSY_TIMEOUT_MS') ? (int)DB_BUSY_TIMEOUT_MS : 3000;
        if ($busyTimeoutMs > 0) {
            $pdo->exec('PRAGMA busy_timeout = ' . $busyTimeoutMs);
        }
    } catch (Throwable $e) {
        
    }

    try {
        if (!defined('DB_ENABLE_WAL') || DB_ENABLE_WAL) {
            $pdo->exec('PRAGMA journal_mode = WAL');
            $pdo->exec('PRAGMA synchronous = NORMAL');
        }
    } catch (Throwable $e) {
        
    }

    
    apply_db_migrations($pdo);

    return $pdo;
}





function apply_db_migrations(PDO $pdo): void
{
    $target = defined('DB_SCHEMA_VERSION') ? (int)DB_SCHEMA_VERSION : 0;
    if ($target <= 0) {
        return;
    }

    try {
        $cur = (int)$pdo->query('PRAGMA user_version')->fetchColumn();
        if ($cur >= $target) {
            return;
        }
    } catch (Throwable $e) {
        return;
    }

    $lockDir = dirname(DB_PATH) . DIRECTORY_SEPARATOR . 'logs';
    if (!is_dir($lockDir)) {
        @mkdir($lockDir, 0777, true);
    }
    $lockFile = $lockDir . DIRECTORY_SEPARATOR . '.db_migrate.lock';
    $fh = @fopen($lockFile, 'c+');
    if (!$fh) {
        return;
    }

    try {
        if (function_exists('flock')) {
            @flock($fh, LOCK_EX);
        }

        $cur = (int)$pdo->query('PRAGMA user_version')->fetchColumn();
        if ($cur >= $target) {
            return;
        }

        
        if ($cur < 1) {
            $pdo->exec("
                CREATE TABLE IF NOT EXISTS password_reset_tokens (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    user_id INTEGER NOT NULL,
                    token TEXT NOT NULL UNIQUE,
                    created_at INTEGER NOT NULL,
                    expires_at INTEGER,
                    FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
                );
            ");
            $pdo->exec("CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_user_id ON password_reset_tokens(user_id);");
            $pdo->exec("CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_expires_at ON password_reset_tokens(expires_at);");
        }

        
        if ($cur < 2) {
            try {
                $pdo->exec("ALTER TABLE categories ADD COLUMN icon_path TEXT;");
            } catch (Throwable $e) {
                
            }
        }

        
        if ($cur < 3) {
            try {
                $pdo->exec("CREATE INDEX IF NOT EXISTS idx_visit_log_time ON visit_log(visit_time);");
            } catch (Throwable $e) {
                
            }
            try {
                $pdo->exec("CREATE INDEX IF NOT EXISTS idx_visit_log_vid_time ON visit_log(visitor_id, visit_time);");
            } catch (Throwable $e) {
                
            }
            try {
                $pdo->exec("CREATE INDEX IF NOT EXISTS idx_visit_log_ip_time ON visit_log(ip, visit_time);");
            } catch (Throwable $e) {
                
            }
        }

        
        if ($cur < 4) {
            try {
                $pdo->exec("
                    CREATE TABLE IF NOT EXISTS media_files (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        type TEXT NOT NULL,
                        path TEXT NOT NULL,
                        original_name TEXT,
                        size INTEGER NOT NULL DEFAULT 0,
                        mime TEXT,
                        uploader_id INTEGER,
                        created_at INTEGER NOT NULL,
                        FOREIGN KEY(uploader_id) REFERENCES users(id)
                    );
                ");
            } catch (Throwable $e) {
                
            }
            try {
                $pdo->exec("CREATE INDEX IF NOT EXISTS idx_media_files_type ON media_files(type);");
                $pdo->exec("CREATE INDEX IF NOT EXISTS idx_media_files_created ON media_files(created_at);");
                $pdo->exec("CREATE INDEX IF NOT EXISTS idx_media_files_uploader ON media_files(uploader_id);");
            } catch (Throwable $e) {
                
            }
        }

        $pdo->exec('PRAGMA user_version = ' . $target);
    } catch (Throwable $e) {
        
    } finally {
        if (function_exists('flock')) {
            @flock($fh, LOCK_UN);
        }
        @fclose($fh);
    }
}
