<?php

namespace App\Http\Controllers;

use App\Models\EmailBounce;
use App\Models\Mailing;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;

class MailgunWebhookController extends Controller
{
    /**
     * Handle Mailgun webhook events
     */
    public function handle(Request $request)
    {
        // Verify webhook signature (recommended for production)
        if (!$this->verifySignature($request)) {
            Log::warning('Invalid Mailgun webhook signature');
            return response('Unauthorized', 401);
        }

        $eventData = $request->input('event-data', []);
        $event = $eventData['event'] ?? null;

        Log::info('Mailgun webhook received', ['event' => $event, 'data' => $eventData]);

        switch ($event) {
            case 'bounced':
                $this->handleBounce($eventData);
                break;
            case 'complained':
                $this->handleComplaint($eventData);
                break;
            case 'unsubscribed':
                $this->handleUnsubscribe($eventData);
                break;
            default:
                Log::info('Unhandled Mailgun event', ['event' => $event]);
        }

        return response('OK', 200);
    }

    /**
     * Handle bounce events
     */
    protected function handleBounce(array $eventData)
    {
        $email = $eventData['recipient'] ?? null;
        $errorCode = $eventData['delivery-status']['code'] ?? null;
        $errorMessage = $eventData['delivery-status']['description'] ?? 'Unknown bounce';

        if (!$email) {
            Log::warning('Bounce event missing recipient email', $eventData);
            return;
        }

        // Determine bounce type based on error code
        $bounceType = $this->determineBounceTypeFromCode($errorCode);

        // Extract mailing ID from message tags or headers if available
        $mailingId = $this->extractMailingId($eventData);

        EmailBounce::recordBounce($email, $bounceType, $errorMessage, $mailingId);

        Log::info("Recorded {$bounceType} bounce", [
            'email' => $email,
            'code' => $errorCode,
            'message' => $errorMessage,
            'mailing_id' => $mailingId,
        ]);
    }

    /**
     * Handle complaint (spam) events
     */
    protected function handleComplaint(array $eventData)
    {
        $email = $eventData['recipient'] ?? null;

        if (!$email) {
            Log::warning('Complaint event missing recipient email', $eventData);
            return;
        }

        $mailingId = $this->extractMailingId($eventData);

        EmailBounce::recordBounce($email, 'complaint', 'Spam complaint', $mailingId);

        Log::warning("Recorded spam complaint", [
            'email' => $email,
            'mailing_id' => $mailingId,
        ]);
    }

    /**
     * Handle unsubscribe events
     */
    protected function handleUnsubscribe(array $eventData)
    {
        $email = $eventData['recipient'] ?? null;

        if (!$email) {
            Log::warning('Unsubscribe event missing recipient email', $eventData);
            return;
        }

        // You might want to handle unsubscribes differently
        // For now, we'll just log it
        Log::info("Unsubscribe event", ['email' => $email]);

        // Optionally suppress the email
        // EmailBounce::suppressEmail($email, 'Unsubscribed via Mailgun');
    }

    /**
     * Determine bounce type from Mailgun error code
     */
    protected function determineBounceTypeFromCode($code): string
    {
        if (!$code) return 'unknown';

        // Mailgun error codes for hard bounces
        $hardBounceCodes = [550, 551, 553, 554];

        // Mailgun error codes for soft bounces
        $softBounceCodes = [421, 450, 451, 452, 552];

        if (in_array($code, $hardBounceCodes)) {
            return 'hard';
        }

        if (in_array($code, $softBounceCodes)) {
            return 'soft';
        }

        return 'unknown';
    }

    /**
     * Extract mailing ID from event data
     */
    protected function extractMailingId(array $eventData): ?int
    {
        // Check if mailing ID is in message tags
        $tags = $eventData['message']['headers']['message-id'] ?? '';
        if (preg_match('/mailing-(\d+)/', $tags, $matches)) {
            return (int) $matches[1];
        }

        // Check custom headers
        $headers = $eventData['message']['headers'] ?? [];
        if (isset($headers['X-Mailing-ID'])) {
            return (int) $headers['X-Mailing-ID'];
        }

        return null;
    }

    /**
     * Verify Mailgun webhook signature
     */
    protected function verifySignature(Request $request): bool
    {
        $timestamp = $request->input('timestamp');
        $token = $request->input('token');
        $signature = $request->input('signature');

        $signingKey = config('services.mailgun.webhook_key');

        if (!$signingKey) {
            Log::warning('Mailgun webhook signing key not configured');
            return config('app.env') !== 'production'; // Skip verification in non-production
        }

        $expectedSignature = hash_hmac('sha256', $timestamp . $token, $signingKey);

        return hash_equals($expectedSignature, $signature);
    }
}