<?php
declare(strict_types=1);

require_once __DIR__ . '/../system/bootstrap.php';
require_once __DIR__ . '/../system/auth.php';
require_once __DIR__ . '/../system/response.php';

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

/* =========================
   ROLE HIERARCHY
   ========================= */
$roleRank = [
    'user'           => 1,
    'company_admin'  => 2,
    'rsp_admin'      => 3,
    'platform_admin' => 4,
    'super_admin'    => 5,
];

try {

    /* =========================
       AUTH
       ========================= */
    $actor = require_auth($pdo);
    $actorRole = $actor['role_key'];

    if (!isset($roleRank[$actorRole])) {
        error_forbidden('Invalid actor role');
    }

    /* =========================
       INPUT
       ========================= */
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        error_bad_request('Method not allowed');
    }

    $input = json_decode(file_get_contents('php://input'), true);

    $targetUserId = (int)($input['user_id'] ?? 0);
    $newRole      = (string)($input['role_key'] ?? '');

    if ($targetUserId <= 0 || !isset($roleRank[$newRole])) {
        error_bad_request('Invalid input');
    }

    /* =========================
       LOAD TARGET USER
       ========================= */
    $stmt = $pdo->prepare("
        SELECT id, role_key, company_id
        FROM users
        WHERE id = ?
          AND deleted_at IS NULL
        LIMIT 1
    ");
    $stmt->execute([$targetUserId]);
    $target = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$target) {
        error_not_found('User not found');
    }

    /* =========================
       HARD STOPS
       ========================= */

    // No self role change
    if ((int)$actor['id'] === (int)$target['id']) {
        error_forbidden('You cannot change your own role');
    }

    $actorRank  = $roleRank[$actorRole];
    $targetRank = $roleRank[$target['role_key']];
    $newRank    = $roleRank[$newRole];

    // Actor must outrank target
    if ($actorRank <= $targetRank) {
        error_forbidden('Insufficient privilege');
    }

    // New role must not exceed actor
    if ($newRank >= $actorRank) {
        error_forbidden('Cannot assign equal or higher role');
    }

    /* =========================
       TENANT SCOPING
       ========================= */

    // Company admin: never allowed (redundant safety)
    if ($actorRole === 'company_admin') {
        error_forbidden('Forbidden');
    }

    // RSP admin: only within RSP
    if ($actorRole === 'rsp_admin') {
        if ((int)$actor['company_id'] !== (int)$target['company_id']) {
            error_forbidden('Forbidden');
        }
        if ($newRole === 'platform_admin') {
            error_forbidden('Forbidden');
        }
    }

    // Platform admin: cannot touch super_admin
    if (
        $actorRole === 'platform_admin' &&
        $target['role_key'] === 'super_admin'
    ) {
        error_forbidden('Forbidden');
    }

    /* =========================
       APPLY CHANGE
       ========================= */
    $stmt = $pdo->prepare("
        UPDATE users
        SET role_key = ?
        WHERE id = ?
    ");
    $stmt->execute([$newRole, $targetUserId]);

    /* =========================
       AUDIT
       ========================= */
    auditLog(
        (int)$actor['id'],
        (int)$target['company_id'],
        'users',
        'role_changed',
        [
            'target_user_id' => $targetUserId,
            'old_role' => $target['role_key'],
            'new_role' => $newRole
        ]
    );

    success('Role updated');
    invalidate_user_sessions($pdo, (int)$userId);

} catch (Throwable $e) {
    error_log('ROLE UPDATE ERROR: ' . $e->getMessage());
    error_server('Role update failed');
}
