<?php
declare(strict_types=1);

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

/*
|--------------------------------------------------------------------------
| TechStackBase – Admin User Update (AUTHORITATIVE)
|--------------------------------------------------------------------------
*/

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

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

ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(E_ALL);

/* =========================
   AUTH
   ========================= */

$actor = require_auth($pdo);

if (!in_array($actor['role_key'], [
    'super_admin',
    'platform_admin',
    'rsp_admin'
], true)) {
    error_forbidden('Insufficient privileges');
}

/* =========================
   INPUT
   ========================= */

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

if (!is_array($input)) {
    error_bad_request('Invalid JSON payload');
}

$userId        = (int)($input['user_id'] ?? 0);
$newCompanyId  = array_key_exists('company_id', $input) ? (int)$input['company_id'] : null;
$newRole = null;

if (array_key_exists('role_key', $input)) {
    $newRole = trim((string)$input['role_key']);

    if ($newRole === '') {
        $newRole = null;
    } else {
        $newRole = strtolower($newRole);
    }
}
$newStatus     = array_key_exists('status', $input) ? strtolower(trim((string)$input['status'])) : null;
$emailVerified = array_key_exists('email_verified', $input) ? (int)$input['email_verified'] : null;

$newDepartment = null;
if (array_key_exists('department_id', $input)) {
$newDepartment = $input['department_id'] !== '' ? (int)$input['department_id'] : null;
}

$newSection = null;
if (array_key_exists('section_id', $input)) {
$newSection = $input['section_id'] !== '' ? (int)$input['section_id'] : null;
}

$newSupervisor = null;
if (array_key_exists('supervisor_id', $input)) {
$newSupervisor = $input['supervisor_id'] !== '' ? (int)$input['supervisor_id'] : null;
}

if ($userId <= 0) {
    error_bad_request('user_id is required');
}

/* =========================
   LOAD TARGET USER
   ========================= */

$stmt = $pdo->prepare("
SELECT
u.id,
u.company_id,
u.role_key,
u.status,
u.email_verified,
c.rsp_id
FROM users u
JOIN companies c ON c.id = u.company_id
WHERE u.id = ?
AND u.deleted_at IS NULL
LIMIT 1
");

$stmt->execute([$userId]);
$target = $stmt->fetch(PDO::FETCH_ASSOC);

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

/* =========================
   SELF PROTECTION
   ========================= */

if ((int)$actor['id'] === $userId) {

if ($newRole !== null || $newStatus !== null || $newCompanyId !== null) {
error_forbidden('You cannot modify your own account');
}

}

/* =========================
   ROLE HIERARCHY
   ========================= */

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

if ($newRole !== null) {

if (!isset($roleRank[$newRole])) {
error_bad_request('Invalid role');
}

if ($roleRank[$newRole] >= $roleRank[$actor['role_key']]) {
error_forbidden('Cannot assign equal or higher role');
}

}

/* =========================
   RSP ADMIN SCOPE
   ========================= */

if ($actor['role_key'] === 'rsp_admin') {

if ((int)$target['rsp_id'] !== (int)$actor['rsp_id']) {
error_forbidden('User outside your RSP');
}

if ($newRole && in_array($newRole, ['platform_admin','super_admin'], true)) {
error_forbidden('Insufficient privilege');
}

}

/* =========================
   BUILD UPDATE
   ========================= */

$fields = [];
$params = [];

if (array_key_exists('company_id',$input)) {
$fields[] = 'company_id = :company_id';
$params['company_id'] = $newCompanyId;
}

if ($newRole !== null) {

    // Map role_key → role_id
    $stmt = $pdo->prepare("SELECT id FROM roles WHERE role_key = ?");
    $stmt->execute([$newRole]);
    $role = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$role) {
        error_bad_request('Invalid role');
    }

    $fields[] = 'role_id = :role_id';
    $params['role_id'] = (int)$role['id'];
}

if ($newStatus !== null) {
$fields[] = 'status = :status';
$params['status'] = $newStatus;
}

if ($emailVerified !== null) {
$fields[] = 'email_verified = :email_verified';
$params['email_verified'] = $emailVerified;
}

if (array_key_exists('department_id',$input)) {
$fields[] = 'department_id = :department_id';
$params['department_id'] = $newDepartment;
}

if (array_key_exists('section_id',$input)) {
$fields[] = 'section_id = :section_id';
$params['section_id'] = $newSection;
}

if (array_key_exists('supervisor_id', $input)) {
    $fields[] = 'supervisor_id = :supervisor_id';
    $params['supervisor_id'] = $newSupervisor;
}

if (!$fields) {

success('Nothing changed');

}

$params['id'] = $userId;

/* =========================
   TRANSACTION
   ========================= */

$pdo->beginTransaction();

try {

$sql = "UPDATE users SET " . implode(', ', $fields) . " WHERE id = :id";

$pdo->prepare($sql)->execute($params);

$sessionInvalidated = false;

if (
($newStatus !== null && $newStatus !== 'active') ||
$newRole !== null ||
$newCompanyId !== null
) {

invalidate_user_sessions($pdo, $userId);
$sessionInvalidated = true;

}

$pdo->commit();

} catch (Throwable $e) {

$pdo->rollBack();
error_log('ADMIN UPDATE FAILED: ' . $e->getMessage());
error_server('Failed to update user');

}

/* =========================
   AUDIT
   ========================= */

audit_log(
$pdo,
$actor,
'update',
'user',
$userId,
[
'changed' => array_keys($params),
'session_invalidated' => $sessionInvalidated
]
);

/* =========================
   RESPONSE
   ========================= */

success('User updated successfully');