<?php

namespace classes;

use Exception;
use mysqli;
use objects\orders_o;

class db
{
    public mysqli $conn;
    private string $host;
    private string $user;
    private string $password;
    private string $database;

    public function __construct(array $config)
    {
        $this->host = $config['host'];
        $this->user = $config['user'];
        $this->password = $config['password'];
        $this->database = $config['database'];
    }

    public function connect(): void
    {
        global $response;
        try {
            $this->conn = new mysqli($this->host, $this->user, $this->password, $this->database);
        } catch (Exception $e) {
            $response->internal_server_error($e->getMessage());
        }
    }

    public function escape_string(string $string): string
    {
        return $this->conn->real_escape_string($string);
    }

    public function close(): void
    {
        $this->conn->close();
    }

    public function get(string $table, int $id)
    {
        $sql = "SELECT * FROM $table WHERE id = $id";
        $result = $this->query($sql);
        return $this->fetch_assoc($result);
    }

    public function query(string $sql): \mysqli_result|bool
    {
        // If the connection is not established, connect
        return $this->conn->query($sql);
    }

    public function fetch_assoc($result)
    {
        return $result->fetch_assoc();
    }

    public function list_objects(string $table): array
    {
        $sql = "SELECT * FROM $table";
        $result = $this->query($sql);
        return $this->fetch_all($result);
    }

    public function fetch_all($result)
    {
        return $result->fetch_all(MYSQLI_ASSOC);
    }

    public function list_objects_paginated(string $table, int $page, int $limit): array
    {
        $offset = ($page - 1) * $limit;
        $sql = "SELECT * FROM $table LIMIT $limit OFFSET $offset";
        $result = $this->query($sql);
        return $this->fetch_all($result);
    }

    public function count_objects(string $table): int
    {
        $sql = "SELECT COUNT(*) FROM $table";
        $result = $this->query($sql);
        return $result->fetch_row()[0];
    }

    public function insert_id(): int
    {
        return $this->conn->insert_id;
    }

    public function conn(): mysqli
    {
        return $this->conn;
    }

    public function prepare(string $sql): false|\mysqli_stmt
    {
        return $this->conn->prepare($sql);
    }

    public function num_rows(\mysqli_result|bool $result): int|string
    {
        return $result->num_rows;
    }

    public function getUsername()
    {
        return $this->user;
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function getHost()
    {
        return $this->host;
    }

    public function getDatabase()
    {
        return $this->database;
    }

    public function backupDatabase(string $path): bool
    {
        // Save the database to the path
        $command = "mysqldump -h {$this->host} -u {$this->user} -p{$this->password} {$this->database} > $path";
        exec($command, $output, $return);
        return $return === 0;
    }

    public function getView(string $view): array
    {
        $sql = "SELECT * FROM $view";
        $result = $this->query($sql);
        return $this->fetch_all($result);
    }

    /**
     * Generate a fake ID for a table.
     * Fake ids are not stored in the database, they are generated on every request starting from -1.
     * This is useful for testing purposes.
     * @see orders_o::simulateOrderFromXLVask()
     * @param string $table
     * @return int
     */
    public function getNextFakeId(string $table): int
    {
        // This is a static variable that will be shared across all instances of the class
        static $fakeId = 0; // Start from 0 and decrement on each call
        $fakeId--;
        return $fakeId;
    }


}