<?php
ob_start();
header('Content-Type: application/json');

// Enable error logging
ini_set('log_errors', 1);
ini_set('error_log', 'login_debug.log');

function log_debug($msg, $data = null) {
    $line = '[' . date('Y-m-d H:i:s') . '] ' . $msg;
    if ($data !== null) {
        $line .= ' | ' . print_r($data, true);
    }
    error_log($line);
}

/* ───── constants ───────────────────────────────────── */

define('DB_PATH',  __DIR__ . '/.db.db');
define('MASTER_KEY', hex2bin(
    'cd6a83f8d5f85a71dd68898ba867642cf0d5c3b92e2e1bae9fb23a26d60d70bc'
));

const SALT_LEN = 16;
const IV_LEN   = 12;

/* ───── crypto ─────────────────────────────────────── */

function hkdf(string $ikm, string $salt, int $len = 32): string {
    $prk = hash_hmac('sha256', $ikm, $salt, true);
    return substr(hash_hmac('sha256', "\x01", $prk, true), 0, $len);
}

function decrypt_payload(string $b64) {
    $bin = base64_decode($b64, true);
    if ($bin === false || strlen($bin) < SALT_LEN + IV_LEN + 16) {
        log_debug("Decrypt failed: invalid base64 or too short", ['input' => $b64]);
        return false;
    }

    $salt = substr($bin, 0, SALT_LEN);
    $iv   = substr($bin, SALT_LEN, IV_LEN);
    $ct   = substr($bin, SALT_LEN + IV_LEN);
    $tag  = substr($ct, -16);
    $cipher = substr($ct, 0, -16);

    $decrypted = openssl_decrypt(
        $cipher,
        'aes-256-gcm',
        hkdf(MASTER_KEY, $salt),
        OPENSSL_RAW_DATA,
        $iv,
        $tag
    );

    log_debug("Payload decrypted", ['plain' => $decrypted]);
    return $decrypted;
}

function encrypt_payload(string $plain): string {
    $salt = random_bytes(SALT_LEN);
    $iv   = random_bytes(IV_LEN);
    $key  = hkdf(MASTER_KEY, $salt);

    $cipher = openssl_encrypt(
        $plain,
        'aes-256-gcm',
        $key,
        OPENSSL_RAW_DATA,
        $iv,
        $tag
    );

    $encoded = base64_encode($salt . $iv . $cipher . $tag);
    log_debug("Payload encrypted", ['cipher' => $encoded]);
    return $encoded;
}

/* ───── PDO helper ─────────────────────────────────── */

function db(): PDO {
    static $pdo = null;
    if ($pdo) return $pdo;

    $pdo = new PDO(
        'sqlite:' . DB_PATH,
        null,
        null,
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
    );

    // Asegurar que la tabla tenga la columna is_demo
    $pdo->exec('PRAGMA table_info(playlist)');
    $columns = $pdo->query("PRAGMA table_info(playlist)")->fetchAll(PDO::FETCH_ASSOC);
    $hasIsDemo = false;
    foreach ($columns as $column) {
        if ($column['name'] === 'is_demo') {
            $hasIsDemo = true;
            break;
        }
    }
    
    if (!$hasIsDemo) {
        $pdo->exec('ALTER TABLE playlist ADD COLUMN is_demo INTEGER DEFAULT 0');
        log_debug("Added is_demo column to playlist table");
    }

    $pdo->exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_dns_url ON dns(url)');
    $pdo->exec('CREATE INDEX IF NOT EXISTS idx_playlist_mac ON playlist(mac_address)');
    $pdo->exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_playlist_mac_dns ON playlist(mac_address, dns_id)');

    log_debug("Database connection established");
    return $pdo;
}

/* ───── MAC normaliser ─────────────────────────────── */

function normalise_mac(string $raw): string {
    $original = $raw;
    $dec = base64_decode($raw, true);
    if ($dec !== false) $raw = $dec;

    $raw = trim($raw);
    if (strpos($raw, '00:') === 0) $raw = substr($raw, 3);

    $hex = preg_replace('/[^0-9a-fA-F]/', '', $raw);
    $pairs = array_filter(
        str_split($hex, 2),
        fn ($p) => strlen($p) === 2
    );

    $mac = strtoupper(implode(':', $pairs));
    log_debug("MAC normalized", ['original' => $original, 'normalized' => $mac]);
    return $mac;
}

/* ───── request data  ──────────────────────────────── */

$action  = $_POST['action'] ?? '';
$payload = $_POST['data']   ?? '';

log_debug("Incoming request", ['action' => $action, 'raw_payload' => $payload]);

if (!$action || !$payload) {
    http_response_code(400);
    $resp = ['error' => 'Faltan parámetros: action o data'];
    log_debug("Final response", $resp);
    echo json_encode($resp);
    ob_end_flush(); flush();
    exit;
}

$plain = decrypt_payload($payload);
if ($plain === false) {
    http_response_code(400);
    $resp = ['error' => 'Error de descifrado'];
    log_debug("Final response", $resp);
    echo json_encode($resp);
    ob_end_flush(); flush();
    exit;
}

