<?php

namespace App\Models;

use Illuminate\Database\Connection;
use Illuminate\Support\Facades\DB;

class CiDatabase
{
    protected static ?self $instance = null;

    protected Connection $connection;
    protected int $lastAffectedRows = 0;

    public static function instance(): self
    {
        return static::$instance ??= new static();
    }

    protected function __construct()
    {
        $this->connection = DB::connection();
    }

    public function table(string $table): CiQueryBuilder
    {
        $normalized = $this->normalizeTableName($table);
        return new CiQueryBuilder($this->connection->table($normalized));
    }

    public function query(string $sql, array $params = []): CiQueryResult
    {
        $trimmed = ltrim($sql);
        if ($trimmed === '') {
            return new CiQueryResult([]);
        }

        $first = strtolower(strtok($trimmed, " \t\n\r\0\x0B") ?: '');

        if ($first === 'select') {
            $rows = $this->connection->select($sql, $params);
            $this->lastAffectedRows = 0;
            return new CiQueryResult($rows);
        }

        $affected = $this->connection->affectingStatement($sql, $params);
        $this->lastAffectedRows = $affected;

        return new CiQueryResult([]);
    }

    public function escape($value): string
    {
        return $this->connection->getPdo()->quote($value);
    }

    public function affectedRows(): int
    {
        return $this->lastAffectedRows;
    }

    public function getFieldNames(string $table): array
    {
        return $this->connection->getSchemaBuilder()->getColumnListing($table);
    }

    protected function normalizeTableName(string $table): string
    {
        $normalized = trim($table);

        if (stripos($normalized, ' as ') !== false) {
            return $normalized;
        }

        if (strpos($normalized, ' ') !== false) {
            [$name, $alias] = preg_split('/\s+/', $normalized, 2);
            return "{$name} as {$alias}";
        }

        return $normalized;
    }
}
