<?php

declare(strict_types=1);

namespace ServerManager\Core;

use ServerManager\Services\AuditService;

class Security
{
    private Logger $logger;
    private AuditService $auditService;

    public function __construct()
    {
        $this->logger = Logger::getInstance();
    }

    public function setAuditService(AuditService $auditService): void
    {
        $this->auditService = $auditService;
    }

    public function hashPassword(string $password): string
    {
        return password_hash($password, PASSWORD_ARGON2ID, [
            'memory_cost' => 65536,
            'time_cost' => 4,
            'threads' => 3,
        ]);
    }

    public function verifyPassword(string $password, string $hash): bool
    {
        return password_verify($password, $hash);
    }

    public function generateCSRFToken(): string
    {
        $token = bin2hex(random_bytes(32));
        Session::set('csrf_token', $token);
        Session::set('csrf_token_time', time());
        return $token;
    }

    public function validateCSRFToken(string $token): bool
    {
        $storedToken = Session::get('csrf_token');
        $tokenTime = Session::get('csrf_token_time');

        if (!$storedToken || !$tokenTime) {
            return false;
        }

        $expiry = App::getConfig()['csrf']['token_expiry'] ?? 7200;
        if (time() - $tokenTime > $expiry) {
            return false;
        }

        return hash_equals($storedToken, $token);
    }

    public function purify(string $input): string
    {
        return htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8');
    }

    public function purifyArray(array $input): array
    {
        return array_map(function ($value) {
            if (is_string($value)) {
                return $this->purify($value);
            }
            if (is_array($value)) {
                return $this->purifyArray($value);
            }
            return $value;
        }, $input);
    }

    public function generateApiToken(): string
    {
        return bin2hex(random_bytes(32));
    }

    public function generateMasterKey(): string
    {
        return bin2hex(random_bytes(32));
    }

    public function sanitizeFilename(string $filename): string
    {
        $filename = preg_replace('/[^a-zA-Z0-9._-]/', '_', $filename);
        return preg_replace('/_+/', '_', $filename);
    }

    public function isValidIP(string $ip): bool
    {
        return filter_var($ip, FILTER_VALIDATE_IP) !== false;
    }

    public function isValidHostname(string $hostname): bool
    {
        return (bool) preg_match('/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/', $hostname);
    }

    public function isValidPort(int $port): bool
    {
        return $port > 0 && $port <= 65535;
    }

    public function isValidEmail(string $email): bool
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }

    public function generateUUID(): string
    {
        $data = random_bytes(16);
        $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
        $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
        return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
    }
}
