<?php

require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/../vendor/autoload.php';

use Tazeros\Core\API;
use MaxMind\Db\Reader;

// tazeros_sniff_inline_type — определяет MIME по magic-байтам файла для файлов,
// которые стоит отдавать inline (а не attachment): картинки и PDF.
// Вернёт 'image/jpeg|png|gif|webp|bmp|application/pdf' если это такой файл,
// иначе null. Нужно, чтобы CDN-файлы (аватарки мостов, вложения-картинки и
// PDF) отдавались inline с корректным Content-Type, а не application/octet-stream
// + nosniff (иначе браузер/PDF-вьюер отказывается их рисовать: images — в <img>,
// pdf — "Failed to transfer media").
function tazeros_sniff_inline_type($path){
    if(!is_file($path)) return null;
    $fp = @fopen($path, 'rb');
    if(!$fp) return null;
    $head = fread($fp, 16);
    fclose($fp);
    if(strlen($head) < 3) return null;
    if(bin2hex(substr($head,0,3)) === 'ffd8ff') return 'image/jpeg';
    if(substr($head,0,8) === "\x89PNG\x0d\x0a\x1a\x0a") return 'image/png';
    if(substr($head,0,3) === "GIF") return 'image/gif';
    if(substr($head,0,4) === "RIFF" && substr($head,8,4) === "WEBP") return 'image/webp';
    if(substr($head,0,2) === "BM") return 'image/bmp';
    if(substr($head,0,5) === "%PDF-") return 'application/pdf';
    return null;
}

header('Access-Control-Allow-Origin: ' . (isset($_SERVER['HTTP_ORIGIN']) ? htmlspecialchars($_SERVER['HTTP_ORIGIN']) : 'https://tazeros.com'));
header('Access-Control-Allow-Methods: GET, OPTIONS, POST');
header('Access-Control-Allow-Headers: Content-Type, Origin, Authorization, Accept, Cache-Control, X-Requested-With, X-Requested-With, Access-Control-Allow-Credentials, Content-Length');
header('Access-Control-Allow-Credentials: true');
header('X-Content-Type-Options: nosniff');
header('Access-Control-Expose-Headers: Content-Length');

$url = $original_url = trim($_SERVER['REQUEST_URI'], '/');

if(isset($config["static"][$url][0])) $url = $config["static"][$url][0];

foreach ($config["redirects"] as $key => $value) {
    if (preg_match($key, "__tazeros__" . $url)) {
        $url = str_replace('$1', $url, $value);
        break;
    }
}

if (substr_count($url, '?') > 0)
    $url = trim(substr($url, 0, max(strpos($url, '?'), 0)), '/');
if (is_file($config["cdn"] . "/files/" . php_uname("n") . "/" . $url)) {
    $__file = $config["cdn"] . "/files/" . php_uname("n") . "/" . $url;
    // Снифф контента: картинки (аватарки мостов, вложенные изображения CDN)
    // отдаём inline с правильным Content-Type, иначе `application/octet-stream`
    // + `X-Content-Type-Options: nosniff` не дают фронту отрисовать их в <img>.
    $__ct = tazeros_sniff_inline_type($__file);
    if ($__ct !== null) {
        header('Content-Type: ' . $__ct);
        header("Cache-control: public");
        header("Expires: " . gmdate("D, d M Y H:i:s", time() + 86400 * 30) . " GMT");
        readfile($__file);
        die();
    }
    header('Content-Description: File Transfer');
    header("Content-Transfer-Encoding: Binary");
    header("Content-disposition: attachment; filename=\"" . $url . "\"");
    header("Content-type: application/octet-stream");
    echo file_get_contents($__file);
    die();
}

$url = explode('/', $url);
if (count($url) >= 2 && $url[0] == "odata")
    $url = array("vizs", "data", "aggregate", $url[1], "odata", isset($url[2]) ? $url[2] : NULL);
if (count($url) >= 2 && $url[0] == "data")
    $url = array("vizs", "data", "aggregate", $url[1]);
if (isset($_GET["url"]))
    $url = array("cdn", "main", "index");
if (count($url) == 1 && substr_count($url[0], "-") == 4)
    $url = array("cdn", "main", "index", $url[0]);

