<?php

namespace Acme\ContactForm;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;

class ContactFormService
{
    public function __construct(
        protected array $config = []
    ) {
        $this->config = array_merge(
            config('contact-form', []),
            $config
        );
    }

    /**
     * Processes a contact form submission.
     */
    public function handle(array $payload, string $subject = '', string $logContext = 'contact-form'): void
    {
        $isSpam = $payload['is_spam'] ?? false;

        if (! $isSpam) {
            $isSpam = $this->performServerSideSpamCheck($payload);
            $payload['is_spam'] = $isSpam;
        }

        if ($isSpam) {
            Log::info("SPAM detected - {$logContext}", $payload);
            Log::info("Email NOT sent (spam detected - {$logContext})", [
                'ip' => $payload['ip'] ?? 'unknown',
                'email' => $payload['email'] ?? 'unknown',
            ]);
        } else {
            Log::info("{$logContext} received", $payload);
            $this->notify($subject ?: __('contact-form::contact-form.default_subject'), $payload);
        }
    }

    protected function notify(string $subject, array $payload): void
    {
        $recipient = $this->config['recipient'] ?? null;

        if (empty($recipient)) {
            return;
        }

        $body = $this->formatMailBody($subject, $payload);

        try {
            Mail::raw($body, function ($message) use ($recipient, $subject): void {
                $message->to($recipient)->subject($subject);
            });
        } catch (\Throwable $e) {
            Log::warning('Contact form email could not be sent', [
                'error' => $e->getMessage(),
            ]);
        }
    }

    protected function formatMailBody(string $subject, array $payload): string
    {
        $lines = [$subject, str_repeat('-', 40)];

        foreach ($payload as $key => $value) {
            if ($key === 'is_spam') {
                continue;
            }

            $value = is_array($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : (string) $value;
            $label = ucfirst(str_replace('_', ' ', $key));
            $lines[] = "{$label}: {$value}";
        }

        return implode(PHP_EOL, $lines);
    }

    protected function performServerSideSpamCheck(array $payload): bool
    {
        $ip = $payload['ip'] ?? 'unknown';
        $config = $this->config;

        $maxAttempts = $config['rate_limit']['max_attempts'] ?? 3;
        $decayMinutes = $config['rate_limit']['decay_minutes'] ?? 15;

        $cacheKey = 'contact_form_'.md5($ip);
        $attempts = cache()->get($cacheKey, 0);

        if ($attempts >= $maxAttempts) {
            Log::warning('Contact form rate limit exceeded', [
                'ip' => $ip,
                'attempts' => $attempts,
                'max_attempts' => $maxAttempts,
            ]);

            return true;
        }

        cache()->put($cacheKey, $attempts + 1, now()->addMinutes($decayMinutes));

        $blacklistedIPs = $config['blacklisted_ips'] ?? [];
        if (in_array($ip, $blacklistedIPs)) {
            Log::warning('Blacklisted IP detected', ['ip' => $ip]);

            return true;
        }

        $userAgent = $payload['user_agent'] ?? '';
        $botPatterns = [
            '/bot/i',
            '/crawler/i',
            '/spider/i',
            '/scraper/i',
            '/curl/i',
            '/wget/i',
            '/python-requests/i',
        ];

        foreach ($botPatterns as $pattern) {
            if (preg_match($pattern, $userAgent)) {
                Log::warning('Bot user-agent detected', [
                    'ip' => $ip,
                    'user_agent' => $userAgent,
                ]);

                return true;
            }
        }

        return false;
    }
}
