<?php

namespace App\Libraries;

/**
 * Login Attempt Rate Limiting
 * 
 * Prevents brute force attacks by limiting login attempts
 * Max 5 attempts, then 5 minute lockout
 */
class LoginAttempt
{
    protected $session;
    protected $maxAttempts = 5;
    protected $lockoutTime = 300; // 5 minutes in seconds

    public function __construct()
    {
        $this->session = session();
    }

    /**
     * Get the login attempts key for the current IP
     */
    protected function getKey(): string
    {
        $ip = service('request')->getIPAddress();
        return 'login_attempts_' . md5($ip);
    }

    /**
     * Check if the user is locked out
     */
    public function isLocked(): bool
    {
        $data = $this->session->get($this->getKey());

        if (!$data) {
            return false;
        }

        // Check if lockout time has passed
        if (isset($data['locked_until']) && time() < $data['locked_until']) {
            return true;
        }

        // If lockout time passed, reset attempts
        if (isset($data['locked_until']) && time() >= $data['locked_until']) {
            $this->reset();
            return false;
        }

        return false;
    }

    /**
     * Get remaining lockout time in seconds
     */
    public function getRemainingLockoutTime(): int
    {
        $data = $this->session->get($this->getKey());

        if (!$data || !isset($data['locked_until'])) {
            return 0;
        }

        $remaining = $data['locked_until'] - time();
        return max(0, $remaining);
    }

    /**
     * Get formatted remaining time (e.g., "4 menit 30 detik")
     */
    public function getFormattedRemainingTime(): string
    {
        $seconds = $this->getRemainingLockoutTime();
        
        if ($seconds <= 0) {
            return '';
        }

        $minutes = floor($seconds / 60);
        $secs = $seconds % 60;

        if ($minutes > 0) {
            return "{$minutes} menit " . ($secs > 0 ? "{$secs} detik" : '');
        }

        return "{$secs} detik";
    }

    /**
     * Record a failed login attempt
     */
    public function recordFailedAttempt(): void
    {
        $data = $this->session->get($this->getKey()) ?? ['attempts' => 0];
        $data['attempts']++;
        $data['last_attempt'] = time();

        // Lock if max attempts reached
        if ($data['attempts'] >= $this->maxAttempts) {
            $data['locked_until'] = time() + $this->lockoutTime;
        }

        $this->session->set($this->getKey(), $data);
    }

    /**
     * Reset login attempts (call after successful login)
     */
    public function reset(): void
    {
        $this->session->remove($this->getKey());
    }

    /**
     * Get remaining attempts before lockout
     */
    public function getRemainingAttempts(): int
    {
        $data = $this->session->get($this->getKey());

        if (!$data) {
            return $this->maxAttempts;
        }

        return max(0, $this->maxAttempts - $data['attempts']);
    }

    /**
     * Get current attempt count
     */
    public function getAttemptCount(): int
    {
        $data = $this->session->get($this->getKey());
        return $data['attempts'] ?? 0;
    }
}
