<?php

namespace App\Services\Security;

use App\Models\IpAttempt;
use Illuminate\Support\Facades\DB;

class IpBanCommandService
{
    public function banNow(?int $id, ?string $ip, int $hours): ?IpAttempt
    {
        $row = $this->findRow($id, $ip);
        if (!$row) {
            return null;
        }

        $blockedUntil = $this->addHours($hours);
        $attempts = max((int) $row->attempts, 10);

        return DB::transaction(function () use ($row, $blockedUntil, $attempts) {
            $row->blocked_until = $blockedUntil;
            $row->attempts = $attempts;
            $row->save();
            return $row->refresh();
        });
    }

    public function unbanOne(?int $id, ?string $ip): ?IpAttempt
    {
        $row = $this->findRow($id, $ip);
        if (!$row) {
            return null;
        }

        return DB::transaction(function () use ($row) {
            $row->blocked_until = null;
            $row->attempts = 0;
            $row->save();
            return $row->refresh();
        });
    }

    public function unbanAll(): int
    {
        return (int) IpAttempt::query()
            ->where('blocked_until', '>', $this->utcNow())
            ->update([
                'blocked_until' => null,
                'attempts' => 0,
            ]);
    }

    private function findRow(?int $id, ?string $ip): ?IpAttempt
    {
        if ($id && $id > 0) {
            return IpAttempt::query()->find($id);
        }
        if ($ip !== null && $ip !== '') {
            return IpAttempt::query()->where('ip_address', $ip)->first();
        }

        return null;
    }

    private function utcNow(): string
    {
        if (function_exists('utc_now')) {
            return (string) utc_now();
        }
        return now('UTC')->toDateTimeString();
    }

    private function addHours(int $hours): string
    {
        $hours = max(1, $hours);
        if (function_exists('utc_now')) {
            return (string) date('Y-m-d H:i:s', strtotime("+{$hours} hours", strtotime((string) utc_now())));
        }
        return now('UTC')->addHours($hours)->toDateTimeString();
    }
}
