<?php
header("Content-Type: application/json; charset=utf-8");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Pragma: no-cache");
header("Expires: 0");

if ($_SERVER["REQUEST_METHOD"] === "OPTIONS") {
    http_response_code(200);
    exit();
}

/*
|--------------------------------------------------------------------------
| Upstream API
|--------------------------------------------------------------------------
*/
$upstream = "https://bcast.nrijewellery.com:7768/VOTSBroadcastStreaming/Services/xml/GetLiveRateByTemplateID/nrijewellery?_=" . round(microtime(true) * 1000);

/*
|--------------------------------------------------------------------------
| Cache
|--------------------------------------------------------------------------
*/
$cacheFile = __DIR__ . "/nri_rates_cache.json";
$ttl = 1; // seconds

/*
|--------------------------------------------------------------------------
| Helpers
|--------------------------------------------------------------------------
*/
function outputJson(array $data): void
{
    echo json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
    exit();
}

function readCache(string $cacheFile): ?array
{
    if (!file_exists($cacheFile)) {
        return null;
    }

    $raw = @file_get_contents($cacheFile);
    if ($raw === false || $raw === "") {
        return null;
    }

    $decoded = json_decode($raw, true);
    if (!is_array($decoded)) {
        return null;
    }

    return $decoded;
}

function outputCached(array $cache): void
{
    if (isset($cache["response"]) && is_array($cache["response"])) {
        outputJson($cache["response"]);
    }

    if (isset($cache["ok"])) {
        outputJson($cache);
    }
}

function isPriceToken(string $token): bool
{
    return preg_match('/^\d+\.\d+$/', $token) === 1;
}

function slugify(string $text): string
{
    $text = strtolower(trim($text));
    $text = preg_replace('/[^a-z0-9]+/', '_', $text);
    $text = trim($text, '_');
    return $text ?: 'item';
}

function parseRateLine(string $line): ?array
{
    $line = trim($line);

    if ($line === "") {
        return null;
    }

    $line = preg_replace('/\s+/', ' ', $line);
    $tokens = preg_split('/\s+/', $line);

    if (!$tokens || count($tokens) < 6) {
        return null;
    }

    $code = array_shift($tokens);

    if (!ctype_digit($code)) {
        return null;
    }

    $priceIndexes = [];
    foreach ($tokens as $index => $token) {
        if (isPriceToken($token)) {
            $priceIndexes[] = $index;
        }
    }

    if (count($priceIndexes) < 4) {
        return null;
    }

    $firstPriceIndex = $priceIndexes[0];
    $nameTokens = array_slice($tokens, 0, $firstPriceIndex);
    $priceTokens = array_slice($tokens, $firstPriceIndex, 4);
    $unitTokens = array_slice($tokens, $firstPriceIndex + 4);

    $name = trim(implode(' ', $nameTokens));
    $unit = trim(implode(' ', $unitTokens));

    if ($name === "") {
        return null;
    }

    return [
        "code" => (int)$code,
        "name" => $name,
        "key" => slugify($name),
        "bid" => isset($priceTokens[0]) ? round((float)$priceTokens[0], 2) : null,
        "ask" => isset($priceTokens[1]) ? round((float)$priceTokens[1], 2) : null,
        "high" => isset($priceTokens[2]) ? round((float)$priceTokens[2], 2) : null,
        "low" => isset($priceTokens[3]) ? round((float)$priceTokens[3], 2) : null,
        "unit" => $unit !== "" ? $unit : null
    ];
}

/*
|--------------------------------------------------------------------------
| Use fresh cache if available
|--------------------------------------------------------------------------
*/
$now = microtime(true);
$cached = readCache($cacheFile);

if ($ttl > 0 && $cached && isset($cached["cached_at"])) {
    $cachedAt = (float)$cached["cached_at"];

    if (($now - $cachedAt) < $ttl) {
        outputCached($cached);
    }
}

/*
|--------------------------------------------------------------------------
| Fetch upstream
|--------------------------------------------------------------------------
*/
$ch = curl_init($upstream);

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
    CURLOPT_HTTPHEADER => [
        "User-Agent: Mozilla/5.0",
        "Accept: text/plain, */*"
    ]
]);

$res = curl_exec($ch);
$curlErr = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

/*
|--------------------------------------------------------------------------
| Fallback to cache if upstream fails
|--------------------------------------------------------------------------
*/
if (!$res || $httpCode < 200 || $httpCode >= 300) {
    if ($cached) {
        outputCached($cached);
    }

    outputJson([
        "ok" => false,
        "error" => "Upstream failed",
        "details" => $curlErr ?: "HTTP {$httpCode}"
    ]);
}

/*
|--------------------------------------------------------------------------
| Parse upstream plain text
|--------------------------------------------------------------------------
*/
$lines = preg_split("/\r\n|\n|\r/", trim($res));
$products = [];
$productsByKey = [];

foreach ($lines as $line) {
    $parsed = parseRateLine($line);

    if ($parsed) {
        $products[] = $parsed;
        $productsByKey[$parsed["key"]] = $parsed;
    }
}

if (empty($productsByKey["gold_spot"])) {
    if ($cached) {
        outputCached($cached);
    }

    outputJson([
        "ok" => false,
        "error" => "GOLD SPOT not found",
        "raw" => $res
    ]);
}

$goldSpot = $productsByKey["gold_spot"];

/*
|--------------------------------------------------------------------------
| Final output
|--------------------------------------------------------------------------
| Frontend compatible shape: j.xauusd.ask / bid / high / low
*/
$output = [
    "ok" => true,
    "updated_at" => gmdate("c"),
    "source" => "NRI Jewellery Live Rate",
    "product" => $goldSpot["name"],
    "unit" => $goldSpot["unit"],
    "xauusd" => [
        "ask"  => $goldSpot["ask"],
        "bid"  => $goldSpot["bid"],
        "high" => $goldSpot["high"],
        "low"  => $goldSpot["low"]
    ],
    "products" => $products,
    "products_by_key" => $productsByKey
];

/*
|--------------------------------------------------------------------------
| Save cache
|--------------------------------------------------------------------------
*/
$cachePayload = [
    "cached_at" => $now,
    "response" => $output
];

@file_put_contents(
    $cacheFile,
    json_encode($cachePayload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
    LOCK_EX
);

/*
|--------------------------------------------------------------------------
| Return JSON
|--------------------------------------------------------------------------
*/
outputJson($output);