<?php
const UPDATES_STATUS_FILE = "k-api.updates-status.php";
const SQL_UPDATES_FOLDER = "./sql-updates";

/** @param callable(_K_Api): void $apiFun */
function CreateApi(callable $apiFun, bool $devmode = false)
{
    header("Access-Control-Allow-Origin: *");
    header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
    header("Access-Control-Allow-Headers: Content-Type, Authorization");

    if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
        http_response_code(200);
        exit;
    }

    $api = new _K_Api();
    $api->dev_mode = $devmode;
    $apiFun($api);
    $api->end();
}
class _K_Api
{
    private $has_exec = false;
    public $dev_mode = false;
    /** @param callable(_K_ApiRequest): string|array|int|float|bool $fun */
    public function on(string $route, string $method, callable $fun)
    {
        $request_url = (count($_GET) > 0 ? array_keys($_GET)[0] : '');
        $r = str_starts_with($route, '/') ? substr($route, 1) : $route;
        if ($this->has_exec) return;
        if ($r != $request_url) {
            return;
        } else {
            $this->has_exec = true;

            $req_method = $_SERVER['REQUEST_METHOD'];
            if ($req_method != $method) {
                http_response_code(405);
                $_a = "";
                if ($this->dev_mode)
                    $_a = " -  using $req_method, available $method";
                die("ERROR: Method Not Allowed" . $_a);
                return;
            }

            $data = [];
            if ($method == 'GET' && count($_GET) > 1) {
                $data = array_slice(array_keys($_GET), 1);
            } else if ($method == 'POST' && count($_POST) > 0) {
                $data = $_POST;
            }

            $fun = $fun(new _K_ApiRequest($data));
            if (is_string($fun) || is_numeric($fun)) {
                if (json_validate($fun) && !is_numeric($fun)) {
                    Header('Content-Type: application/json');
                }
                echo $fun;
            } else if (is_array($fun) || is_bool($fun)) {
                Header('Content-Type: application/json');
                echo json_encode($fun);
            } else {
                http_response_code(500);
                $_a = "Internal Server Error";
                if ($this->dev_mode) {
                    $_type = gettype($fun);
                    $_a = "unknown return type ($_type), (available bool, array, numeric, string)";
                }
                die("ERROR: " . $_a);
            }

            return;
        }
    }

    public function useUpdates(PDO $db)
    {
        $currentVersion = file_get_contents(UPDATES_STATUS_FILE);
        if ($currentVersion === false) {
            file_put_contents(UPDATES_STATUS_FILE, "<?php // -1");
            $currentVersion = -1;
        } else {
            $currentVersion = intval(substr($currentVersion, 9));
        }
        $files = glob(SQL_UPDATES_FOLDER . '/*.sql');
        $updateVersion = null;
        foreach ($files as $file) {
            if (!is_file($file)) {
                continue;
            }
            $version = intval(basename($file, '.sql'));
            if ($version > $currentVersion) {
                $db->exec(file_get_contents($file));
                $updateVersion = $version;
            }
        }
        if ($updateVersion !== null) {
            file_put_contents(
                UPDATES_STATUS_FILE,
                "<?php // " . $updateVersion
            );
        }
    }

    public function end()
    {
        if (!$this->has_exec) {
            http_response_code(404);
            echo 'ERROR: Not Found';
        }
    }
}

class _K_ApiRequest
{
    public array $data;
    public _K_ApiResponse $res;

    public function __construct(array $data)
    {
        $this->data = $data;
        $this->res = new _K_ApiResponse($this);
    }
    public function hasData(array $dataArr)
    {
        foreach ($dataArr as $i) {
            if (!isset($this->data[$i])) {
                return false;
            }
        }
        return true;
    }
}

class _K_ApiResponse
{
    public function __construct($req) {}
    public function code(int $httpCode)
    {
        http_response_code($httpCode);
    }
}
