<?php
session_start();
require_once '../config/database.php';

header('Content-Type: application/json');

$input = json_decode(file_get_contents('php://input'), true);
$action = $input['action'] ?? '';

function b64Encode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function b64Decode($str) {
    return base64_decode(strtr($str, '-_', '+/') . str_repeat('=', (4 - strlen($str) % 4) % 4));
}
function jsonErr($msg) {
    echo json_encode(['success' => false, 'error' => $msg]); exit;
}

/* ════════════════════════════════════════
   1. REGISTER — get challenge
   ════════════════════════════════════════ */
if ($action === 'register_challenge') {
    $username = trim($input['username'] ?? '');
    if (!$username) jsonErr('Username required');

    /* Find user */
    $st = $pdo->prepare("SELECT id, name FROM users WHERE (email=? OR username=?) AND status='active' LIMIT 1");
    $st->execute([$username, $username]);
    $user = $st->fetch(PDO::FETCH_ASSOC);
    if (!$user) jsonErr('User not found');

    /* Generate challenge */
    $challenge = b64Encode(random_bytes(32));
    $_SESSION['webauthn_challenge']      = $challenge;
    $_SESSION['webauthn_register_uid']   = $user['id'];

    echo json_encode([
        'success'      => true,
        'challenge'    => $challenge,
        'user_id'      => b64Encode(pack('N', $user['id'])),
        'display_name' => $user['name'],
    ]);
    exit;
}

/* ════════════════════════════════════════
   2. REGISTER — save credential
   ════════════════════════════════════════ */
if ($action === 'register_save') {
    $uid          = $_SESSION['webauthn_register_uid'] ?? null;
    $credentialId = $input['credential_id'] ?? '';
    $publicKey    = $input['public_key']    ?? '';

    if (!$uid || !$credentialId) jsonErr('Missing data');

    try {
        /* Check columns exist, add if not */
        $cols = $pdo->query("SHOW COLUMNS FROM users LIKE 'webauthn_credential_id'")->fetch();
        if (!$cols) {
            $pdo->exec("ALTER TABLE users ADD COLUMN webauthn_credential_id VARCHAR(500) NULL, ADD COLUMN webauthn_public_key TEXT NULL");
        }
        $pdo->prepare("UPDATE users SET webauthn_credential_id=?, webauthn_public_key=? WHERE id=?")
            ->execute([$credentialId, $publicKey, $uid]);
        echo json_encode(['success' => true]);
    } catch (Throwable $e) {
        jsonErr('DB error: ' . $e->getMessage());
    }
    exit;
}

/* ════════════════════════════════════════
   3. AUTHENTICATE — get challenge (by credential id, from localStorage)
   ════════════════════════════════════════ */
if ($action === 'get_challenge') {
    $credentialId = $input['credential_id'] ?? '';
    if (!$credentialId) jsonErr('Credential ID required');

    /* Find user by credential */
    try {
        $st = $pdo->prepare("SELECT id FROM users WHERE webauthn_credential_id=? AND status='active' LIMIT 1");
        $st->execute([$credentialId]);
        $user = $st->fetch(PDO::FETCH_ASSOC);
        if (!$user) jsonErr('Credential not found — please log in with password');
    } catch (Throwable $e) {
        jsonErr('DB error: ' . $e->getMessage());
    }

    $challenge = b64Encode(random_bytes(32));
    $_SESSION['webauthn_challenge']     = $challenge;
    $_SESSION['webauthn_auth_uid']      = $user['id'];

    echo json_encode(['success' => true, 'challenge' => $challenge]);
    exit;
}

/* ════════════════════════════════════════
   3b. AUTHENTICATE — get challenge BY USERNAME
       (works without a localStorage pointer: Safari vs home-screen app,
        or after the browser data was cleared)
   ════════════════════════════════════════ */
if ($action === 'get_challenge_by_user') {
    $username = trim($input['username'] ?? '');
    if (!$username) jsonErr('Username required');

    try {
        $st = $pdo->prepare("SELECT id, webauthn_credential_id FROM users WHERE (email=? OR username=?) AND status='active' LIMIT 1");
        $st->execute([$username, $username]);
        $user = $st->fetch(PDO::FETCH_ASSOC);
        if (!$user) jsonErr('User not found');
        if (empty($user['webauthn_credential_id'])) jsonErr('No biometric is set up for this account yet');
    } catch (Throwable $e) {
        jsonErr('DB error: ' . $e->getMessage());
    }

    $challenge = b64Encode(random_bytes(32));
    $_SESSION['webauthn_challenge'] = $challenge;
    $_SESSION['webauthn_auth_uid']  = $user['id'];

    /* hand back the stored credential id so the client can call navigator.credentials.get */
    echo json_encode([
        'success'       => true,
        'challenge'     => $challenge,
        'credential_id' => $user['webauthn_credential_id'],
    ]);
    exit;
}

