<?php
/**
 * license-php/api/verify.php
 * POST /api/license/verify
 * Token & Central License State Verification Endpoint.
 */

require_once __DIR__ . '/../lib/Response.php';
require_once __DIR__ . '/../lib/Database.php';
require_once __DIR__ . '/../lib/LicenseCrypto.php';
require_once __DIR__ . '/../lib/Entitlements.php';
require_once __DIR__ . '/../lib/AuditLogger.php';
require_once __DIR__ . '/../lib/LicenseRepository.php';

Response::handleCors();

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    Response::json(405, ['success' => false, 'message' => 'Method Not Allowed']);
}

$config = require __DIR__ . '/../config/config.php';
$pdo = Database::getConnection($config);
$repo = new LicenseRepository($pdo);
$audit = new AuditLogger($pdo);

$body = Response::getJsonBody();
$token = trim((string)($body['token'] ?? ''));
$domain = LicenseCrypto::cleanDomain($body['domain'] ?? '');
$product = trim((string)($body['product'] ?? $config['product_name']));

if (!$token) {
    Response::json(400, [
        'success' => false,
        'valid'   => false,
        'status'  => 'invalid',
        'message' => 'Token is required'
    ]);
}

// Step 1: Cryptographic signature verification using Public Key
$pubKeyPath = $config['keys']['public'] ?? '';
$publicKeyPem = '';
if ($pubKeyPath && file_exists($pubKeyPath)) {
    $publicKeyPem = file_get_contents($pubKeyPath);
} else {
    $privKeyPath = $config['keys']['private'] ?? '';
    if ($privKeyPath && file_exists($privKeyPath)) {
        $privKey = openssl_pkey_get_private(file_get_contents($privKeyPath));
        if ($privKey) {
            $details = openssl_pkey_get_details($privKey);
            $publicKeyPem = $details['key'] ?? '';
        }
    }
}

if (!$publicKeyPem) {
    Response::json(500, [
        'success' => false,
        'valid'   => false,
        'status'  => 'error',
        'message' => 'Server public key is not configured.'
    ]);
}

$verification = LicenseCrypto::verifyToken($token, $publicKeyPem);
if (!$verification['valid']) {
    Response::json(401, [
        'success' => false,
        'valid'   => false,
        'status'  => 'invalid_signature',
        'message' => 'Invalid or tampered token: ' . ($verification['reason'] ?? 'Signature mismatch')
    ]);
}

$payload = $verification['payload'];

// Step 2: Domain matching
if ($domain && !empty($payload['domain'])) {
    $tokenDomain = LicenseCrypto::cleanDomain($payload['domain']);
    if ($tokenDomain !== $domain) {
        Response::json(403, [
            'success' => false,
            'valid'   => false,
            'status'  => 'domain_mismatch',
            'message' => 'Token domain does not match current domain'
        ]);
    }
}

// Step 3: Expiration check
if (!empty($payload['expires_at'])) {
    $expTime = strtotime($payload['expires_at']);
    if ($expTime !== false && time() > $expTime) {
        Response::json(403, [
            'success' => false,
            'valid'   => false,
            'status'  => 'expired',
            'message' => 'License token has expired'
        ]);
    }
}

// Step 4: Central Database State check
$lic = null;
$lookupId = $payload['license_id'] ?? $payload['sub'] ?? null;
if (!empty($lookupId)) {
    $lic = $repo->findById($lookupId);
}

if (!$lic) {
    $audit->log(null, 'VERIFY_NOT_FOUND', $domain, ['license_id' => $payload['license_id'] ?? null]);
    Response::json(404, [
        'success' => false,
        'valid'   => false,
        'status'  => 'not_found',
        'message' => 'License not found or has been deleted'
    ]);
}

if ($lic['status'] === 'revoked') {
    Response::json(403, [
        'success' => false,
        'valid'   => false,
        'status'  => 'revoked',
        'message' => 'License has been revoked'
    ]);
}

if ($lic['status'] === 'suspended') {
    Response::json(403, [
        'success' => false,
        'valid'   => false,
        'status'  => 'suspended',
        'message' => 'License is suspended'
    ]);
}

if (!empty($lic['domain']) && !empty($payload['domain'])) {
    if (LicenseCrypto::cleanDomain($lic['domain']) !== LicenseCrypto::cleanDomain($payload['domain'])) {
        Response::json(403, [
            'success' => false,
            'valid'   => false,
            'status'  => 'domain_mismatch',
            'message' => 'License has been transferred to another domain'
        ]);
    }
}

$repo->updateLastVerified($lic['id']);

$activePlan = $lic['plan'] ?: ($payload['plan'] ?? 'PRO');
$activeEntitlements = Entitlements::getPlanEntitlements($activePlan, $lic['license_type'] ?? ($payload['license_type'] ?? 'Subscription'));

Response::json(200, [
    'success' => true,
    'valid'   => true,
    'status'  => 'active',
    'message' => 'License is valid',
    'license' => [
        'product'       => $payload['product'] ?? $lic['product'],
        'domain'        => $payload['domain'] ?? $lic['domain'],
        'plan'          => $activePlan,
        'customer_name' => $payload['customer'] ?? $lic['customer_name'],
        'expires_at'    => $payload['expires_at'] ?? $lic['expires_at'],
        'entitlements'  => $activeEntitlements
    ]
]);