header('Content-type: application/json');

if (count($url) >= 3) {
    $_POST['module'] = $url[0];
    $_POST['controller'] = $url[1];
    $_POST['method'] = $url[2];
}

$module = isset($_POST['module']) ? $_POST['module'] : 'none';
$controller = isset($_POST['controller']) ? $_POST['controller'] : 'none';
$method = isset($_POST['method']) ? $_POST['method'] : 'none';
$attributes = isset($config["static"][$original_url][1]) ? $config["static"][$original_url][1] : (isset($_POST['attributes']) ? json_decode($_POST['attributes'], TRUE) : array());

// Fallback for JSON body upload (bypasses Suhosin POST value limits).
// Used by TCode Go client for large knowledge graph uploads.
if (empty($attributes) && $_SERVER['REQUEST_METHOD'] === 'POST' && ($_SERVER['CONTENT_TYPE'] ?? '') === 'application/json') {
    $raw = @file_get_contents('php://input');
    if ($raw !== false) {
        $parsed = @json_decode($raw, true);
        if (is_array($parsed)) {
            $attributes = $parsed;
        }
    }
}
$token = isset($config["static"][$original_url][2]) ? $config["static"][$original_url][2] : (isset($_GET["token"]) ? $_GET["token"] : (isset($_POST['token']) ? $_POST['token'] : (isset($_COOKIE["token"]) ? $_COOKIE["token"] : "none")));
$cache = isset($_POST['cache']) ? intval($_POST['cache']) : (isset($_GET["cache"]) ? intval($_GET["cache"]) : 0);

if (!isset($attributes['url']) || !is_string($attributes['url']) || !preg_match('~^https?://~', $attributes['url'])) {
    $attributes["url"] = $url;
}

if (substr_count($config["router"][$module . "_" . $controller], "Daemon") > 0) die('{"state": 404,"response": null,"message": "Function not found","documentation": "https://tazeros.com/docs/backend"}');

if (!isset($_SERVER["HTTP_USER_AGENT"]))
    $_SERVER["HTTP_USER_AGENT"] = "";
$attributes["environment"] = array(
    "time" => microtime(true),
    "host" => !empty($_SERVER["HTTP_HOST"]) ? strtr(trim(htmlspecialchars($_SERVER["HTTP_HOST"])), array("www." => "", ".local" => ".com")) : NULL,
    "real_host" => !empty($_SERVER["HTTP_HOST"]) ? trim(htmlspecialchars($_SERVER["HTTP_HOST"])) : NULL,
    "origin" => !empty($_SERVER["HTTP_ORIGIN"]) ? strtr(trim(htmlspecialchars($_SERVER["HTTP_ORIGIN"])), array("https://" => "", "http://" => "")) : NULL,
    "real_origin" => !empty($_SERVER["HTTP_HOST"]) ? trim(htmlspecialchars($_SERVER["HTTP_HOST"])) : NULL,
    "timezone" => date_default_timezone_get(),
);
if (isset($_SERVER['HTTP_CLIENT_IP']))
    $attributes["environment"]["ip"] = $_SERVER['HTTP_CLIENT_IP'];
else if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
    $attributes["environment"]["ip"] = $_SERVER['HTTP_X_FORWARDED_FOR'];
else if (isset($_SERVER['HTTP_X_FORWARDED']))
    $attributes["environment"]["ip"] = $_SERVER['HTTP_X_FORWARDED'];
else if (isset($_SERVER['HTTP_FORWARDED_FOR']))
    $attributes["environment"]["ip"] = $_SERVER['HTTP_FORWARDED_FOR'];
else if (isset($_SERVER['HTTP_FORWARDED']))
    $attributes["environment"]["ip"] = $_SERVER['HTTP_FORWARDED'];
else if (isset($_SERVER['REMOTE_ADDR']))
    $attributes["environment"]["ip"] = $_SERVER['REMOTE_ADDR'];
else
    $attributes["environment"]["ip"] = '127.0.0.1';

