<?php

/**
 * An extension to the SQLite3 class to add our own logging and binding semantics!
 */
class Database extends SQLite3
{
    public int $count = 0;
    public array $log = [];
    public float $query_time = 0;

    public function __construct(string $db_path)
    {
        parent::__construct($db_path);

        parent::exec('PRAGMA cache_size = 32000');
        parent::exec('PRAGMA journal_mode = WAL');
        parent::exec('PRAGMA temp_store = MEMORY');
    }

    public function query(string $query, array $params = []): SQLite3Result|false
    {
        $p = strpos($query, '?') !== false;
        $stmt = $this->prepare($query);

		foreach ($params ?? [] as $k => $v) $stmt->bindValue($p ? $k + 1 : $k, $v, $this->getSQLiteType($v));

        $start = microtime(true);
        $r = $stmt->execute();
        $this->log($query, microtime(true) - $start);

        return $r;
    }

    public function exec(string $query): bool
    {
        $start = microtime(true);
        $r = parent::exec($query);
        $this->log($query, microtime(true) - $start);
        return $r;
    }

    public function exists(string $table, string $column, mixed $value, bool $case_insensitive = true): bool
    {
        if ($case_insensitive) {
            $query = "SELECT 1 FROM $table WHERE $column = :v COLLATE NOCASE LIMIT 1";
        } else {
            $query = "SELECT 1 FROM $table WHERE $column = :v LIMIT 1";
        }

        $result = $this->query($query, [':v' => $value]);
        return $result->fetchArray(SQLITE3_NUM) !== false;
    }

    private function log(string $query, float $time_taken): void
    {
        $this->count++;
        $this->query_time += $time_taken;

        if (env('debug', false)) $this->log[] = [$query, $time_taken];
    }

    private function getSQLiteType(mixed $value): int
    {
        return match (true) {
            is_int($value)   => SQLITE3_INTEGER,
            is_float($value) => SQLITE3_FLOAT,
            is_null($value)  => SQLITE3_NULL,
            default          => SQLITE3_TEXT
        };
    }
}
