<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Jobs\SendEmailBatch;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Schema;

class BulkEmailController extends Controller
{
    public function create(Request $request)
    {
        $oldInput = (array) $request->session()->getOldInput();
        $recipientFilters = $this->resolveRecipientFilters($oldInput);
        $referralCode = trim((string) ($oldInput['referral_code'] ?? ''));

        $recipientCount = 0;
        if ($this->canEstimateRecipientCount($recipientFilters, $referralCode)) {
            $recipientCount = $this->recipientQuery($recipientFilters, $referralCode)->count();
        }

        return view('admin.bulk_email', [
            'initialRecipientCount' => $recipientCount,
        ]);
    }

    public function recipientCount(Request $request): JsonResponse
    {
        $recipientFilters = $this->resolveRecipientFilters($request->query());
        $referralCode = trim((string) $request->query('referral_code', ''));

        $count = 0;
        if ($this->canEstimateRecipientCount($recipientFilters, $referralCode)) {
            $count = $this->recipientQuery($recipientFilters, $referralCode)->count();
        }

        return response()->json([
            'count' => $count,
        ]);
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'subject' => ['required', 'string', 'max:190'],
            'message' => ['required', 'string', 'max:5000'],
            'recipient_filters' => ['nullable', 'array'],
            'recipient_filters.*' => ['string', 'in:verified,unverified'],
            'referral_code' => ['nullable', 'string', 'max:100'],
            'test_mode' => ['nullable', 'boolean'],
        ]);

        $recipientFilters = $this->resolveRecipientFilters($data);
        $referralCode = trim((string) ($data['referral_code'] ?? ''));

        if ($request->boolean('test_mode')) {
            $admin = $request->user();
            if (!$admin || empty($admin->email)) {
                return back()->withErrors('Test mode: admin email পাওয়া যায়নি।')->withInput();
            }

            Bus::dispatch(new SendEmailBatch([$admin->email], $data['subject'], $data['message'], true));

            return back()->with('ok', 'Test email queued (admin only).');
        }

        if (empty($recipientFilters) && $referralCode === '') {
            return back()
                ->withInput()
                ->withErrors('Recipients Filter থেকে কমপক্ষে একটি টিক দিন, অথবা শুধু Referral Code দিয়ে পাঠান।');
        }

        $query = $this->recipientQuery($recipientFilters, $referralCode);
        $total = (clone $query)->count();

        if ($total === 0) {
            return back()->withErrors('এই ফিল্টারে কোনো ইউজারের ইমেইল পাওয়া যায়নি।')->withInput();
        }

        $query->select('email')->orderBy('id')->chunk(500, function ($chunk) use ($data) {
            $emails = $chunk
                ->pluck('email')
                ->map(fn ($email) => trim((string) $email))
                ->filter()
                ->unique()
                ->values()
                ->all();

            if (!empty($emails)) {
                Bus::dispatch(new SendEmailBatch($emails, $data['subject'], $data['message']));
            }
        });

        return back()->with('ok', "Queued emails for {$total} users.");
    }

    private function recipientQuery(array $filters, string $referralCode): Builder
    {
        $query = User::query()
            ->whereNotNull('email')
            ->where('email', '<>', '');

        $this->applyVerificationScope($query, $filters);

        if ($referralCode !== '') {
            $query->whereRaw('LOWER(referral_code) = ?', [strtolower($referralCode)]);
        }

        return $query;
    }

    private function resolveRecipientFilters(array $payload): array
    {
        $raw = $payload['recipient_filters'] ?? [];
        if (!is_array($raw)) {
            $raw = [];
        }

        $allowed = ['verified', 'unverified'];
        $filters = [];

        foreach ($raw as $value) {
            if (!is_string($value)) {
                continue;
            }
            $value = trim($value);
            if ($value === '' || !in_array($value, $allowed, true)) {
                continue;
            }
            if (!in_array($value, $filters, true)) {
                $filters[] = $value;
            }
        }

        return $filters;
    }

    private function canEstimateRecipientCount(array $filters, string $referralCode): bool
    {
        if (!empty($filters)) {
            return true;
        }

        return $referralCode !== '';
    }

    private function applyVerificationScope(Builder $query, array $filters): void
    {
        $hasVerified = in_array('verified', $filters, true);
        $hasUnverified = in_array('unverified', $filters, true);

        // Both selected => all users (no verification condition)
        if ($hasVerified && $hasUnverified) {
            return;
        }

        // None selected => no verification condition (referral-based send case)
        if (!$hasVerified && !$hasUnverified) {
            return;
        }

        $onlyVerified = $hasVerified && !$hasUnverified;
        $onlyUnverified = $hasUnverified && !$hasVerified;

        if (Schema::hasColumn('users', 'is_verifide')) {
            if ($onlyVerified) {
                $query->where('is_verifide', 1);
            } elseif ($onlyUnverified) {
                $query->where('is_verifide', 0);
            }
            return;
        }

        if (Schema::hasColumn('users', 'is_active')) {
            if ($onlyVerified) {
                $query->where('is_active', 1);
            } elseif ($onlyUnverified) {
                $query->where('is_active', 0);
            }
            return;
        }

        if (Schema::hasColumn('users', 'email_verified_at')) {
            if ($onlyVerified) {
                $query->whereNotNull('email_verified_at');
            } elseif ($onlyUnverified) {
                $query->whereNull('email_verified_at');
            }
        }
    }
}
