<?php

namespace App\Filters;

use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Config\Services;

class RateLimitFilter implements FilterInterface
{
    protected $request;
    protected $response;
    protected $session;
    protected $limit;
    protected $period;

    public function __construct(int $limit = 3, int $period = 60) // Default: 3 requests per minute
    {
        $this->limit  = $limit;
        $this->period = $period;
        $this->request  = Services::request();
        $this->response = Services::response();
        $this->session  = session();
    }

    public function before(RequestInterface $request, $arguments = null)
    {
        $ipAddress = $request->getIPAddress();
        $key = 'ratelimit_' . $ipAddress;

        $requestCount = $this->session->get($key) ?? 0;
        $lastRequestTime = $this->session->get($key . '_time') ?? 0;

        $currentTime = time();

        // Reset count if the period has passed
        if (($currentTime - $lastRequestTime) > $this->period) {
            $requestCount = 0;
            $this->session->remove($key . '_time');
        }

        // Check if limit is reached
        if ($requestCount >= $this->limit) {
            // Set a rate limit header for client feedback
            $this->response->setHeader('X-RateLimit-Remaining', '0');
            $this->response->setHeader('X-RateLimit-Reset', ($lastRequestTime + $this->period) - $currentTime);

            // Return a response indicating rate limit exceeded
            // Use setResponseCode to set HTTP status code 429 (Too Many Requests)
            return $this->response->setStatusCode(429)->setJSON([
                'success' => false,
                'message' => 'Anda telah melebihi batas permintaan. Silakan coba lagi nanti.',
                'csrf_token' => csrf_hash(),
            ]);
        }

        // Increment request count and update last request time
        $this->session->set($key, $requestCount + 1);
        $this->session->set($key . '_time', $currentTime);

        // Set rate limit headers for successful requests too
        $this->response->setHeader('X-RateLimit-Limit', (string)$this->limit);
        $this->response->setHeader('X-RateLimit-Remaining', (string)($this->limit - ($requestCount + 1)));
        $this->response->setHeader('X-RateLimit-Reset', (string)($this->period - ($currentTime - $lastRequestTime)));

        return null; // Allow request to proceed
    }

    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        // No action needed after the request
    }
}