$pdo = db();

/* ───── routing  ───────────────────────────────────── */

switch ($action) {

case 'fetch_dns': {
    $urls = $pdo->query('SELECT url FROM dns ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);
    log_debug("fetch_dns: urls fetched", $urls);

    $json = json_encode($urls, JSON_UNESCAPED_SLASHES);
    $encrypted = encrypt_payload($json);

    log_debug("fetch_dns response encrypted", ['json' => $json, 'encrypted' => $encrypted]);

    header('Content-Length: ' . strlen($encrypted));
    echo $encrypted;

    if (ob_get_level()) ob_end_flush();
    flush();
    break;
}

case 'submit_url': {
    $data = json_decode($plain, true) ?: [];
    $mac  = normalise_mac($data['mac'] ?? '');
    $url  = trim($data['url'] ?? '');

    if (!$mac || !$url) {
        http_response_code(400);
        $resp = ['error' => 'Faltan parámetros: MAC o URL'];
        log_debug("Final response", $resp);
        echo json_encode($resp);
        ob_end_flush(); flush();
        break;
    }

    $parsed = parse_url($url);
    parse_str($parsed['query'] ?? '', $params);

    $username = $params['username'] ?? '';
    $password = $params['password'] ?? '';

    log_debug("Parsed URL", compact('parsed', 'params'));

    if (empty($parsed['scheme']) || empty($parsed['host']) || $username === '' || $password === '') {
        http_response_code(400);
        $resp = ['error' => 'URL inválida o incompleta'];
        log_debug("Final response", $resp);
        echo json_encode($resp);
        ob_end_flush(); flush();
        break;
    }

    $base_url = $parsed['scheme'] . '://' . $parsed['host']
              . (isset($parsed['port']) ? ':' . $parsed['port'] : '');

    $stmt = $pdo->prepare('SELECT id FROM dns WHERE url = ?');
    $stmt->execute([$base_url]);
    $dns_id = $stmt->fetchColumn();

    if (!$dns_id) {
        http_response_code(404);
        $resp = ['error' => 'Servidor DNS no encontrado'];
        log_debug("Final response", $resp);
        echo json_encode($resp);
        ob_end_flush(); flush();
        break;
    }

    $now = time();
    
    // Verificar si ya existe
    $stmt = $pdo->prepare('SELECT COUNT(*) FROM playlist WHERE mac_address = :mac AND dns_id = :dns');
    $stmt->execute([':mac' => $mac, ':dns' => $dns_id]);
    $exists = $stmt->fetchColumn() > 0;

    if ($exists) {
        // Actualizar registro existente - asegurar que sea cliente final
        $stmt = $pdo->prepare(
            'UPDATE playlist 
             SET username = :user, password = :pass, last_used = :now, is_demo = 0 
             WHERE mac_address = :mac AND dns_id = :dns'
        );
        $message = 'Credenciales actualizadas correctamente ✅';
    } else {
        // Insertar nuevo registro - siempre como cliente final
        $stmt = $pdo->prepare(
            'INSERT INTO playlist (dns_id, mac_address, username, password, pin, last_used, is_demo) 
             VALUES (:dns, :mac, :user, :pass, "0000", :now, 0)'
        );
        $message = 'Cuenta activada correctamente ✅';
    }

    $success = $stmt->execute([
        ':dns'  => $dns_id,
        ':mac'  => $mac,
        ':user' => $username,
        ':pass' => $password,
        ':now'  => $now
    ]);

    if ($success) {
        $resp = [
            'status' => 'ok',
            'message' => $message,
            'details' => 'Bienvenido, tu cuenta está activa'
        ];
        log_debug("submit_url success", $resp);
    } else {
        http_response_code(500);
        $resp = ['error' => 'Error al guardar en la base de datos'];
        log_debug("submit_url database error", $resp);
    }

    echo json_encode($resp);
    ob_end_flush(); flush();
    break;
}

case 'check_mac': {
    $data = json_decode($plain, true) ?: [];
    $mac  = normalise_mac($data['mac'] ?? '');

    log_debug("Executing MAC check", ['mac' => $mac]);

    $stmt = $pdo->prepare('SELECT COUNT(*) FROM playlist WHERE mac_address = ?');
    $executed = $stmt->execute([$mac]);

    if (!$executed) {
        log_debug("MAC check query failed to execute", ['mac' => $mac]);
        $exists = false;
    } else {
        $rawCount = $stmt->fetchColumn();
        $count = is_numeric($rawCount) ? (int)$rawCount : 0;
        $exists = $count > 0;
    }

    $resp = [
        'exists' => $exists,
        'message' => $exists ? 'MAC encontrada en el sistema' : 'MAC no registrada'
    ];
    
    $json = json_encode($resp);
    log_debug("check_mac response", ['json' => $json]);

    header('Content-Length: ' . strlen($json));
    echo $json;

    if (ob_get_level()) ob_end_flush();
    flush();
    break;
}

default:
    http_response_code(400);
    $resp = ['error' => 'Acción no válida'];
    log_debug("Final response", $resp);
    echo json_encode($resp);
    ob_end_flush(); flush();
}