<?php

namespace App\Controllers\View;

use App\Controllers\BaseController;
use App\Models\IpAttemptModel;

class IpBanController extends BaseController
{
    protected $ipAttemptModel;

    public function __construct()
    {
        $this->ipAttemptModel = new IpAttemptModel();
        helper(['url', 'form']);
    }

    public function index()
    {
        $now = utc_now();
        $status = strtolower(trim((string)($this->request->getGet('status') ?? 'all')));

        $builder = $this->ipAttemptModel->orderBy('updated_at', 'DESC');
        if ($status === 'active') {
            $builder = $builder->where('blocked_until >', $now);
        }

        $banned = $builder->findAll();

        return view('administrator/ip_bans', [
            'banned' => $banned,
            'status' => $status,
            'now'    => $now,
        ]);
    }

    public function unban()
    {
        $isAjax = $this->request->isAJAX();
        $json = function(array $p, int $code=200){
            $p['csrfTokenName'] = csrf_token();
            $p['csrfHash'] = csrf_hash();
            $p[csrf_token()] = csrf_hash();
            return $this->response->setStatusCode($code)->setJSON($p);
        };

        $id  = (int) $this->request->getPost('id');
        $ip  = trim((string) $this->request->getPost('ip'));
        $all = (int) $this->request->getPost('all') === 1;

        try {
            if ($all) {
                // Clear all active bans
                $now = utc_now();
                $builder = $this->ipAttemptModel->builder();
                $builder->where('blocked_until >', $now)
                    ->set(['blocked_until' => null, 'attempts' => 0])
                    ->update();

                $cnt = $this->ipAttemptModel->db->affectedRows();
                $msg = $cnt . ' IP(s) unbanned.';
                return $isAjax ? $json(['ok'=>true,'message'=>$msg,'count'=>$cnt])
                               : redirect()->to(site_url('administrator/ip_bans'))->with('success', $msg);
            }

            $row = null;
            if ($id > 0) {
                $row = $this->ipAttemptModel->find($id);
            } elseif ($ip !== '') {
                $row = $this->ipAttemptModel->where('ip_address', $ip)->first();
            }

            if (!$row) {
                $msg = 'IP record not found.';
                return $isAjax ? $json(['ok'=>false,'message'=>$msg],404)
                               : redirect()->back()->with('error', $msg);
            }

            $ok = $this->ipAttemptModel->update($row['id'], [
                'blocked_until' => null,
                'attempts'      => 0,
            ]);

            if (!$ok) {
                throw new \RuntimeException('Failed to update record.');
            }

            $msg = 'IP ' . $row['ip_address'] . ' unbanned.';
            return $isAjax ? $json(['ok'=>true,'message'=>$msg])
                           : redirect()->to(site_url('administrator/ip_bans'))->with('success', $msg);
        } catch (\Throwable $e) {
            $msg = 'Unable to unban: ' . $e->getMessage();
            return $isAjax ? $json(['ok'=>false,'message'=>$msg],500)
                           : redirect()->back()->with('error', $msg);
        }
    }

    public function banNow()
    {
        $isAjax = $this->request->isAJAX();
        $json = function(array $p, int $code=200){
            $p['csrfTokenName'] = csrf_token();
            $p['csrfHash'] = csrf_hash();
            $p[csrf_token()] = csrf_hash();
            return $this->response->setStatusCode($code)->setJSON($p);
        };

        // Accept both POST and GET params
        $id     = (int) ($this->request->getPost('id') ?? $this->request->getGet('id') ?? 0);
        $ip     = trim((string) ($this->request->getPost('ip') ?? $this->request->getGet('ip') ?? ''));
        $hours  = (int) ($this->request->getPost('hours') ?? $this->request->getGet('hours') ?? 24);
        if ($hours <= 0) $hours = 24;

        try {
            $row = null;
            if ($id > 0) {
                $row = $this->ipAttemptModel->find($id);
            } elseif ($ip !== '') {
                $row = $this->ipAttemptModel->where('ip_address', $ip)->first();
            }

            if (!$row) {
                $msg = 'IP record not found.';
                return $isAjax ? $json(['ok'=>false,'message'=>$msg],404)
                               : redirect()->to(site_url('administrator/ip_bans'))->with('error', $msg);
            }

            $blockedUntil = date('Y-m-d H:i:s', strtotime("+{$hours} hours"));
            $ok = $this->ipAttemptModel->update($row['id'], [
                'blocked_until' => $blockedUntil,
                // Optionally set attempts to threshold for clarity
                'attempts'      => max((int)$row['attempts'], 10),
            ]);

            if (!$ok) {
                throw new \RuntimeException('Failed to update record.');
            }

            $msg = 'IP ' . $row['ip_address'] . ' banned for ' . $hours . 'h.';
            return $isAjax ? $json(['ok'=>true,'message'=>$msg])
                           : redirect()->to(site_url('administrator/ip_bans'))->with('success', $msg);
        } catch (\Throwable $e) {
            $msg = 'Unable to ban: ' . $e->getMessage();
            return $isAjax ? $json(['ok'=>false,'message'=>$msg],500)
                           : redirect()->back()->with('error', $msg);
        }
    }
}
