<?php

namespace App\Console\Commands;

use App\Models\MailingBounce;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class ManageBouncedMailings extends Command
{
    /**
     * The name and signature of the console command.
     */
    protected $signature = 'mailings:manage-bounces
                            {action : Action to perform: list, stats, suppress, unsuppress, cleanup, check-thresholds}
                            {--email= : Specific email address for suppress/unsuppress/check actions}
                            {--days= : Number of days for cleanup (default: 90)}
                            {--type= : Bounce type filter: hard, soft, complaint}';

    /**
     * The console command description.
     */
    protected $description = 'Manage bounced email addresses from mailings with threshold-based actions';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $action = $this->argument('action');

        switch ($action) {
            case 'list':
                $this->listBounces();
                break;
            case 'stats':
                $this->showStats();
                break;
            case 'suppress':
                $this->suppressEmail();
                break;
            case 'unsuppress':
                $this->unsuppressEmail();
                break;
            case 'cleanup':
                $this->cleanupOldBounces();
                break;
            case 'check-thresholds':
                $this->checkThresholds();
                break;
            default:
                $this->error("Invalid action. Use: list, stats, suppress, unsuppress, cleanup, check-thresholds");
                return 1;
        }

        return 0;
    }

    /**
     * List bounced emails
     */
    protected function listBounces()
    {
        $query = MailingBounce::query();

        if ($type = $this->option('type')) {
            $query->where('bounce_type', $type);
        }

        $bounces = $query->orderBy('bounced_at', 'desc')->get();

        if ($bounces->isEmpty()) {
            $this->info('No bounced emails found.');
            return;
        }

        $headers = ['Email', 'Type', 'Reason', 'Bounced At', 'Suppressed'];
        $rows = $bounces->map(function ($bounce) {
            return [
                $bounce->email,
                $bounce->bounce_type,
                Str::limit($bounce->bounce_reason, 50),
                $bounce->bounced_at->format('Y-m-d H:i'),
                $bounce->is_suppressed ? 'Yes' : 'No',
            ];
        });

        $this->table($headers, $rows);
    }

    /**
     * Show bounce statistics
     */
    protected function showStats()
    {
        $config = timebank_config('mailing.bounce_thresholds', []);
        $windowDays = $config['counting_window_days'] ?? 30;

        $totalBounces = MailingBounce::count();
        $suppressedEmails = MailingBounce::where('is_suppressed', true)->count();
        $hardBounces = MailingBounce::where('bounce_type', 'hard')->count();
        $softBounces = MailingBounce::where('bounce_type', 'soft')->count();
        $recentBounces = MailingBounce::where('bounced_at', '>=', now()->subDays(7))->count();
        $windowBounces = MailingBounce::where('bounced_at', '>=', now()->subDays($windowDays))->count();

        $this->info("Mailing Bounce Statistics:");
        $this->line("Total bounces: {$totalBounces}");
        $this->line("Suppressed emails: {$suppressedEmails}");
        $this->line("Hard bounces: {$hardBounces}");
        $this->line("Soft bounces: {$softBounces}");
        $this->line("Recent bounces (7 days): {$recentBounces}");
        $this->line("Bounces in threshold window ({$windowDays} days): {$windowBounces}");

        // Threshold configuration
        $this->line("\nThreshold Configuration:");
        $this->line("  Suppression threshold: " . ($config['suppression_threshold'] ?? 3));
        $this->line("  Verification reset threshold: " . ($config['verification_reset_threshold'] ?? 2));
        $this->line("  Counting window: {$windowDays} days");

        // Top bouncing domains
        $topDomains = MailingBounce::select(DB::raw('SUBSTRING_INDEX(email, "@", -1) as domain, COUNT(*) as count'))
            ->groupBy('domain')
            ->orderBy('count', 'desc')
            ->limit(5)
            ->get();

        if ($topDomains->isNotEmpty()) {
            $this->line("\nTop bouncing domains:");
            foreach ($topDomains as $domain) {
                $this->line("  {$domain->domain}: {$domain->count} bounces");
            }
        }

        // Emails approaching thresholds
        $this->showEmailsApproachingThresholds($config);
    }

    /**
     * Show emails that are approaching bounce thresholds
     */
    protected function showEmailsApproachingThresholds(array $config): void
    {
        $suppressionThreshold = $config['suppression_threshold'] ?? 3;
        $verificationResetThreshold = $config['verification_reset_threshold'] ?? 2;
        $windowDays = $config['counting_window_days'] ?? 30;

        // Find emails with high bounce counts but not yet suppressed
        $emailsNearThreshold = MailingBounce::select('email', DB::raw('COUNT(*) as bounce_count'))
            ->where('bounce_type', 'hard')
            ->where('bounced_at', '>=', now()->subDays($windowDays))
            ->where('is_suppressed', false)
            ->groupBy('email')
            ->having('bounce_count', '>=', max(1, $verificationResetThreshold - 1))
            ->orderBy('bounce_count', 'desc')
            ->limit(10)
            ->get();

        if ($emailsNearThreshold->isNotEmpty()) {
            $this->line("\nEmails Approaching Thresholds:");
            $headers = ['Email', 'Hard Bounces', 'Status'];
            $rows = $emailsNearThreshold->map(function ($item) use ($suppressionThreshold, $verificationResetThreshold) {
                $status = [];
                if ($item->bounce_count >= $suppressionThreshold) {
                    $status[] = 'Will suppress';
                } elseif ($item->bounce_count >= $verificationResetThreshold) {
                    $status[] = 'Will reset verification';
                }
                if (empty($status)) {
                    $status[] = 'Approaching threshold';
                }

                return [
                    $item->email,
                    $item->bounce_count,
                    implode(', ', $status)
                ];
            });

            $this->table($headers, $rows);
        }
    }

    /**
     * Check thresholds for a specific email or all emails
     */
    protected function checkThresholds(): void
    {
        $email = $this->option('email');

        if ($email) {
            $stats = MailingBounce::getBounceStats($email);
            $this->displayEmailStats($stats);
        } else {
            $this->info("Checking all emails against current thresholds...");

            // Get all emails with bounces
            $emails = MailingBounce::distinct('email')->pluck('email');

            $problematicEmails = [];
            foreach ($emails as $emailAddress) {
                $stats = MailingBounce::getBounceStats($emailAddress);

                $config = timebank_config('mailing.bounce_thresholds', []);
                $suppressionThreshold = $config['suppression_threshold'] ?? 3;
                $verificationResetThreshold = $config['verification_reset_threshold'] ?? 2;

                if ($stats['recent_hard_bounces'] >= $verificationResetThreshold) {
                    $problematicEmails[] = $stats;
                }
            }

            if (empty($problematicEmails)) {
                $this->info("No emails exceed the current thresholds.");
                return;
            }

            $this->info("Found " . count($problematicEmails) . " emails exceeding thresholds:");

            foreach ($problematicEmails as $stats) {
                $this->displayEmailStats($stats);
                $this->line('---');
            }
        }
    }

    /**
     * Display bounce statistics for a specific email
     */
    protected function displayEmailStats(array $stats): void
    {
        $config = timebank_config('mailing.bounce_thresholds', []);
        $suppressionThreshold = $config['suppression_threshold'] ?? 3;
        $verificationResetThreshold = $config['verification_reset_threshold'] ?? 2;

        $this->line("Email: {$stats['email']}");
        $this->line("  Total bounces: {$stats['total_bounces']}");
        $this->line("  Recent bounces ({$stats['window_days']} days): {$stats['recent_bounces']}");
        $this->line("  Recent hard bounces: {$stats['recent_hard_bounces']}");
        $this->line("  Currently suppressed: " . ($stats['is_suppressed'] ? 'Yes' : 'No'));

        // Status assessment
        if ($stats['recent_hard_bounces'] >= $suppressionThreshold) {
            $this->line("  🔴 Status: Should be suppressed ({$stats['recent_hard_bounces']} >= {$suppressionThreshold})");
        } elseif ($stats['recent_hard_bounces'] >= $verificationResetThreshold) {
            $this->line("  🟡 Status: Should reset verification ({$stats['recent_hard_bounces']} >= {$verificationResetThreshold})");
        } else {
            $this->line("  🟢 Status: Below thresholds");
        }
    }

    /**
     * Suppress a specific email
     */
    protected function suppressEmail()
    {
        $email = $this->option('email');

        if (!$email) {
            $email = $this->ask('Enter email address to suppress');
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $this->error('Invalid email address.');
            return;
        }

        MailingBounce::suppressEmail($email, 'Manually suppressed via command');
        $this->info("Email {$email} has been suppressed.");
    }

    /**
     * Unsuppress a specific email
     */
    protected function unsuppressEmail()
    {
        $email = $this->option('email');

        if (!$email) {
            $email = $this->ask('Enter email address to unsuppress');
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $this->error('Invalid email address.');
            return;
        }

        $updated = MailingBounce::where('email', $email)
            ->update(['is_suppressed' => false]);

        if ($updated > 0) {
            $this->info("Email {$email} has been unsuppressed.");
        } else {
            $this->warn("Email {$email} was not found in bounce list.");
        }
    }

    /**
     * Clean up old bounces
     */
    protected function cleanupOldBounces()
    {
        $days = $this->option('days') ?: 90;

        if (!$this->confirm("Delete bounces older than {$days} days? This will only remove old soft bounces, keeping hard bounces and suppressions.")) {
            return;
        }

        $deleted = MailingBounce::where('bounce_type', 'soft')
            ->where('is_suppressed', false)
            ->where('bounced_at', '<', now()->subDays($days))
            ->delete();

        $this->info("Deleted {$deleted} old soft bounce records.");
    }
}