<?php

namespace App\Services;

use Illuminate\Support\Facades\Session;

class CaptchaService
{
    /**
     * Generate random CAPTCHA text with 5 characters
     * Characters: uppercase, lowercase, numbers
     */
    private static function generateRandomText(int $length = 5): string
    {
        $characters = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789'; // Exclude confusing chars (I, O, i, l, 0, 1)
        $result = '';
        for ($i = 0; $i < $length; $i++) {
            $result .= $characters[random_int(0, strlen($characters) - 1)];
        }
        return $result;
    }

    /**
     * Generate CAPTCHA: create text, render image, save to session
     * Returns checksum for URL cache-busting
     */
    public static function generateCaptcha(): string
    {
        $captchaText = self::generateRandomText(5);
        $checksum = md5($captchaText . time());

        // Store in session with metadata
        Session::put('captcha', [
            'text' => strtolower($captchaText),
            'checksum' => $checksum,
            'created_at' => now(),
            'attempts' => 0,
        ]);

        return $checksum;
    }

    /**
     * Render CAPTCHA image as PNG using PHP GD
     * Returns image resource or false on error
     */
    public static function renderImage(string $captchaText): ?string
    {
        // Ensure GD library is available
        if (!extension_loaded('gd')) {
            return null;
        }

        $width = 400;
        $height = 150;
        $fontSize = 50;

        // Create image
        $image = imagecreatetruecolor($width, $height);

        // Define colors
        $bgColor = imagecolorallocate($image, 255, 255, 255); // White background
        $textColor = imagecolorallocate($image, 0, 0, 0);    // Black text
        $noiseColor1 = imagecolorallocate($image, 220, 220, 220); // Light gray
        $noiseColor2 = imagecolorallocate($image, 100, 100, 100); // Dark gray

        // Fill background
        imagefilledrectangle($image, 0, 0, $width, $height, $bgColor);

        // Add noise (lines and dots)
        for ($i = 0; $i < 10; $i++) {
            $x1 = random_int(0, $width);
            $y1 = random_int(0, $height);
            $x2 = random_int(0, $width);
            $y2 = random_int(0, $height);
            imageline($image, $x1, $y1, $x2, $y2, $noiseColor1);
        }

        for ($i = 0; $i < 30; $i++) {
            $x = random_int(0, $width);
            $y = random_int(0, $height);
            imagefilledarc($image, $x, $y, 2, 2, 0, 360, $noiseColor2, IMG_ARC_PIE);
        }

        // Add border
        imagerectangle($image, 0, 0, $width - 1, $height - 1, $noiseColor2);

        // Try to use TTF font if available, fallback to built-in
        $fontPath = public_path('fonts/DejaVuSans.ttf');
        
        if (file_exists($fontPath)) {
            // Use TTF font for better rendering
            $textBox = imagettfbbox($fontSize, 0, $fontPath, $captchaText);
            $textWidth = $textBox[2] - $textBox[0];
            $textHeight = $textBox[1] - $textBox[7];
            
            $x = ($width - $textWidth) / 2;
            $y = ($height + $textHeight) / 2 - 5;

            imagettftext($image, $fontSize, 0, $x, $y, $textColor, $fontPath, $captchaText);
        } else {
            // Fallback to built-in font
            $textWidth = strlen($captchaText) * 10;
            $x = ($width - $textWidth) / 2;
            $y = ($height - 10) / 2;

            imagestring($image, 5, $x, $y, $captchaText, $textColor);
        }

        // Output as PNG
        ob_start();
        imagepng($image);
        $imageData = ob_get_clean();
        imagedestroy($image);

        return $imageData;
    }

    /**
     * Validate user input against stored CAPTCHA
     * Returns true if valid, false if invalid
     */
    public static function validateCaptcha(string $userInput, string $checksum): bool
    {
        $captcha = Session::get('captcha', null);

        // Check if CAPTCHA exists and hasn't expired (5 minutes)
        if (!$captcha || !isset($captcha['text']) || !isset($captcha['created_at'])) {
            return false;
        }

        $createdAt = $captcha['created_at'];
        if ($createdAt->diffInMinutes(now()) > 5) {
            Session::forget('captcha');
            return false;
        }

        // Verify checksum matches
        if (($captcha['checksum'] ?? null) !== $checksum) {
            return false;
        }

        // Compare user input (case-insensitive) with stored text
        if (strtolower($userInput) === $captcha['text']) {
            Session::forget('captcha');
            return true;
        }

        // Increment failed attempts
        $captcha['attempts'] = ($captcha['attempts'] ?? 0) + 1;
        Session::put('captcha', $captcha);

        // Lock after 5 failed attempts
        if ($captcha['attempts'] >= 5) {
            Session::forget('captcha');
            return false; // Caller should handle lock message
        }

        return false;
    }

    /**
     * Get remaining attempts (utility function)
     */
    public static function getRemainingAttempts(): int
    {
        $captcha = Session::get('captcha', null);
        if (!$captcha) {
            return 5;
        }
        return max(0, 5 - ($captcha['attempts'] ?? 0));
    }

    /**
     * Check if CAPTCHA session is still valid
     */
    public static function isValid(): bool
    {
        $captcha = Session::get('captcha', null);

        if (!$captcha || !isset($captcha['created_at'])) {
            return false;
        }

        $createdAt = $captcha['created_at'];
        return $createdAt->diffInMinutes(now()) <= 5;
    }

    /**
     * Forget CAPTCHA session
     */
    public static function forget(): void
    {
        Session::forget('captcha');
    }
}
