<?php

namespace App\Console\Commands;

use App\Imports\SendinBlueContactImport;
use App\Subscriber;
use App\SubscriberContactFileImport;
use App\Tools\SendinBlueEmailService;
use App\UserEmailCampaign;
use App\UserMailingList;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;

class PushMailCampaignAndContactsToSendinBlue extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */

    protected $signature = 'push:mail-campaign';

    /**
     * The console command description.
     *
     * @var string
     */


    protected $description = 'Push Mail Campaign and Contacts To SendinBlue API';

    private $sendinblue;
    private $senderEmail;

    public function __construct()
    {
        parent::__construct();
        $this->sendinblue = new SendinBlueEmailService();
        $this->senderEmail = 'digitalandmarketing@gcb.com.gh';
//        $this->senderEmail = 'support@npontu.com';
    }



    public function handle()
    {
        $currentTimeStamp = Carbon::now()->format('Y-m-d H:i:s');

        $this->appLog("============================== START PUSHING MAIL CAMPAIGN & CONTACTS TO SENDINBLUE API ==============================");
        $this->appLog("============================== START PUSHING MAIL CAMPAIGN & CONTACTS TO SENDINBLUE API ==============================");

        // Get all pending campaigns
        $allPendingCampaigns = UserEmailCampaign::query()->whereNotNull('schedule_at')
            ->whereIn('status',['pending','update'])->where('schedule_at','>=',$currentTimeStamp)->get();


        $allPendingCampaigns->map(function ($campaign){

            // Get email contact list for the pending campaign
            $mailContacts = SubscriberContactFileImport::query()->where('user_mailing_list_id','=',$campaign->user_mailing_list_id)->latest()->first();

            // Check if file exists
            $fileExist = isset($mailContacts->file_path) && Storage::exists($mailContacts->file_path);

            // If There is an email contact record && the email Contacts File Exist
            if (isset($mailContacts) && $fileExist){

                $fileUrl = $mailContacts->file_url;
                $listId = $this->list($mailContacts->user_mailing_list_id);

                // start uploading contacts, change status
                $mailContacts->update(['status' => 'starting']);

                // Publishing Contacts On SendinBlue
                $response = $this->sendinblue_publish_contacts($fileUrl, $listId->api_mail_list_id);

                // Check if publishing is successful
                if(isset($response['processId'])) {

                    // Publishing Contacts Locally
                    if ($mailContacts->file_contacts):

                        // Delete Temporal local contacts
                        $this->deleteTemporalEmailContacts($mailContacts->user_mailing_list_id);

                        // Delete Subscribed local contacts
                        $this->deleteSubscribedEmailContacts($mailContacts->user_mailing_list_id);

                        // Publish contacts locally
                        $contacts = json_decode($mailContacts->file_contacts, true);
                        $this->local_publish($contacts);
                    endif;

                    // Updating contact file import Contacts Locally
                    $mailContacts->update([
                        'status' => 'completed',
                        'processId' => $response['processId']
                    ]);
                    $this->appLog("Successful in Importing Mail Contacts");
                }
                else{
                    // starting to upload contacts, change status
                    $mailContacts->update(['status' => 'failed']);

                    // Error Encountered import file
                    $this->appLog("Error Encountered while Importing Mail Contacts | Error: " . json_encode($response['message']));
                }
            }

            if (isset($mailContacts) && $mailContacts->status == 'completed'){
                if ($campaign->status == 'update' && !empty($campaign->mail_campaign_id)){
                    $this->updateCampaignOnSendinblue($campaign);
                }
                else{
                    $this->pushCampaignToSendinblue($campaign);
                }

            }

        });

        $this->appLog("============================== END PUSHING MAIL CAMPAIGN & CONTACTS TO SENDINBLUE API ==============================");
        $this->appLog("============================== END PUSHING MAIL CAMPAIGN & CONTACTS TO SENDINBLUE API ==============================");

    }


    public function pushCampaignToSendinblue($campaignData){
        //save and send campaign email
        try {
            $userCampaign = $campaignData;
            //store campaign mail
            $endpoint = 'create-campaign-email';
            $sendinblue =  $this->sendinblue;
            $schedule_at = Carbon::createFromFormat('Y-m-d H:i:s', $campaignData->schedule_at)->format('Y-m-d\TH:i:sP');
            $attachmentUrl = $campaignData->user_email_campaign_attachment()->latest()->first();
            $htmlContent = '<!DOCTYPE html> <html> <body> '. $campaignData->message . ' </body> </html>';

            // Get list id on sendinblue
            $listId = $this->list($campaignData->user_mailing_list_id);

            $formData = [
                'listIds' => $listId->api_mail_list_id ?? '',
                'tag' => $campaignData->tag,
                'senderName' => $campaignData->from_name,
                'senderEmail' => $this->senderEmail,
                'replyTo' => $campaignData->reply_to,
                'subject' => $campaignData->subject,
                'campaignName' => $campaignData->campaign_name,
                'companyEmail' => $campaignData->company_email,
                'emailFooter' => $campaignData->email_footer,
                'htmlContent' => $htmlContent,
                'attachmentUrl' => isset($attachmentUrl) ? ($attachmentUrl->file_url ?? '') : '',
                'scheduleAt' => $campaignData->schedule_at ?? Carbon::now()->addMinutes(10)->format('Y-m-d H:i:s')
            ];

            $response = $sendinblue->postApiCall($endpoint, $formData);

            //if response is not an error, update the campaign with content
            if (isset($response['id']))
            {
                //update the user campaign both locally and on sendinblue with the campaign id
                $userCampaign->update([
                    'mail_campaign_id' => $response['id'],
                    'status' => 'pushed',
                ]);

                $this->appLog("Successfully Created Campaign On Sendinblue | Response: " . json_encode($response));
            }
            else{
                $this->appLog("Error Creating Campaign On Sendinblue | Response: " . json_encode($response));
            }

        }
        catch (\Exception $e) {
            $this->appLog("Error Creating Campaign On Sendinblue " . $e->getMessage());
        }
    }


    public function updateCampaignOnSendinblue($campaignData){
        //update and schedule campaign email
        try {
            // Get list id on sendinblue
            $listId = $this->list($campaignData->user_mailing_list_id);
            //store campaign mail
            $endpoint = "update-campaign-email/". $campaignData->mail_campaign_id;
            $attachmentUrl = $campaignData->user_email_campaign_attachment()->latest()->first();
            $htmlContent = '<!DOCTYPE html> <html> <body> '. $campaignData->message . ' </body> </html>';
            $formData = [
                'listIds' => $listId->api_mail_list_id ?? '',
                'tag' => $campaignData->tag,
                'senderName' => $campaignData->from_name,
                'senderEmail' => $this->senderEmail,
                'replyTo' => $campaignData->reply_to,
                'subject' => $campaignData->subject,
                'campaignName' => $campaignData->campaign_name,
                'companyEmail' => $campaignData->company_email,
                'emailFooter' => $campaignData->email_footer,
                'htmlContent' => $htmlContent,
                'attachmentUrl' => isset($attachmentUrl) ? ($attachmentUrl->file_url ?? '') : '',
                'scheduleAt' => $campaignData->schedule_at ?? Carbon::now()->addMinutes(10)->format('Y-m-d H:i:s')
            ];

            $response = $this->sendinblue->postApiCall($endpoint, $formData);

            //if response is not an error, update the campaign with content
            if (isset($response['status']) && $response['status'] == 'success')
            {
                //update the user campaign status locally
                $campaignData->update([
                    'status' => 'pushed',
                ]);
                $this->appLog("Successfully Updated Campaign On Sendinblue | Response: " . json_encode($response));
            }
            else{
                $this->appLog("Error Updating Campaign On Sendinblue | Response: " . json_encode($response));
            }

        }
        catch (\Exception $e) {
            $this->appLog("Error Updating Campaign On Sendinblue " . $e->getMessage());
        }
    }


    public function sendinblue_publish_contacts($fileUrl, $apiListId)
    {
        $endpoint = 'import-contacts';
        $sendinblue =  $this->sendinblue;

        $formData = [
            'listId' => $apiListId,
            'fileUrl' => $fileUrl
        ];

        return $sendinblue->postApiCall($endpoint, $formData);
    }


    public function local_publish($params)
    {
        Subscriber::query()->insert($params);
    }


    public function list($listId){
        return UserMailingList::query()->find($listId);
    }


    public function deleteTemporalEmailContacts($user_mailing_list_id){
        Subscriber::query()
            ->where('user_mailing_list_id','=',$user_mailing_list_id)
            ->where('status','=','temporal')
            ->forceDelete();
    }

    public function deleteSubscribedEmailContacts($user_mailing_list_id){
        Subscriber::query()
            ->where('user_mailing_list_id','=',$user_mailing_list_id)
            ->where('status','=','subscribed')
            ->delete();
    }


    public function appLog($message)
    {
        Log::channel('api_request')->info("\n");
        Log::channel('api_request')->info($message);
    }
}
