<?php
declare(strict_types=1);

require_once __DIR__ . '/../../security/auth_guard.php';
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../../core/Response.php';
require_once __DIR__ . '/../../core/Validator.php';
require_once __DIR__ . '/../../core/Logger.php';

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

Validator::required($data, ['employee_id']);

$employeeId = (int)$data['employee_id'];

$db = Database::getInstance();

/**
 * Prevent self role update
 */
if ($employeeId === (int)$_SESSION['employee_id'] && isset($data['role_id'])) {
    Response::error('You cannot change your own role', 403);
}

/**
 * Get current user role level
 */
$stmt = $db->prepare("
    SELECT r.level
    FROM employees e
    JOIN roles r ON r.id = e.role_id
    WHERE e.id = :id
");
$stmt->execute(['id' => $_SESSION['employee_id']]);
$currentUser = $stmt->fetch();

if (!$currentUser) {
    Response::error('Unauthorized', 401);
}

$currentLevel = (int)$currentUser['level'];

/**
 * Get target employee
 */
$stmt = $db->prepare("
    SELECT e.id, r.level, r.name AS role_name
    FROM employees e
    JOIN roles r ON r.id = e.role_id
    WHERE e.id = :id
");
$stmt->execute(['id' => $employeeId]);
$target = $stmt->fetch();

if (!$target) {
    Response::error('Employee not found', 404);
}

/**
 * Protect Super Admin
 */
if ($target['role_name'] === 'Super Admin') {
    Response::error('Super Admin cannot be updated', 403);
}

/**
 * Role hierarchy enforcement
 */
if ((int)$target['level'] >= $currentLevel) {
    Response::error('You cannot update an employee with equal or higher role', 403);
}

/**
 * Build dynamic update
 */
$allowedFields = ['first_name', 'last_name', 'email', 'mobile', 'password', 'role_id'];
$updateFields = [];
$params = ['id' => $employeeId];

foreach ($allowedFields as $field) {
    if (!isset($data[$field])) {
        continue;
    }

    if ($field === 'email') {
        Validator::email($data['email']);

        // Email uniqueness check
        $stmt = $db->prepare("
            SELECT id FROM employees WHERE email = :email AND id != :id
        ");
        $stmt->execute([
            'email' => $data['email'],
            'id'    => $employeeId
        ]);

        if ($stmt->fetch()) {
            Response::error('Email already exists', 409);
        }

        $updateFields[] = "email = :email";
        $params['email'] = strtolower(trim($data['email']));
    }

    elseif ($field === 'password') {
        Validator::minLength($data['password'], PASSWORD_MIN_LENGTH, 'Password');

        $updateFields[] = "password_hash = :password_hash";
        $params['password_hash'] = password_hash($data['password'], PASSWORD_DEFAULT);
    }

    elseif ($field === 'role_id') {
        $stmt = $db->prepare("SELECT level FROM roles WHERE id = :role_id");
        $stmt->execute(['role_id' => $data['role_id']]);
        $newRole = $stmt->fetch();

        if (!$newRole || (int)$newRole['level'] >= $currentLevel) {
            Response::error('Invalid or higher role assignment', 403);
        }

        $updateFields[] = "role_id = :role_id";
        $params['role_id'] = (int)$data['role_id'];
    }

    else {
        $updateFields[] = "{$field} = :{$field}";
        $params[$field] = trim((string)$data[$field]);
    }
}

if (empty($updateFields)) {
    Response::error('No valid fields provided for update', 422);
}

/**
 * Execute update
 */
$sql = "
    UPDATE employees
    SET " . implode(', ', $updateFields) . ",
        updated_by = :updated_by,
        updated_at = NOW()
    WHERE id = :id
";

$params['updated_by'] = $_SESSION['employee_id'];

$stmt = $db->prepare($sql);
$stmt->execute($params);

Logger::auth('Employee updated', [
    'employee_id' => $employeeId,
    'updated_by'  => $_SESSION['employee_id']
]);

Response::success('Employee updated successfully');