$attributes["environment"]["ip"] = explode(",", $attributes["environment"]["ip"]);
$attributes["environment"]["ip"] = trim($attributes["environment"]["ip"][0]);
$attributes["environment"]["ip"] = strtr($attributes["environment"]["ip"], array('::1' => '127.0.0.1'));
if (substr_count($attributes["environment"]["ip"], "172.16.10.") > 0) $attributes["environment"]["ip"] = "95.84.138.196";

$attributes["environment"]["api_host"] = $attributes["environment"]["origin"] == "tazeros.local" ? "https://api.tazeros.local" : ($attributes["environment"]["host"] == "mediazoom.co" ? "https://api11.mediazoom.co" : "https://api11.tazeros.com");

if (in_array($attributes["environment"]["ip"], $config["blacklisted_ip"]))
    die('{"state":429, "message":"Your IP address has been blocked", "documentation":"https://tazeros.com/docs/backend"}');

$reader = new MaxMind\Db\Reader(__DIR__ . '/../assets/Core/cities.mmdb');
$geoip = $reader->get($attributes["environment"]["ip"]);
$attributes["environment"]["geoip"] = array(
    "continent_code" => isset($geoip["continent"]["code"]) ? $geoip["continent"]["code"] : NULL,
    "country_code" => isset($geoip["country"]["iso_code"]) ? $geoip["country"]["iso_code"] : NULL,
    //"country_code3": "USA",
    "country_name" => isset($geoip["country"]["names"]["en"]) ? $geoip["country"]["names"]["en"] : NULL,
    //"region": "NJ",
    "city" => isset($geoip["city"]["names"]["en"]) ? $geoip["city"]["names"]["en"] : NULL,
    "postal_code" => isset($geoip["postal"]["code"]) ? $geoip["postal"]["code"] : NULL,
    "latitude" => isset($geoip["location"]["latitude"]) ? $geoip["location"]["latitude"] : NULL,
    "longitude" => isset($geoip["location"]["longitude"]) ? $geoip["location"]["longitude"] : NULL,
    // "dma_code": 504,
    // "area_code": 609
);

if ($attributes["environment"]["real_host"] == "api.tazeros.com") {
    echo json_encode($attributes["environment"]);
    die();
}
if(isset($attributes["_redirect"]) && $attributes["_redirect"] == "https://api12.tazeros.com"){
    $host = $attributes["_redirect"];
    unset($attributes["_redirect"]);
}else{
    $host = "https://" . php_uname("n") . ".tazeros.com";
}
header('X-Tazeros-API: ' . $module . '/' . $controller . '/' . $method);
$log_attributes = isset($_POST['attributes']) ? (string)$_POST['attributes'] : json_encode($attributes, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if (strlen($log_attributes) > 512) {
    $log_attributes = substr($log_attributes, 0, 512) . '…';
}
$log_post = http_build_query(array(
    'module' => $module,
    'controller' => $controller,
    'method' => $method,
    'cache' => $cache,
    'attributes' => $log_attributes,
));
if (strlen($log_post) > 2048) {
    $log_post = substr($log_post, 0, 2048) . '…';
}
header('X-Tazeros-POST: ' . $log_post);
$response = API::call($module, $controller, $method, $attributes, $token, $cache, $host);

$json_flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
if (isset($_GET["pretty"]))
    $json_flags |= JSON_PRETTY_PRINT;

if (isset($response['response']['state']) && $response['response']['state'] >= 300 && $response['response']['state'] <= 310) {
    header('Location: ' . $response['response']['data']);
} elseif (isset($response["response"]["state"]) && $response["response"]["state"] == 206 && isset($response["response"]["data"])) {
    echo json_encode($response["response"]["data"], $json_flags);
} elseif (isset($response["response"]["state"]) && $response["response"]["state"] == 205 && isset($response["response"]["data"])) {
    header('Content-type: ' . ($response['response']['content_type'] ?? 'audio/wav'));
    if (isset($response['response']['content_headers']) && is_array($response['response']['content_headers'])) {
        foreach ($response['response']['content_headers'] as $h) {
            header($h);
        }
    }
    if (isset($response['response']['content_disposition']))
        header('Content-Disposition: ' . $response['response']['content_disposition']);
    echo $response["response"]["data"];
} elseif (isset($response["response"]["state"]) && $response["response"]["state"] == 204) {
} else {
    echo json_encode($response, $json_flags);
}
