<?php

// ============================================================
// config.php — API RRB — Compatible PHP 5.x / 7.x / 8.x
// ============================================================

// ── Base de datos LOCAL (producción) ─────────────────────────
define('DB_HOST',    'localhost');
define('DB_NAME',    'wwsist_rrb5');
define('DB_USER',    'wwsist_mikes');
define('DB_PASS',    'Mikel123*');

// ── Base de datos REMOTA (pruebas) ────────────────────────────
define('DB_REMOTE_HOST', 'rrbteam.biz');
define('DB_REMOTE_NAME', 'xrrbteam_rrb26');
define('DB_REMOTE_USER', 'xrrbteam_mikes5');
define('DB_REMOTE_PASS', 'Mikel123*');

define('JWT_SECRET', 'RRB_SECRET_KEY_2026_CAMBIAR');
define('JWT_EXPIRE', 604800);

// ─────────────────────────────────────────────────────────────
// getDB()
// Lee el token Bearer del request, busca db_remote en la BD
// que corresponde y devuelve la conexión correcta.
// Ambas BDs tienen admin_sessions y usuarios_sist.
// ─────────────────────────────────────────────────────────────
function getDB($forceRemote = null) {
    static $pdoLocal  = null;
    static $pdoRemote = null;

    if ($forceRemote === null) {
        $forceRemote = _dbRemoteFromToken();
    }

    $useRemote = (bool)$forceRemote;

    if ($useRemote) {
        if ($pdoRemote === null) {
            try {
                $pdoRemote = new PDO(
                    'mysql:host=' . DB_REMOTE_HOST . ';dbname=' . DB_REMOTE_NAME . ';charset=utf8mb4',
                    DB_REMOTE_USER,
                    DB_REMOTE_PASS,
                    array(
                        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                        PDO::ATTR_EMULATE_PREPARES   => false,
                    )
                );
            } catch (PDOException $e) {
                http_response_code(500);
                echo json_encode(array('success' => false, 'message' => 'Error de conexion a la base de datos remota.'));
                exit;
            }
        }
        return $pdoRemote;
    }

    if ($pdoLocal === null) {
        try {
            $pdoLocal = new PDO(
                'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4',
                DB_USER,
                DB_PASS,
                array(
                    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES   => false,
                )
            );
        } catch (PDOException $e) {
            http_response_code(500);
            echo json_encode(array('success' => false, 'message' => 'Error de conexion a la base de datos.'));
            exit;
        }
    }
    return $pdoLocal;
}

// Alias para compatibilidad — siempre BD local
function getLocalDB() {
    return getDB(false);
}

// ─────────────────────────────────────────────────────────────
// _dbRemoteFromToken()
// Lee el Bearer token y determina si debe usar BD remota.
// Primero intenta leer el flag desde la BD local (admin_sessions).
// Si el flag es true, confirma con la BD remota.
// ─────────────────────────────────────────────────────────────
function _dbRemoteFromToken() {
    static $cached = null;
    if ($cached !== null) return $cached;

    $token = _extractBearerToken();
    if (!$token) { $cached = false; return false; }

    // Consultar la BD LOCAL primero para leer el flag
    try {
        $pdo = new PDO(
            'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4',
            DB_USER, DB_PASS,
            array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
        );
        $stmt = $pdo->prepare("SELECT db_remote FROM admin_sessions WHERE token = ? AND expira > NOW() LIMIT 1");
        $stmt->execute(array($token));
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row) {
            $cached = (bool)$row['db_remote'];
            return $cached;
        }
    } catch (Exception $e) {}

    $cached = false;
    return false;
}

// ─────────────────────────────────────────────────────────────
// _extractBearerToken()
// ─────────────────────────────────────────────────────────────
function _extractBearerToken() {
    $h = '';

    if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
        $h = $_SERVER['HTTP_AUTHORIZATION'];
    } elseif (!empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
        $h = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
    } elseif (!empty($_SERVER['Authorization'])) {
        $h = $_SERVER['Authorization'];
    }

    if (!$h && function_exists('apache_request_headers')) {
        $hdrs = apache_request_headers();
        if (!empty($hdrs['Authorization'])) $h = $hdrs['Authorization'];
        elseif (!empty($hdrs['authorization'])) $h = $hdrs['authorization'];
    }

    if (!$h && function_exists('getallheaders')) {
        $hdrs = getallheaders();
        if (!empty($hdrs['Authorization'])) $h = $hdrs['Authorization'];
        elseif (!empty($hdrs['authorization'])) $h = $hdrs['authorization'];
    }

    if ($h && strpos($h, 'Bearer ') === 0) {
        return trim(substr($h, 7));
    }
    if (!empty($_GET['token'])) {
        return trim($_GET['token']);
    }
    return '';
}