/* ════════════════════════════════════════
   4. AUTHENTICATE — verify
   ════════════════════════════════════════ */
if ($action === 'verify') {
    $uid              = $_SESSION['webauthn_auth_uid']  ?? null;
    $storedChallenge  = $_SESSION['webauthn_challenge'] ?? null;
    $clientDataJSON   = $input['client_data_json']      ?? '';
    $challenge        = $input['challenge']             ?? '';

    if (!$uid || !$storedChallenge) jsonErr('Session expired — please try again');
    if ($storedChallenge !== $challenge) jsonErr('Challenge mismatch');

    /* Verify client data */
    $clientData = json_decode(b64Decode($clientDataJSON), true);
    if (!$clientData) jsonErr('Invalid client data');

    $receivedChallenge = $clientData['challenge'] ?? '';
    /* Normalize padding */
    $norm = rtrim(strtr($receivedChallenge, '+/', '-_'), '=');
    if ($norm !== rtrim($storedChallenge, '=')) jsonErr('Challenge verification failed');

    /* Check origin */
    $expectedOrigin = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'];
    if (($clientData['origin'] ?? '') !== $expectedOrigin) {
        /* Allow common variations */
        $origins = [$expectedOrigin, 'https://' . $_SERVER['HTTP_HOST'], 'http://' . $_SERVER['HTTP_HOST']];
        if (!in_array($clientData['origin'] ?? '', $origins)) {
            jsonErr('Origin mismatch — expected ' . $expectedOrigin);
        }
    }

    /* Load user & set session */
    try {
        $st = $pdo->prepare("SELECT * FROM users WHERE id=? AND status='active' LIMIT 1");
        $st->execute([$uid]);
        $user = $st->fetch(PDO::FETCH_ASSOC);
        if (!$user) jsonErr('User not found');

        $_SESSION['user_id']      = $user['id'];
        $_SESSION['name']         = $user['name'];
        $_SESSION['role']         = $user['role'];
        $_SESSION['company_id']   = null;
        $_SESSION['company_name'] = null;
        $_SESSION['staff_role']   = null;

        if (in_array($user['role'], ['company_admin','staff','customer'])) {
            $cs = $pdo->prepare("SELECT cs.company_id,cs.staff_role,c.name AS company_name FROM company_staff cs JOIN companies c ON c.id=cs.company_id WHERE cs.user_id=? LIMIT 1");
            $cs->execute([$uid]);
            $csRow = $cs->fetch(PDO::FETCH_ASSOC);
            if ($csRow) {
                $_SESSION['company_id']   = $csRow['company_id'];
                $_SESSION['company_name'] = $csRow['company_name'];
                $_SESSION['staff_role']   = $csRow['staff_role'];
            }
        }

        /* Determine redirect */
        $ua       = $_SERVER['HTTP_USER_AGENT'] ?? '';
        $isMobile = (bool)preg_match('/android|iphone|ipad|ipod|blackberry|windows phone|mobile/i', $ua);

        $redirect = match($user['role']) {
            'admin'         => '../admin/dashboard.php',
            'company_admin' => $isMobile ? '../customer/dashboard.php' : '../company/dashboard.php',
            'partner'       => '../partner/dashboard.php',
            'customer','staff' => $isMobile ? '../customer/dashboard.php' : '../customer/desktop.php',
            default         => '../auth/login.php',
        };

        /* Clear challenge */
        unset($_SESSION['webauthn_challenge'], $_SESSION['webauthn_auth_uid']);

        echo json_encode(['success' => true, 'redirect' => $redirect]);

    } catch (Throwable $e) {
        jsonErr('Authentication error: ' . $e->getMessage());
    }
    exit;
}

/* ════════════════════════════
   5. REMOVE biometric
════════════════════════════ */
if ($action === 'remove') {
    if (!isset($_SESSION['user_id'])) jsonErr('Not logged in');
    try {
        $pdo->prepare("UPDATE users SET webauthn_credential_id=NULL, webauthn_public_key=NULL WHERE id=?")
            ->execute([(int)$_SESSION['user_id']]);
        echo json_encode(['success' => true]);
    } catch (Throwable $e) { jsonErr('DB error: ' . $e->getMessage()); }
    exit;
}

jsonErr('Unknown action: ' . $action);