<?php

namespace App\Console\Commands;

use App\Classes\SMS\ExpireCustomerNotifySms;
use App\Http\Controllers\CompanyInfoController;
use Carbon\Carbon;
use App\Models\Pop;
use App\Models\Client;
use Illuminate\Console\Command;
use App\Jobs\ExpireCustomerNotification;
use App\Jobs\ResellerSendSms;
use App\Models\Reseller;
use App\Models\ResellerSmsGetway;
use App\Models\ResellerSmsLog;
use App\Models\SmsLog;
use App\Models\SmsPaymentReminder;
use Illuminate\Support\Facades\Log;

class ExpireSmsSendCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'expire:notification';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'This Will send sms to expire customer';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */

    public function getMessage($client, $sms)
    {
        $l = new CompanyInfoController();
        $link = $l->baseUrl();
        if ($client->customerAccount && $client->customerAccount->dueAmount > 0) {
            $dueAmount = $client->customerAccount->dueAmount;
        } else {
            $dueAmount = 0;
        }


        if (getBillingType() == 'day_to_day' || siteinfo()->day_to_day_after_10_days == 'Yes') {
            $check_due = isset($client->customerAccount) ? $client->customerAccount->dueAmount : 0;
            $dueAmount = ($client->packages->package_rate ?? 0)  + $check_due - ($client->parmanent_discount ?? 0);

        }
        Log::error($client->id);

            $message = $sms;

            $message = str_replace(
                [
                    '{c_id}',
                    '{c_code}',
                    '{c_username}',
                    '{c_name}',
                    '{c_password}',
                    '{c_deadline}',
                    '{MonthlyBill}',
                    '{TotalDue}',
                    '{company_name}',
                    '{company_cell}',
                    '{payment_url}',
                    '{BTRC_speed}',
                    '{BTRC_rate}'
                ],
                [
                    $client->id,
                    $client->customer_code ?? '',
                    $client->userid,
                    $client->clientsinfo->clients_name,
                    $client->password,
                    Carbon::parse($client->expire_date)->format('d-M-Y'),
                    $client->packages->package_rate ?? 0,
                    $dueAmount,
                    siteinfo()->name,
                    siteinfo()->mobile,
                    $link.$client->slug,
                    $client->packages->package_bandwidth ?? 0,
                    $client->packages->btrc_package_price ?? 0
                ],
                $message
            );


            Log::error("Final Message for Client ID: " . $client->id . " is: " . $message);
        return $message;
    }




    public function handle()
    {
        // Log::info("log -expire:notification");

        if(globalPermission('customResellerSmsGatewaySetup')){
            $this->processWithSeparateGatewayOwnResellers();
        } else {
            if (checkSettings('main_sms_gateway_for_own_other') == 'enable') {
                $this->processWithSeparateGatewayOwnResellersForOwnGatewayType();
                $this->processWithDefaultGatewayOwnResellers();
            } else {
                $this->processWithDefaultGatewayOwnResellers();
            }
        }

        if (checkSettings('main_sms_gateway_for_own_other') == 'disable') {
            $this->processWithSeparateGatewayOtherResellers();
        }
    }

    /**
     * When main_sms_gateway_for_own_other is enable and customResellerSmsGatewaySetup is disable,
     * send reminder from reseller_sms_getways for resellers with sms_gateway_type=own and pop sms_send=yes.
     */
    protected function processWithSeparateGatewayOwnResellersForOwnGatewayType()
    {
        $ownResellers = Reseller::with('resellerSmsGateway')
                // ->where('reseller_type', 'own')
                ->where('sms_gateway_type', 'own')
                ->whereHas('resellerSmsGateway', function($query) {
                    $query->whereNotNull('sms_gateway');
                })->get();

            foreach ($ownResellers as $reseller) {
                $smsGateway = $reseller->resellerSmsGateway;
                if ($smsGateway->sms_gateway) {
                    if($reseller->reseller_type == 'own'){
                        $reminderCustomerSms = collect(json_decode($smsGateway->sms_formate))
                            ->where('sms_type', 'own_reseller_customer_reminder')
                            ->first();
                    } else {
                        $reminderCustomerSms = collect(json_decode($smsGateway->sms_formate))
                            ->where('sms_type', 'other_reseller_customer_reminder')
                            ->first();
                    }

                    if ($reminderCustomerSms && $reminderCustomerSms->send_sms === "Yes") {
                        $pop_ids = Pop::where('reseller_id', $reseller->id)->where('sms_send', 'yes')->pluck('id');
                        $clients = $this->getAllEligibleClientsToNotifyWithSms($pop_ids, $reminderCustomerSms->days_before);
                        $this->sendSmsClients($clients, $reminderCustomerSms->sms_body, $smsGateway->sms_gateway, $reseller->id);
                    }
                    if ($reminderCustomerSms && isset($reminderCustomerSms->second_send_sms) && $reminderCustomerSms->second_send_sms === "Yes") {
                        $pop_ids = Pop::where('reseller_id', $reseller->id)->where('sms_send', 'yes')->pluck('id');
                        $secondDays = $reminderCustomerSms->second_days_before ?? 1;
                        $clientsSecond = $this->getAllEligibleClientsToNotifyWithSms($pop_ids, $secondDays);
                        $secondBody = $reminderCustomerSms->second_sms_body ?? $reminderCustomerSms->sms_body;
                        $this->sendSmsClients($clientsSecond, $secondBody, $smsGateway->sms_gateway, $reseller->id);
                    }
                }
            }
    }

    protected function processWithSeparateGatewayOwnResellers()
    {
        $ownResellers = Reseller::with('resellerSmsGateway')
                ->where('reseller_type', 'own')
                ->whereHas('resellerSmsGateway', function($query) {
                    $query->whereNotNull('sms_gateway'); // Ensure that sms_gateway is present
                })->get();

            foreach ($ownResellers as $reseller) {
                $smsGateway = $reseller->resellerSmsGateway;

                if ($smsGateway->sms_gateway) {
                    // Decode and collect SMS format just once
                    $reminderCustomerSms = collect(json_decode($smsGateway->sms_formate))
                        ->where('sms_type', 'own_reseller_customer_reminder')
                        ->first();

                    // 1st reminder
                    if ($reminderCustomerSms && $reminderCustomerSms->send_sms === "Yes") {
                        $pop_ids = Pop::where('reseller_id',$reseller->id)
                                                         ->where('sms_send', 'yes')->pluck('id');

                        $clients = $this->getAllEligibleClientsToNotifyWithSms($pop_ids,$reminderCustomerSms->days_before);

                        $this->sendSmsClients($clients,$reminderCustomerSms->sms_body,$smsGateway->sms_gateway,$reseller->id);
                    }

                    // 2nd reminder for own reseller customers
                    if ($reminderCustomerSms && isset($reminderCustomerSms->second_send_sms) && $reminderCustomerSms->second_send_sms === "Yes") {
                        $pop_ids = Pop::where('reseller_id',$reseller->id)
                                                         ->where('sms_send', 'yes')->pluck('id');

                        $secondDays = $reminderCustomerSms->second_days_before ?? 1;
                        $clientsSecond = $this->getAllEligibleClientsToNotifyWithSms($pop_ids, $secondDays);

                        $secondBody = $reminderCustomerSms->second_sms_body ?? $reminderCustomerSms->sms_body;
                        $this->sendSmsClients($clientsSecond, $secondBody, $smsGateway->sms_gateway, $reseller->id);
                    }
                }
            }

    }

    protected function processWithDefaultGatewayOwnResellers()
    {
        if (checkSettings('main_sms_gateway_for_own_other') == 'enable') {
            $pops = Pop::where('sms_send', 'yes')
                ->whereHas('reseller', function ($q) {
                    $q->where(function ($q2) {
                        $q2->whereNull('sms_gateway_type')->orWhere('sms_gateway_type', '!=', 'own');
                    });
                })
                ->pluck('id');
        } else {
            $pops = Pop::where('bill_generate', 'yes')->where('sms_send', 'yes')->pluck('id');
        }
            $sms = json_decode(getSmsMessage()->where('tamplate_name', 'bill_reminder')->first()->tamplate_body);

            if ($sms->frist_sendsms == 'Yes') {

                $clients = $this->getAllEligibleClientsToNotifyWithSms($pops,$sms->first_reminder_day);

                if ($clients->count() > 0) {

                    if (SmsPaymentReminder::where('expire_date', $clients->first()->expire_date)->where('step', 'first')->count() < 1) {

                        $client_ids = $clients->pluck('userid')->toJson();

                        SmsPaymentReminder::create([
                            'step' => 'first',
                            'expire_date' => $clients->first()->expire_date,
                            'user_list' => $client_ids
                        ]);


                        $this->sendSmsClients($clients,$sms->frist_sms_body);

                    }
                }
            }

            // 2nd reminder: same process as 1st, using second_reminder_day and second_sms_body
            if (isset($sms->second_sendsms) && $sms->second_sendsms == 'Yes') {

                $clientsSecond = $this->getAllEligibleClientsToNotifyWithSms($pops, $sms->second_reminder_day ?? 1);

                if ($clientsSecond->count() > 0) {

                    if (SmsPaymentReminder::where('expire_date', $clientsSecond->first()->expire_date)->where('step', 'second')->count() < 1) {

                        $client_ids = $clientsSecond->pluck('userid')->toJson();

                        SmsPaymentReminder::create([
                            'step' => 'second',
                            'expire_date' => $clientsSecond->first()->expire_date,
                            'user_list' => $client_ids
                        ]);

                        $this->sendSmsClients($clientsSecond, $sms->second_sms_body ?? $sms->frist_sms_body);
                    }
                }
            }
    }

    protected function processWithSeparateGatewayOtherResellers()
    {
        $other_resellers_pops = Pop::where('bill_generate', 'no')->get();

        foreach ($other_resellers_pops as $pop) {
            $reseller_sms_getway = ResellerSmsGetway::with('reseller')->where('reseller_id', $pop->reseller_id)->first();
            if($reseller_sms_getway){
                $reminder_customer_sms = collect(json_decode($reseller_sms_getway->sms_formate))->where('sms_type','other_reseller_customer_reminder')->first();

                // 1st reminder
                if($reminder_customer_sms && $reminder_customer_sms->send_sms == "Yes"){
                    $notify_clients = Client::with('clientsinfo')->where('expire_date', today()->addDay($reminder_customer_sms->days_before))->where('pop_id', $pop->id)->get();
                    foreach($notify_clients as $item){
                        (new ExpireCustomerNotifySms)->otherResellerCustomerSendSmsBeforeExpire($item,$reseller_sms_getway->sms_gateway,$reseller_sms_getway->reseller->name,
                                                            $reseller_sms_getway->reseller->contact,$reminder_customer_sms->sms_body,$reseller_sms_getway->reseller->id);
                    }
                }

                // 2nd reminder for other resellers
                if ($reminder_customer_sms && isset($reminder_customer_sms->second_send_sms) && $reminder_customer_sms->second_send_sms == "Yes") {
                    $secondDays = $reminder_customer_sms->second_days_before ?? 1;
                    $notify_clients_second = Client::with('clientsinfo')->where('expire_date', today()->addDay($secondDays))->where('pop_id', $pop->id)->get();
                    foreach($notify_clients_second as $item){
                        $secondBody = $reminder_customer_sms->second_sms_body ?? $reminder_customer_sms->sms_body;
                        (new ExpireCustomerNotifySms)->otherResellerCustomerSendSmsBeforeExpire($item,$reseller_sms_getway->sms_gateway,$reseller_sms_getway->reseller->name,
                                                            $reseller_sms_getway->reseller->contact,$secondBody,$reseller_sms_getway->reseller->id);
                    }
                }
            }

        }
    }

    public function getAllEligibleClientsToNotifyWithSms($pop_ids, $days)
    {
        $clientsQuery = Client::with([
            'customerAccount',
            'packages:id,package_rate,package_bandwidth,btrc_package_price',
            'clientsinfo:id,client_id,contact_no,clients_name'
        ])
        ->whereIn('clients_status', ['active', 'expired', 'disable'])
        ->whereIn('pop_id', $pop_ids);

        // Only for clients whose POP is in Pop::where('bill_generate', 'yes')
        // enforce customerAccount.dueAmount > 0 (and only when billing is not day_to_day).
        if (getBillingType() != 'day_to_day') {
            $billGeneratePopIds = Pop::whereIn('id', $pop_ids)
                                     ->where('bill_generate', 'yes')
                                     ->pluck('id');

            if ($billGeneratePopIds->isNotEmpty()) {
                $clientsQuery->where(function ($q) use ($billGeneratePopIds) {
                    // Clients under bill_generate = 'yes' POPs must have dueAmount > 0
                    $q->where(function ($q2) use ($billGeneratePopIds) {
                        $q2->whereIn('pop_id', $billGeneratePopIds)
                           ->whereHas('customerAccount', function ($q3) {
                               $q3->where('dueAmount', '>', 0);
                           });
                    })
                    // Clients under other POPs are included without dueAmount restriction
                    ->orWhereNotIn('pop_id', $billGeneratePopIds);
                });
            }
        }

        // Handle first day of the month
        if (today()->format('d') == '01' && getBillingType() != 'day_to_day') {
            SmsPaymentReminder::where('expire_date', today()->format('Y-m-d'))->delete();
            $clientsQuery->where(function ($q) use ($days) {
                $q->where('expire_date', today())
                ->orWhere('expire_date', today()->addDay($days));
            });
        } else {
            $clientsQuery->where('expire_date', today()->addDay($days));
        }

        return $clientsQuery->select(
            'id', 'expire_date', 'clients_status', 'pop_id',
            'userid', 'password', 'slug', 'package_id', 'customer_code'
        )->get();
    }


    public function sendSmsClients($clients,$message,$resellerSmsGateway = null,$reseller_id = null){
        $billingType = getBillingType();
        $dayToDayAfter10Days = siteinfo()->day_to_day_after_10_days === 'Yes';
        $shouldCheckDueAmount = $billingType === 'day_to_day' || $dayToDayAfter10Days;

        foreach ($clients as $client) {
            Log::error($client->id." check this");
            // Cache the required client data
            // Calculate due amount
            $checkDue = $client->customerAccount->dueAmount ?? 0;
            $packageRate = $client->packages->package_rate ?? 0;
            $permanentDiscount = $client->parmanent_discount ?? 0;
            $dueAmount = $packageRate + $checkDue - $permanentDiscount;

            // Decide whether to send the notification based on dueAmount and global conditions
            if (!$shouldCheckDueAmount || $dueAmount > 0) {



                if($resellerSmsGateway == null){
                    $contactNo = $client->clientsinfo->contact_no;
                    $finalMessage = $this->getMessage($client, $message);

                    $data = [
                        'message' => $finalMessage,
                        'contact_no' => $contactNo,
                        'type' => 'reminder'
                    ];
                    ExpireCustomerNotification::dispatch($data);
                }else{
                    $contactNo = $client->clientsinfo->contact_no;
                    $finalMessage = $this->getMessage($client, $message);
                    $data = [
                        'reseller_id' => $reseller_id,
                        'contact' => $contactNo,
                        'message' => $finalMessage,
                        'type' => "Reminder",
                        'api' => $resellerSmsGateway

                    ];
                    ResellerSendSms::dispatch($data);
                }

            }
        }
    }


}
