<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Libs\Services\FcmService;
use App\Services\ExhibitionDataService;
use App\Services\FcmMessageDataService;
use Illuminate\Support\Carbon;
use App;
use Illuminate\Support\Str;
use Throwable;
use Illuminate\Support\Facades\Log;

class ProcessWeeklyOpeningNotifications implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected ExhibitionDataService $exhibitionDataService;
    protected FcmService $fcmService;
    protected FcmMessageDataService $fcmDataService;
    private const EXHIBITION_TEXT_SEPARATOR = ' | ';
    private string $topic                   = FcmService::TOPIC_WEEKLY_OPENINGS;
    public const QUEUE                      = 'weekly_openings';

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->onQueue(static::QUEUE);
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle(
        FcmService $fcmService,
        ExhibitionDataService $exhibitionDataService,
        FcmMessageDataService $fcmDataService
    ) {
        $this->exhibitionDataService = $exhibitionDataService;
        $this->fcmService            = $fcmService;
        $this->fcmDataService        = $fcmDataService;

        if (!FcmService::areFcmNotificationsActive()) {
            Log::info('The ProcessWeeklyOpeningNotifications was executed but FCM notifications are inactive');
            return;
        }

        //upcoming week
        // $weekStartDate = $now->startOfWeek(Carbon::MONDAY)->addDays(7)->startOfDay();
        // $weekEndDate   = $now->endOfWeek(Carbon::SUNDAY))->addDays(7)>endOfDay();
        //current week
        $weekStartDate  = now()->startOfWeek(Carbon::MONDAY)->startOfDay();
        $weekEndDate    = now()->endOfWeek(Carbon::SUNDAY)->endOfDay();
        $weekNumber     = $weekStartDate->weekOfYear;
        $controlWeek    = $weekNumber . '_' . date('Y');
        $weekStartDate  = $weekStartDate->format('Y-m-d H:i:s');
        $weekEndDate    = $weekEndDate->format('Y-m-d H:i:s');
        $langCodes      = getAvailableLanguageCodes();
        $messageContent = [];
        $resSend        = null;

        //check if a message for the week has been sent 
        if ($this->fcmDataService->wasWeeklyExhibitionsMessageSent($controlWeek)) {
            Log::info('The ProcessWeeklyOpeningNotifications was executed but the notification has been sent for this week.');
            return;
        }


        //We need to get the exhibitions in both lang codes since the notifications are localized
        foreach ($langCodes as $langCode) {
            App::setlocale($langCode);
            //getting the exibitions that open on the desired week
            $localizedExhibitions = $this->exhibitionDataService->getOpeningBetween($weekStartDate, $weekEndDate);
            $exhibitsCount        = $localizedExhibitions->count();
            if ($exhibitsCount == 0) {
                continue;
            }

            //get the title
            $title = trans_choice('fcm.' . FcmService::TOPIC_WEEKLY_OPENINGS . '.title', $exhibitsCount, [
                'total' => $exhibitsCount
            ]);
            //add the emoji
            $title = "\u{1F37E}" . ' ' . $title;
            $body = '';
            foreach ($localizedExhibitions as $localizedExhibition) {

                $location    = $localizedExhibition->location->city ?
                    $localizedExhibition->location->city->title :
                    $localizedExhibition->location->title;

                $artist      = $localizedExhibition->artists->first();
                $transParams = [
                    'name'     => $localizedExhibition->title,
                    'artist'   => $artist ? $artist->title : 'n/a',
                    'location' => $location,

                ];
                $body        .= trans('fcm.' . FcmService::TOPIC_WEEKLY_OPENINGS . '.body_template', $transParams) . self::EXHIBITION_TEXT_SEPARATOR;
            }

            $localizedTopic = $this->topic . '_' . $langCode;
            $body           = rtrim($body, self::EXHIBITION_TEXT_SEPARATOR);
            $body           = trans('fcm.' . FcmService::TOPIC_WEEKLY_OPENINGS . '.body', ['body' => $body]);
            $data           = [
                'topic' => $this->topic
            ];
            $body           = Str::limit($body, 1000, '...');
            $message        = $this->fcmService->getTopicMessageStructure($localizedTopic, $title, $body, $data);

            //send the message to the topic
            try {
                $messageId = $this->fcmService->sendMessageToTopic($message);

                if (!$resSend && $messageId) {
                    $resSend        = $messageId;
                    $messageContent = $message;
                    Log::info('The ProcessWeeklyOpeningNotifications was and sent with the message id ' . $messageId . ' for the localized topic ' . $localizedTopic);
                }
            } catch (Throwable $t) {
                Log::error('Error sending weekly exhibits notification: ' . $t->getMessage());
            }
        }


        //At this point we need to check the sending result and store the sent message to avoid repetitions
        //we will assume that if the message was sent to one topic it was sent for all 
        if ($resSend) {
            $this->fcmDataService->addFcmTopicMessage('weekly_openings', $resSend, $messageContent, null, $controlWeek);
        }
    }
}
