<?php
// /public_html/test_erp/api/auth/login_action.php
// ============================================================
// Login Action v2.0 — Phase B (TEST Environment)
// Updated: 2026-07-22
// Same as live version — TEST DB এ কাজ করবে
// ============================================================

require_once __DIR__ . '/../../config/session.php';
require_once __DIR__ . '/../../config/db.php';
require_once __DIR__ . '/../../config/response.php';

const MAX_FAILED_ATTEMPTS = 5;
const LOCKOUT_MINUTES     = 15;

function _login_client_ip(): string {
    foreach (['HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'] as $k) {
        if (!empty($_SERVER[$k])) {
            $ip = trim(explode(',', $_SERVER[$k])[0]);
            if (filter_var($ip, FILTER_VALIDATE_IP)) return $ip;
        }
    }
    return '0.0.0.0';
}

function _login_ua_hash(): string {
    return hash('sha256', $_SERVER['HTTP_USER_AGENT'] ?? '');
}

function _login_audit($conn, string $action, int $userId, string $note = ''): void {
    try {
        if (!$conn) return;
        $ip = _login_client_ip();
        $stmt = $conn->prepare(
            "INSERT INTO audit_log (table_name, record_id, action, changed_by, changed_at, ip_address, note)
             VALUES ('users', ?, ?, ?, NOW(), ?, ?)"
        );
        if (!$stmt) return;
        $stmt->bind_param('isiss', $userId, $action, $userId, $ip, $note);
        $stmt->execute();
        $stmt->close();
    } catch (Throwable $e) { /* silent */ }
}

if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    jsonResponse([
        'status'  => 405, 'success' => false,
        'message' => 'শুধু POST অনুরোধ গ্রহণযোগ্য', 'data' => null,
    ], 405);
}

$raw = file_get_contents('php://input');
$json = json_decode($raw, true);
if (!is_array($json)) $json = [];

$email    = trim((string)($json['email']    ?? $_POST['email']    ?? ''));
$password = (string)     ($json['password'] ?? $_POST['password'] ?? '');

if ($email === '' || $password === '') {
    jsonResponse([
        'status'  => 422, 'success' => false,
        'message' => 'ইমেইল এবং পাসওয়ার্ড প্রয়োজন', 'data' => null,
    ], 422);
}

$stmt = $conn->prepare(
    "SELECT id, name, email, password, role, status,
            failed_login_attempts, locked_until
     FROM users
     WHERE email = ? AND is_deleted = 0
     LIMIT 1"
);
if (!$stmt) {
    jsonResponse([
        'status'  => 500, 'success' => false,
        'message' => 'সার্ভার সমস্যা হয়েছে', 'data' => null,
    ], 500);
}
$stmt->bind_param('s', $email);
$stmt->execute();
$result = $stmt->get_result();
$user   = $result ? $result->fetch_assoc() : null;
$stmt->close();

if (!$user) {
    password_verify($password, '$2y$12$NgjAKOaUkKng.sigLrregeMSSZw4PERmCuXrNZIllwKPVXkBiYqm6');
    _login_audit($conn, 'LOGIN', 0, 'Failed login (unknown email): ' . substr($email, 0, 50));
    jsonResponse([
        'status'  => 401, 'success' => false,
        'message' => 'ইমেইল বা পাসওয়ার্ড ভুল!', 'data' => null,
    ], 401);
}

$userId = (int)$user['id'];

if (($user['status'] ?? '') !== 'active') {
    _login_audit($conn, 'LOGIN', $userId, 'Failed login: account inactive');
    jsonResponse([
        'status'  => 403, 'success' => false,
        'message' => 'ইউজার একাউন্ট সক্রিয় নয়', 'data' => null,
    ], 403);
}

if (!empty($user['locked_until'])) {
    $lockedUntil = strtotime($user['locked_until']);
    if ($lockedUntil && $lockedUntil > time()) {
        $remainingMin = (int)ceil(($lockedUntil - time()) / 60);
        _login_audit($conn, 'LOGIN', $userId, "Failed login: account locked ({$remainingMin} min left)");
        jsonResponse([
            'status'  => 423, 'success' => false,
            'message' => "অ্যাকাউন্ট সাময়িকভাবে লক করা হয়েছে। {$remainingMin} মিনিট পর আবার চেষ্টা করুন।",
            'data'    => null,
        ], 423);
    }
    $rs = $conn->prepare("UPDATE users SET locked_until = NULL, failed_login_attempts = 0 WHERE id = ?");
    if ($rs) { $rs->bind_param('i', $userId); $rs->execute(); $rs->close(); }
}