// --- Funciones de respuesta ---

function jsonOk($data, $code = 200) {
    http_response_code($code);
    echo json_encode(array('success' => true, 'data' => $data));
    exit;
}

function jsonErr($code, $msg) {
    http_response_code($code);
    echo json_encode(array('success' => false, 'message' => $msg));
    exit;
}

// --- Funciones JWT ---

function b64url($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function makeJWT($payload) {
    $h              = b64url(json_encode(array('alg' => 'HS256', 'typ' => 'JWT')));
    $payload['iat'] = time();
    $payload['exp'] = time() + JWT_EXPIRE;
    $p              = b64url(json_encode($payload));
    $sig            = b64url(hash_hmac('sha256', $h . '.' . $p, JWT_SECRET, true));
    return $h . '.' . $p . '.' . $sig;
}

function checkJWT($token) {
    $parts = explode('.', $token);
    if (count($parts) !== 3) return null;
    $expected = b64url(hash_hmac('sha256', $parts[0] . '.' . $parts[1], JWT_SECRET, true));
    if (function_exists('hash_equals')) {
        if (!hash_equals($expected, $parts[2])) return null;
    } else {
        if ($expected !== $parts[2]) return null;
    }
    $data = json_decode(base64_decode(strtr($parts[1], '-_', '+/')), true);
    if (!is_array($data)) return null;
    if (isset($data['exp']) && $data['exp'] < time()) return null;
    return $data;
}

// --- Middleware de autenticacion ---
// Valida el token en la BD correcta (local o remota según el flag)

function auth() {
    $rawToken = _extractBearerToken();
    if (!$rawToken) jsonErr(401, 'Token requerido.');

    $db = getDB(); // ya sabe si usar local o remota

    try {
        $stmt = $db->prepare(
            "SELECT s.idusuarios_sist, u.nombre_usr, u.rango_idrango, s.db_remote
             FROM admin_sessions s
             INNER JOIN usuarios_sist u ON u.idusuarios_sist = s.idusuarios_sist
             WHERE s.token = ? AND s.expira > NOW()
             LIMIT 1"
        );
        $stmt->execute(array($rawToken));
        $session = $stmt->fetch(PDO::FETCH_ASSOC);
    } catch (Exception $e) {
        jsonErr(500, 'Error de autenticacion.');
    }

    if (!$session) jsonErr(401, 'Token invalido o expirado.');

    return array(
        'sub'       => $session['idusuarios_sist'],
        'usr'       => $session['nombre_usr'],
        'rango'     => $session['rango_idrango'],
        'db_remote' => (bool)$session['db_remote'],
    );
}

// --- Leer body JSON ---

function body() {
    $raw = file_get_contents('php://input');
    $d   = json_decode($raw, true);
    return is_array($d) ? $d : array();
}

// --- Calculo de referencia ---

function calcRef($id) {
    $temp   = (int)$id;
    $digits = str_split((string)$temp);
    $len    = count($digits);
    $start2 = ($len % 2 === 0);
    $sum    = 0;
    foreach ($digits as $i => $d) {
        $useTwo = $start2 ? ($i % 2 === 0) : ($i % 2 !== 0);
        $mult   = $useTwo ? 2 : 1;
        $val    = (int)$d * $mult;
        if ($val > 9) {
            $s   = str_split((string)$val);
            $val = (int)$s[0] + (int)$s[1];
        }
        $sum += $val;
    }
    $r = $sum % 10;
    $v = ($r === 0) ? 0 : (10 - $r);
    return (string)$temp . (string)$v;
}

// ============================================================
// CORS y headers
// ============================================================
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Content-Type: application/json; charset=utf-8');

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