<?php
require __DIR__ . '/bootstrap.php';

use App\Core\Auth;
use App\Core\Csrf;
use App\Core\Database;
use App\Core\Response;
use App\Core\Security;

$admin = Auth::requireRole(['super_admin']);
$pdo = Database::connection();
$input = request_input();
$method = $_SERVER['REQUEST_METHOD'];
$action = $input['action'] ?? 'overview';

function pyrk_int_setting(array $input, string $key, int $min, int $max): int
{
    $value = (int)($input[$key] ?? 0);
    if ($value < $min || $value > $max) {
        Response::error("{$key} must be between {$min} and {$max}.");
    }
    return $value;
}

function pyrk_security_user_select(): string
{
    return 'SELECT u.id, u.full_name, u.email, u.mobile, u.status, u.failed_login_count, u.locked_until, u.last_login_at, u.last_login_ip, u.blocked_at, u.blocked_reason, r.name AS role_name FROM users u JOIN roles r ON r.id = u.role_id';
}

if ($method === 'GET' && $action === 'settings') {
    Response::ok(['settings' => Security::settings()]);
}

if ($method === 'POST' && $action === 'save_settings') {
    Csrf::validateFromRequest();
    $maxFailed = pyrk_int_setting($input, 'max_failed_attempts', 1, 20);
    $lockout = pyrk_int_setting($input, 'lockout_minutes', 1, 1440);
    $sessionTimeout = pyrk_int_setting($input, 'session_timeout_minutes', 5, 1440);

    Security::setSetting('max_failed_attempts', (string)$maxFailed, (int)$admin['id']);
    Security::setSetting('lockout_minutes', (string)$lockout, (int)$admin['id']);
    Security::setSetting('session_timeout_minutes', (string)$sessionTimeout, (int)$admin['id']);
    Security::audit((int)$admin['id'], 'security_settings_updated', 'app_settings', null, [
        'max_failed_attempts' => $maxFailed,
        'lockout_minutes' => $lockout,
        'session_timeout_minutes' => $sessionTimeout,
    ]);
    Response::ok(['settings' => Security::settings()], 'Security settings saved.');
}

if ($method === 'GET' && $action === 'accounts') {
    $q = trim((string)($input['q'] ?? ''));
    $status = trim((string)($input['status'] ?? ''));
    $role = trim((string)($input['role'] ?? ''));
    $where = [];
    $params = [];
    if ($q !== '') {
        $where[] = '(u.full_name LIKE ? OR u.email LIKE ? OR u.mobile LIKE ?)';
        $like = '%' . $q . '%';
        array_push($params, $like, $like, $like);
    }
    if ($status !== '') {
        $where[] = 'u.status = ?';
        $params[] = $status;
    }
    if ($role !== '') {
        $where[] = 'r.name = ?';
        $params[] = $role;
    }
    $sql = pyrk_security_user_select();
    if ($where) {
        $sql .= ' WHERE ' . implode(' AND ', $where);
    }
    $sql .= ' ORDER BY FIELD(u.status,"blocked","inactive","active"), u.full_name ASC LIMIT 300';
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);
    $roles = $pdo->query('SELECT name FROM roles ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);
    Response::ok(['accounts' => $stmt->fetchAll(), 'roles' => $roles]);
}

if ($method === 'GET' && $action === 'login_logs') {
    $q = trim((string)($input['q'] ?? ''));
    $success = (string)($input['success'] ?? '');
    $userId = (int)($input['user_id'] ?? 0);
    $limit = (int)($input['limit'] ?? 100);
    $limit = max(10, min(300, $limit));

    $where = [];
    $params = [];
    if ($q !== '') {
        $where[] = '(ll.email LIKE ? OR ll.ip_address LIKE ? OR u.full_name LIKE ? OR ll.failure_reason LIKE ?)';
        $like = '%' . $q . '%';
        array_push($params, $like, $like, $like, $like);
    }
    if ($success === '1' || $success === '0') {
        $where[] = 'll.success = ?';
        $params[] = (int)$success;
    }
    if ($userId > 0) {
        $where[] = 'll.user_id = ?';
        $params[] = $userId;
    }

    $sql = 'SELECT ll.*, u.full_name, u.status, r.name AS role_name FROM login_logs ll LEFT JOIN users u ON u.id = ll.user_id LEFT JOIN roles r ON r.id = u.role_id';
    if ($where) {
        $sql .= ' WHERE ' . implode(' AND ', $where);
    }
    $sql .= ' ORDER BY ll.login_at DESC, ll.id DESC LIMIT ' . $limit;
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);
    Response::ok(['logs' => $stmt->fetchAll()]);
}

if ($method === 'POST' && $action === 'block') {
    Csrf::validateFromRequest();
    $userId = (int)($input['user_id'] ?? 0);
    $reason = trim((string)($input['reason'] ?? 'Blocked by admin'));
    if (!$userId) Response::error('Missing user id.');
    if ($userId === (int)$admin['id']) Response::error('You cannot block your own account.');

    $stmt = $pdo->prepare('SELECT id, status, email, full_name FROM users WHERE id = ? LIMIT 1');
    $stmt->execute([$userId]);
    $target = $stmt->fetch();
    if (!$target) Response::error('Account not found.', 404);

    $pdo->prepare('UPDATE users SET status = "blocked", locked_until = NULL, failed_login_count = 0, blocked_at = NOW(), blocked_by = ?, blocked_reason = ?, updated_at = NOW() WHERE id = ?')->execute([(int)$admin['id'], $reason, $userId]);
    Security::audit((int)$admin['id'], 'account_blocked', 'users', $userId, ['reason' => $reason], $target);
    Response::ok([], 'Account blocked.');
}

if ($method === 'POST' && $action === 'unblock') {
    Csrf::validateFromRequest();
    $userId = (int)($input['user_id'] ?? 0);
    if (!$userId) Response::error('Missing user id.');

    $stmt = $pdo->prepare('SELECT id, status, email, full_name FROM users WHERE id = ? LIMIT 1');
    $stmt->execute([$userId]);
    $target = $stmt->fetch();
    if (!$target) Response::error('Account not found.', 404);

    $pdo->prepare('UPDATE users SET status = "active", locked_until = NULL, failed_login_count = 0, blocked_at = NULL, blocked_by = NULL, blocked_reason = NULL, updated_at = NOW() WHERE id = ?')->execute([$userId]);
    Security::audit((int)$admin['id'], 'account_unblocked', 'users', $userId, null, $target);
    Response::ok([], 'Account unblocked and set to active.');
}

if ($method === 'POST' && $action === 'reset_lock') {
    Csrf::validateFromRequest();
    $userId = (int)($input['user_id'] ?? 0);
    if (!$userId) Response::error('Missing user id.');
    $pdo->prepare('UPDATE users SET locked_until = NULL, failed_login_count = 0, updated_at = NOW() WHERE id = ?')->execute([$userId]);
    Security::audit((int)$admin['id'], 'account_lock_reset', 'users', $userId);
    Response::ok([], 'Failed attempts and temporary lock reset.');
}

Response::error('Unsupported security action.', 404);