$stored = (string)($user['password'] ?? '');
$isValid = false;
if (strpos($stored, '$2y$') === 0 ||
    strpos($stored, '$2a$') === 0 ||
    strpos($stored, '$2b$') === 0) {
    $isValid = password_verify($password, $stored);
} else {
    $isValid = hash_equals($stored, $password);
    if ($isValid) {
        $newHash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
        $up = $conn->prepare("UPDATE users SET password = ?, password_changed_at = NOW() WHERE id = ?");
        if ($up) { $up->bind_param('si', $newHash, $userId); $up->execute(); $up->close(); }
    }
}

if (!$isValid) {
    $newFailed = (int)$user['failed_login_attempts'] + 1;
    $lockUntilSql = null;
    $note = "Failed login: wrong password (attempt {$newFailed}/" . MAX_FAILED_ATTEMPTS . ")";

    if ($newFailed >= MAX_FAILED_ATTEMPTS) {
        $lockUntilSql = date('Y-m-d H:i:s', time() + (LOCKOUT_MINUTES * 60));
        $note = "Account locked for " . LOCKOUT_MINUTES . " min after {$newFailed} failed attempts";
    }

    $up = $conn->prepare(
        "UPDATE users SET failed_login_attempts = ?, locked_until = ? WHERE id = ?"
    );
    if ($up) {
        $up->bind_param('isi', $newFailed, $lockUntilSql, $userId);
        $up->execute();
        $up->close();
    }
    _login_audit($conn, 'LOGIN', $userId, $note);

    if ($newFailed >= MAX_FAILED_ATTEMPTS) {
        jsonResponse([
            'status'  => 423, 'success' => false,
            'message' => "অনেকবার ভুল হয়েছে। অ্যাকাউন্ট " . LOCKOUT_MINUTES . " মিনিটের জন্য লক করা হয়েছে।",
            'data'    => null,
        ], 423);
    }

    $remaining = MAX_FAILED_ATTEMPTS - $newFailed;
    jsonResponse([
        'status'  => 401, 'success' => false,
        'message' => "ইমেইল বা পাসওয়ার্ড ভুল! আর {$remaining} বার চেষ্টা করতে পারবেন।",
        'data'    => null,
    ], 401);
}

// ---------- Success ----------
session_regenerate_id(true);

$clientIp = _login_client_ip();
$uaHash   = _login_ua_hash();

$_SESSION['user_id']       = $userId;
$_SESSION['user_name']     = (string)$user['name'];
$_SESSION['user_role']     = (string)$user['role'];
$_SESSION['role']          = (string)$user['role'];
$_SESSION['LOGIN_TIME']    = time();
$_SESSION['LAST_ACTIVITY'] = time();
$_SESSION['LAST_REGEN']    = time();
$_SESSION['BIND_IP']       = $clientIp;
$_SESSION['BIND_UA']       = $uaHash;
$_SESSION['csrf_token']    = csrf_rotate_token();

$upd = $conn->prepare(
    "UPDATE users
     SET failed_login_attempts = 0,
         locked_until          = NULL,
         last_login_at         = NOW(),
         last_login_ip         = ?,
         last_login_ua_hash    = ?
     WHERE id = ?"
);
if ($upd) {
    $upd->bind_param('ssi', $clientIp, $uaHash, $userId);
    $upd->execute();
    $upd->close();
}

_login_audit($conn, 'LOGIN', $userId, 'User login successful (TEST env)');
header('X-CSRF-Token: ' . $_SESSION['csrf_token']);

jsonResponse([
    'status'  => 200, 'success' => true,
    'message' => 'লগইন সফল',
    'data'    => [
        'user_id'    => $userId,
        'name'       => (string)$user['name'],
        'role'       => (string)$user['role'],
        'csrf_token' => $_SESSION['csrf_token'],
    ],
], 200);
