<?php
/**
 * api/device/activate.php — POST /api/device/activate
 *
 * Canjea un código NUMÉRICO con credenciales embebidas. El código lleva
 * username/password + dns_id (servidor Xtream); al canjearlo se vincula esa
 * playlist al dispositivo (con su flag de protección) y se registra el equipo.
 *
 * - permanent=1: multiuso, no expira (sirve de login del usuario).
 * - permanent=0: un solo uso; si tiene 'expire', se rechaza pasada esa fecha.
 *
 * Request:  { "mac", "code" }
 * Response: { "ok": true }  o  { "ok": false, "error": "..." }
 */

declare(strict_types=1);

require_once __DIR__ . '/../../lib/helpers.php';
require_once __DIR__ . '/../../lib/device.php';

if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
    json_out(['ok' => false, 'error' => 'method_not_allowed'], 405);
}

$body = read_json_body();

$mac = normalize_mac(isset($body['mac']) ? (string) $body['mac'] : null);
if ($mac === null) {
    json_out(['ok' => false, 'error' => 'mac inválida'], 400);
}

// Código: solo dígitos (el modelo nuevo es numérico).
$code = preg_replace('/\D+/', '', (string) ($body['code'] ?? ''));
if ($code === '') {
    json_out(['ok' => false, 'error' => 'código requerido'], 400);
}

try {
    $pdo = db();
    $pdo->beginTransaction();

    // 1. El código debe existir.
    $stmt = $pdo->prepare(
        'SELECT id, username, password, dns_id, name, protected, permanent, expire,
                use_count, device_id, used_at
           FROM activation_codes WHERE code = ? LIMIT 1'
    );
    $stmt->execute([$code]);
    $codeRow = $stmt->fetch();

    if (!$codeRow) {
        $pdo->rollBack();
        json_out(['ok' => false, 'error' => 'código inválido'], 200);
    }

    $permanent = (int) ($codeRow['permanent'] ?? 0) === 1;

    // 2. Validaciones según tipo.
    if (!$permanent) {
        // Un solo uso: no debe estar canjeado.
        if (!empty($codeRow['used_at']) || !empty($codeRow['device_id'])) {
            $pdo->rollBack();
            json_out(['ok' => false, 'error' => 'código ya utilizado'], 200);
        }
    }
    // Expiración (aplica a no permanentes con fecha).
    $expire = trim((string) ($codeRow['expire'] ?? ''));
    if (!$permanent && $expire !== '' && strtotime($expire) !== false && strtotime($expire) < time()) {
        $pdo->rollBack();
        json_out(['ok' => false, 'error' => 'código expirado'], 200);
    }

    // 3. Localizar o crear el dispositivo por MAC.
    $device = device_find_by_mac($mac);
    if ($device === null) {
        $device = device_create($mac, null, null, null);
    }
    $deviceId = (int) $device['id'];

    // 4. Resolver el DNS (servidor) y vincular la playlist Xtream del código.
    $serverUrl = '';
    if (!empty($codeRow['dns_id'])) {
        $dns = $pdo->prepare('SELECT url FROM dns WHERE id = ? LIMIT 1');
        $dns->execute([(int) $codeRow['dns_id']]);
        $serverUrl = (string) ($dns->fetchColumn() ?: '');
    }
    if ($serverUrl !== '' && (string) $codeRow['username'] !== '') {
        bind_credential_to_device($deviceId, [
            'url'       => $serverUrl,
            'username'  => (string) $codeRow['username'],
            'password'  => (string) $codeRow['password'],
            'name'      => (string) ($codeRow['name'] ?: 'Mi Lista'),
            'protected' => (int) ($codeRow['protected'] ?? 0),
        ]);
    }

    // 5. Registrar el dispositivo (propaga la expiración del código si la trae).
    if (!$permanent && $expire !== '') {
        $upd = $pdo->prepare(
            'UPDATE devices SET registered = 1, sub_trial = 0, locked = 0,
                    sub_expire = COALESCE(NULLIF(?, ""), sub_expire) WHERE id = ?'
        );
        $upd->execute([$expire, $deviceId]);
    } else {
        $pdo->prepare('UPDATE devices SET registered = 1, sub_trial = 0, locked = 0 WHERE id = ?')
            ->execute([$deviceId]);
    }

    // 6. Trackeo de uso. Para single-use queda enlazado al dispositivo; para
    //    permanente se cuenta cada canje pero no se bloquea.
    if ($permanent) {
        $pdo->prepare(
            'UPDATE activation_codes SET use_count = use_count + 1,
                    used_at = COALESCE(used_at, ?), device_id = ? WHERE id = ?'
        )->execute([now_iso(), $deviceId, (int) $codeRow['id']]);
    } else {
        $pdo->prepare(
            'UPDATE activation_codes SET use_count = use_count + 1,
                    used_at = ?, device_id = ? WHERE id = ?'
        )->execute([now_iso(), $deviceId, (int) $codeRow['id']]);
    }

    $pdo->commit();
    json_out(['ok' => true], 200);
} catch (Throwable $ex) {
    if (isset($pdo) && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    error_log('[api/device/activate] ' . $ex->getMessage());
    json_out(['ok' => false, 'error' => 'server_error'], 500);
}
