<?php

namespace App\Console\Commands;

use App\Mail\test;
use App\Models\AlertMailRule;
use App\Models\InvoiceValidation;
use App\Models\Plant;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;

class SendInvoiceReport extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    // protected $signature = 'app:send-invoice-report';
    protected $signature = 'send:invoice-report {schedule_type} {plant}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $schedule = $this->argument('schedule_type');
        $plantIdArg = (int) $this->argument('plant');

        $invoiceRules = AlertMailRule::where('module', 'InvoiceValidation')
            ->where('rule_name', 'InvoiceMail')
            ->where('plant', $plantIdArg)
            ->get();

        $serialRules = AlertMailRule::where('module', 'InvoiceValidation')
            ->where('rule_name', 'SerialInvoiceMail')
            ->where('plant', $plantIdArg)
            ->get();

        $materialRules = AlertMailRule::where('module', 'InvoiceValidation')
            ->where('rule_name', 'MaterialInvoiceMail')
            ->where('plant', $plantIdArg)
            ->get();

        // $this->info('Invoice Rules: ' . $invoiceRules->toJson());
        // $this->info('Serial Rules: ' . $serialRules->toJson());
        // $this->info('Material Rules: ' . $materialRules->toJson());

        $serialTableData = [];
        $materialTableData = [];
        $bundleTableData = [];

        $plantIds = $plantIdArg == 0
            ? InvoiceValidation::select('plant_id')->distinct()->pluck('plant_id')->toArray()
            : [$plantIdArg];

        $isPlantRun = $plantIdArg != 0;

        $no = 1;
        if (strtolower($schedule) == 'daily') {
            $startDate = now()->subDay()->setTime(8, 0, 0);
            $endDate = now()->setTime(8, 0, 0);
        } else {
            $startDate = now()->setTime(8, 0, 0);
            $endDate = now()->copy()->addDay()->setTime(8, 0, 0);
        }
        foreach ($plantIds as $plantId) {
            $plant = Plant::find($plantId);
            $plantName = $plant ? $plant->name : $plantId;

            // Serial Invoice
            $totalSerialCount = InvoiceValidation::where('plant_id', $plantId)
                ->whereNull('quantity')
                ->whereBetween('created_at', [$startDate, $endDate])
                ->distinct('invoice_number')
                ->count('invoice_number');

            $scannedSerialCount = InvoiceValidation::select('invoice_number')
                ->where('plant_id', $plantId)
                ->whereNull('quantity')
                ->whereBetween('created_at', [$startDate, $endDate])
                ->groupBy('invoice_number')
                ->havingRaw("COUNT(*) = SUM(CASE WHEN scanned_status = 'Scanned' THEN 1 ELSE 0 END)")
                ->count();

            $serialInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
                ->where('quantity', null)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->count();

            $scannedInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
                ->where('scanned_status', 'Scanned')
                ->where(function ($query) {
                    $query->whereNull('quantity')
                        ->orWhere('quantity', 0);
                })
                ->whereBetween('created_at', [$startDate, $endDate])
                ->count();

            $serialTableData[] = [
                'no' => $no,
                'plant_id' => $plantId,
                'plant' => $plantName,
                'totalInvoice' => $totalSerialCount,
                'scannedInvoice' => $scannedSerialCount,
                'totalInvoiceQuan' => $serialInvoiceQuan,
                'scannedInvoiceQuan' => $scannedInvoiceQuan,
            ];

            // Material Invoice
            $totalMatCount = InvoiceValidation::where('plant_id', $plantId)
                ->where('quantity', 1)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->distinct('invoice_number')
                ->count('invoice_number');

            $scannedMatCount = InvoiceValidation::select('invoice_number')
                ->where('plant_id', $plantId)
                ->where('quantity', 1)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->groupBy('invoice_number')
                ->havingRaw("COUNT(*) = SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END)")
                ->count();

            $totalMatInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
                ->where('quantity', 1)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->count();

            $scannedMatInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
                ->where('quantity', 1)
                ->whereNotNull('serial_number')
                ->where('serial_number', '!=', '')
                ->whereBetween('created_at', [$startDate, $endDate])
                ->count();

            $materialTableData[] = [
                'no' => $no,
                'plant_id' => $plantId,
                'plant' => $plantName,
                'totalInvoice' => $totalMatCount,
                'scannedInvoice' => $scannedMatCount,
                'totalInvoiceQuan' => $totalMatInvoiceQuan,
                'scannedInvoiceQuan' => $scannedMatInvoiceQuan,
            ];

            // Bundle Invoice
            $totalBundleCount = InvoiceValidation::where('plant_id', $plantId)
                ->where('quantity', '>', 1)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->distinct('invoice_number')
                ->count('invoice_number');

            $scannedBundleCount = InvoiceValidation::select('invoice_number')
                ->where('plant_id', $plantId)
                ->where('quantity', '>', 1)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->groupBy('invoice_number')
                ->havingRaw("COUNT(*) = SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END)")
                ->count();

            $totalBundleInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
                ->where('quantity', '>', 1)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->count();

            $scannedBundleInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
                ->where('quantity', '>', 1)
                ->whereNotNull('serial_number')
                ->where('serial_number', '!=', '')
                ->whereBetween('created_at', [$startDate, $endDate])
                ->count();

            $bundleTableData[] = [
                'no' => $no,
                'plant_id' => $plantId,
                'plant' => $plantName,
                'totalInvoice' => $totalBundleCount,
                'scannedInvoice' => $scannedBundleCount,
                'totalInvoiceQuan' => $totalBundleInvoiceQuan,
                'scannedInvoiceQuan' => $scannedBundleInvoiceQuan,
            ];

            $no++;
        }

        // $mail = new test($serialTableData, $materialTableData, $bundleTableData, $schedule);
        // $contentVars = $mail->content()->with;

        $this->info($contentVars['greeting'] ?? 'Invoice Report');

        // Send to SerialInvoiceMail recipients
        // if ($mailRules->has('SerialInvoiceMail')) {

        //     foreach ($mailRules->get('SerialInvoiceMail') as $rule) {

        //         $filteredSerialData = [];

        //         $toEmails = collect(explode(',', $rule->email))
        //             ->map(fn ($e) => trim($e))
        //             ->filter()
        //             ->unique()
        //             ->values()
        //             ->toArray();

        //         $ccEmails = collect(explode(',', $rule->cc_emails ?? ''))
        //             ->map(fn ($e) => trim($e))
        //             ->filter()
        //             ->unique()
        //             ->values()
        //             ->toArray();

        //         if (empty($toEmails)) {
        //             $this->warn("Skipping rule ID {$rule->id} — no valid To emails found.");

        //             continue;
        //         }

        //         if ($rule->plant == 0) {
        //             $filteredSerialData = $serialTableData;

        //         } else {
        //             $filteredSerialData = collect($serialTableData)
        //                 ->where('plant_id', $rule->plant)
        //                 ->values()
        //                 ->toArray();
        //         }

        //         if (empty($filteredSerialData)) {
        //             $this->warn("Skipping empty mail for rule {$rule->id}");
        //             continue;
        //         }

        //         // \Mail::to($toEmails)
        //         //     ->cc($ccEmails)
        //         //     ->send(new test(
        //         //         $filteredSerialData,
        //         //         [],
        //         //         [],
        //         //         $schedule
        //         //     ));

        //         $mail = new test(
        //             $filteredSerialData,
        //             [],
        //             [],
        //             $schedule
        //         );

        //         \Mail::to($toEmails)
        //             ->cc($ccEmails)
        //             ->send($mail);

        //         // \Mail::to($toEmails)->cc($ccEmails)->send(new test($serialTableData, [], [], $schedule));

        //         $this->info("Mail sent for rule ID {$rule->id} → To: ".implode(', ', $toEmails).($ccEmails ? ' | CC: '.implode(', ', $ccEmails) : ''));
        //     }
        // }

        if ($serialRules->isNotEmpty()) {

            foreach ($serialRules as $rule) {

                if (
                    $isPlantRun &&
                    $plantIdArg != 0 &&
                    $rule->plant != 0 &&
                    $rule->plant != $plantIdArg
                ) {
                    continue;
                }

                if (
                    $plantIdArg == 0 &&
                    $rule->plant != 0
                ) {
                    continue;
                }

                $data = collect($serialTableData)
                    ->when($rule->plant != 0, fn ($q) => $q->where('plant_id', $rule->plant))
                    ->values()
                    ->toArray();

                if (empty($data)) continue;

                \Mail::to($rule->email)
                    ->cc($rule->cc_emails ?? [])
                    ->send(new test($data, [], [], $schedule));
            }
        }

        // Send to MaterialInvoiceMail recipients (material + bundle table)
        if ($materialRules->isNotEmpty()) {
            // $emails = $mailRules['MaterialInvoiceMail']->pluck('email')->unique()->toArray();
            // foreach ($emails as $email) {
            //     Mail::to($email)->send(new test([], $materialTableData, $bundleTableData, $schedule));
            // }
            foreach ($materialRules as $rule) {

                $toEmails = collect(explode(',', $rule->email))
                    ->map(fn ($e) => trim($e))
                    ->filter()
                    ->unique()
                    ->values()
                    ->toArray();

                $ccEmails = collect(explode(',', $rule->cc_emails ?? ''))
                    ->map(fn ($e) => trim($e))
                    ->filter()
                    ->unique()
                    ->values()
                    ->toArray();

                if (empty($toEmails)) {
                    $this->warn("Skipping rule ID {$rule->id} — no valid To emails found.");

                    continue;
                }

                 // FILTER DATA
                if ($rule->plant == 0) {

                    $filteredMaterialData = $materialTableData;
                    $filteredBundleData = $bundleTableData;

                } else {

                    $filteredMaterialData = collect($materialTableData)
                        ->where('plant_id', $rule->plant)
                        ->values()
                        ->toArray();

                    $filteredBundleData = collect($bundleTableData)
                        ->where('plant_id', $rule->plant)
                        ->values()
                        ->toArray();
                }

                \Mail::to($toEmails)
                    ->cc($ccEmails)
                    ->send(new test(
                        [],
                        $filteredMaterialData,
                        $filteredBundleData,
                        $schedule
                    ));

                // \Mail::to($toEmails)->cc($ccEmails)->send(new test([], $materialTableData, $bundleTableData, $schedule));

                $this->info("Mail sent for rule ID {$rule->id} → To: ".implode(', ', $toEmails).($ccEmails ? ' | CC: '.implode(', ', $ccEmails) : ''));
            }
        }

        if ($invoiceRules->isNotEmpty()) {

            foreach ($invoiceRules as $rule) {

                // During global run, only execute plant=0 rule
                if ($plantIdArg == 0 && $rule->plant != 0) {
                    continue;
                }

                // During plant run, only execute matching rule
                if (
                    $plantIdArg != 0 &&
                    $rule->plant != 0 &&
                    $rule->plant != $plantIdArg
                ) {
                    continue;
                }

                $filteredSerialData = [];
                $filteredMaterialData = [];
                $filteredBundleData = [];

                $toEmails = collect(explode(',', $rule->email))
                    ->map(fn ($e) => trim($e))
                    ->filter()
                    ->unique()
                    ->values()
                    ->toArray();

                $ccEmails = collect(explode(',', $rule->cc_emails ?? ''))
                    ->map(fn ($e) => trim($e))
                    ->filter()
                    ->unique()
                    ->values()
                    ->toArray();

                if (empty($toEmails)) {
                    $this->warn("Skipping rule ID {$rule->id} — no valid To emails found.");

                    continue;
                }

                if ($rule->plant == 0) {

                    $filteredSerialData = $serialTableData;
                    $filteredMaterialData = $materialTableData;
                    $filteredBundleData = $bundleTableData;

                } else {

                    $filteredSerialData = collect($serialTableData)
                        ->where('plant_id', $rule->plant)
                        ->values()
                        ->toArray();

                    $filteredMaterialData = collect($materialTableData)
                        ->where('plant_id', $rule->plant)
                        ->values()
                        ->toArray();

                    $filteredBundleData = collect($bundleTableData)
                        ->where('plant_id', $rule->plant)
                        ->values()
                        ->toArray();
                }

                // Prevent empty mails
                if (
                    empty($filteredSerialData) &&
                    empty($filteredMaterialData) &&
                    empty($filteredBundleData)
                ) {
                    $this->warn("Skipping empty mail for rule {$rule->id}");
                    continue;
                }

                // \Mail::to($toEmails)
                //     ->cc($ccEmails)
                //     ->send(new test(
                //         $filteredSerialData,
                //         $filteredMaterialData,
                //         $filteredBundleData,
                //         $schedule
                //     ));

                $mail = new test(
                    $filteredSerialData,
                    $filteredMaterialData,
                    $filteredBundleData,
                    $schedule
                );

                \Mail::to($toEmails)
                    ->cc($ccEmails)
                    ->send($mail);

                // \Mail::raw('Test mail', function ($message) use ($toEmails, $ccEmails) {
                //     $message->to($toEmails)
                //             ->cc($ccEmails)
                //             ->subject('Test');
                // });

                // \Mail::to($toEmails)->cc($ccEmails)->send(new test($serialTableData, $materialTableData, $bundleTableData, $schedule));

                // $this->info("Mail sent for rule ID {$rule->id} → To: ".implode(', ', $toEmails).($ccEmails ? ' | CC: '.implode(', ', $ccEmails) : ''));
            }
        }

        // Show preview in console
        $this->info('--- Serial Invoice Table ---');
        $this->table(['#', 'Plant', 'Total Invoice', 'Scanned Invoice', 'TotalInvoice Quantity', 'ScannedInvoice Quantity'], $serialTableData);

        $this->info('--- Material Invoice Table ---');
        $this->table(['#', 'Plant', 'Total Invoice', 'Scanned Invoice', 'TotalInvoice Quantity', 'ScannedInvoice Quantity'], $materialTableData);

        $this->info('--- Bundle Invoice Table ---');
        $this->table(['#', 'Plant', 'Total Invoice', 'Scanned Invoice', 'TotalInvoice Quantity', 'ScannedInvoice Quantity'], $bundleTableData);

        $this->info($contentVars['wishes'] ?? '');

    }
}
