<?php

namespace App\Console\Commands\ChannelManager;

use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManager\Reseliva;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Core\Service\ChannelManagerService;
use App\Core\Service\PropertyRoomAvailabilityQueueService;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyRoomAvailabilityQueue;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;

class RoomAvailabilityPushService extends Command
{
    protected $signature = 'cron:roomavailability-push-service';

    protected $description = '';
    protected $mailer;
    protected $channelService;
    protected $channelManagerService;
    protected $propertyRoomAvailabilityQueueService;

    public function __construct(
        Mailer $mailer,
        ChannelManagerService $channelManagerService,
        PropertyRoomAvailabilityQueueService $propertyRoomAvailabilityQueueService,
        ChannelManagerPropertyMappingService $channelManagerPropertyMappingService
    )
    {
        parent::__construct();
        $this->mailer = $mailer;
        $this->channelManagerService = $channelManagerService;
        $this->propertyRoomAvailabilityQueueService = $propertyRoomAvailabilityQueueService;
        $this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
    }

    public function handle()
    {

        try {

            $this->info(date('Y-m-d H:i:s') . ' : Start');

            //Queue Check
            $this->info(date('Y-m-d H:i:s') . ' : Queue Check');
            $roomAvailabilityQueueCountCriteria = ['criteria' => [['field' => 'status', 'condition' => '=', 'value' => 1]], 'count' => true];
            $roomAvailabilityQueueCount = $this->propertyRoomAvailabilityQueueService->select($roomAvailabilityQueueCountCriteria);
            if ($roomAvailabilityQueueCount['status'] == 'success') {
                $roomAvailabilityQueueCount = $roomAvailabilityQueueCount['data'];

                if ($roomAvailabilityQueueCount > 2000) {


                    $roomAvailabilityQueueCountGroupByProperty = PropertyRoomAvailabilityQueue::selectRaw('property_id, COUNT(*) as total')
                        ->groupBy('property_id')
                        ->orderByDesc('total')
                        ->first();

                    $roomAvailabilityQueueCountGroupByProperty = $roomAvailabilityQueueCountGroupByProperty ? $roomAvailabilityQueueCountGroupByProperty->toArray() : null;
                    if ($roomAvailabilityQueueCountGroupByProperty) {
                        if ($roomAvailabilityQueueCountGroupByProperty['total'] > 1000) {
                            PropertyRoomAvailabilityQueue::where('property_id', $roomAvailabilityQueueCountGroupByProperty['property_id'])->delete();
                        }
                    }

                }

                if ($roomAvailabilityQueueCount > 1000) {

                    $this->error(date('Y-m-d H:i:s') . ' : Queue Alarm: ' . $roomAvailabilityQueueCount);

                    //Clear Test Property Data
                    PropertyRoomAvailabilityQueue::where('property_id', 1)->delete();

                    //$logMessage
                    $mailParams = [
                        'title' => 'RoomAvailabilityPushService Error - Queue Error',
                        'logMessage' => 'Queue: ' . $roomAvailabilityQueueCount
                    ];

                    $this->mailer->onQueue('logMail', new LogMail($mailParams));
                    //$logMessage
                }
            }
            //Queue Check


            $channelManagerCriteria =
                [
                    'criteria' =>
                        [
                            ['field' => 'status', 'condition' => '=', 'value' => 1],
                        ],
                    /*'whereIn' =>
                        [
                            ['field' => 'id', "value" => [7]]
                        ],*/
                    'orderBy' => [
                        ['field' => 'id', 'value' => 'ASC']
                    ]
                ];

            $channelManager = $this->channelManagerService->select($channelManagerCriteria);

            $channelManagerList = [];
            if ($channelManager['status'] == 'success' && !empty($channelManager['data'])) {
                $channelManagerList = $channelManager['data'];
            }


            $roomAvailabilityQueueCriteria =
                [
                    'criteria' =>
                        [
                            ['field' => 'status', 'condition' => '=', 'value' => 1],
                        ],
                    'with' => ['property'/*, 'propertyChannelManager.channelManagerRoomRate.propertyRoomRateMapping'*/],
                    'orderBy' => [
                        ['field' => 'id', 'value' => 'ASC']
                    ],
                    'take' => 500
                ];

            $roomAvailabilityQueue = $this->propertyRoomAvailabilityQueueService->select($roomAvailabilityQueueCriteria);

            if ($roomAvailabilityQueue['status'] == 'success' && !empty($roomAvailabilityQueue['data'])) {


                foreach ($roomAvailabilityQueue['data'] as $data) {
                    $roomAvailabilityQueueData[$data['property_id']][] = $data;
                }


                $channelManagerPushedIdsList = [];
                $channelManagerNoneMappingIdsList = [];

                //PROPERTY
                foreach ($roomAvailabilityQueueData as $roomAvailabilityQueuePropertyId => $roomAvailabilityQueueProperty) {


                    //CHANNEL MANAGER
                    $channelManagerCheckList = [];
                    foreach ($channelManagerList as $channelKey => $channel) {

                        if (in_array($channel['id'], [7, 10, 13])) {
                            continue;
                        }

                        $this->info(date('Y-m-d H:i:s') . ' : Channel Start: ' . $channel['name']);

                        if (!class_exists("App\Core\Service\ChannelManager\\{$channel['name']}")) {
                            $this->error(date('Y-m-d H:i:s') . ' : Channel: ' . $channel['name'] . ' Class does not exist!');
                            continue;
                        }

                        $channelService = App::make("App\Core\Service\ChannelManager\\{$channel['name']}");

                        $channelManagerPropertyMappingCriteria = [
                            'criteria' =>
                                [
                                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                                    ['field' => 'property_id', 'condition' => '=', 'value' => $roomAvailabilityQueuePropertyId],
                                    ['field' => 'channel_manager_id', 'condition' => '=', 'value' => $channel['id']],
                                    ['field' => 'channel_manager_property_id', 'condition' => '!=', 'value' => null],
                                ],
                            'firstRow' => true,
                        ];

                        $channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria);


                        if ($channelManagerPropertyMapping['status'] != 'success' || ($channelManagerPropertyMapping['status'] == 'success' && empty($channelManagerPropertyMapping['data']))) {
                            $this->info(date('Y-m-d H:i:s') . ' : Channel: ' . $channel['name'] . ' PropertyID: ' . $roomAvailabilityQueuePropertyId . ' : PASS');
                            continue;
                        }

                        $channelManagerCheckList[$channel['id']] = true;

                        $roomAvailabilityPush = $channelService->roomAvailabilityPush($roomAvailabilityQueuePropertyId, $roomAvailabilityQueueProperty);

                        if ($roomAvailabilityPush['status']) {

                            $channelManagerPushedIdsList[$channel['id']] = $roomAvailabilityPush['data']['channelManagerPushedIds'];
                            $channelManagerNoneMappingIdsList[$channel['id']] = $roomAvailabilityPush['data']['channelManagerNoneMappingIds'];

                            $this->info(date('Y-m-d H:i:s') . ' : Success: ' . $channel['name']);

                        } else {

                            $channelManagerCheckList[$channel['id']] = false;

                            //$logMessage
                            $mailParams = [
                                'title' => $channel['name'] . ' - RoomAvailabilityPushService Error - inventoryRoomRateUpdate Error',
                                'logMessage' => '<pre>' . print_r($roomAvailabilityPush, true) . '</pre>'
                            ];

                            $this->mailer->onQueue('logMail', new LogMail($mailParams));
                            //$logMessage

                            $this->error(date('Y-m-d H:i:s') . ' : Error: ' . $channel['name'] . ' - ' . $roomAvailabilityPush['message']);


                        }

                        $this->info(date('Y-m-d H:i:s') . ' : Channel Finished: ' . $channel['name']);

                    }

                    if (in_array(false, $channelManagerCheckList)) {
                        $this->error(date('Y-m-d H:i:s') . ' : Error Break: ' . var_export($channelManagerCheckList));
                        continue;
                    }

                    if (count($channelManagerPushedIdsList) > 1) {
                        $channelManagerPushedIdIntersect = call_user_func_array('array_intersect', $channelManagerPushedIdsList);
                        if (!empty($channelManagerPushedIdIntersect)) {
                            $this->propertyRoomAvailabilityQueueService->delete($channelManagerPushedIdIntersect);
                            $this->info(date('Y-m-d H:i:s') . ' : channelManagerPushedIdsList Deleted: ' . var_dump($channelManagerPushedIdIntersect));
                        }
                    } elseif (!empty($channelManagerPushedIdsList)) {
                        $this->propertyRoomAvailabilityQueueService->delete(reset($channelManagerPushedIdsList));
                        $this->info(date('Y-m-d H:i:s') . ' : channelManagerPushedIdsList Deleted: ' . var_dump($channelManagerPushedIdsList));
                    }

                    if (empty($channelManagerNoneMappingIdsList)) {
                        $this->info(date('Y-m-d H:i:s') . ' : channelManagerNoneMappingIdsList Empty');
                        continue;
                    }

                    $channelManagerNoneMappingIdsListMerge = call_user_func_array('array_merge', $channelManagerNoneMappingIdsList);
                    if (!empty($channelManagerNoneMappingIdsListMerge)) {
                        $this->propertyRoomAvailabilityQueueService->delete($channelManagerNoneMappingIdsListMerge);
                        $this->info(date('Y-m-d H:i:s') . ' : channelManagerNoneMappingIdsListMerge Deleted: ' . var_dump($channelManagerNoneMappingIdsListMerge));
                    }

                }


            }


            $this->info(date('Y-m-d H:i:s') . ' : Finished');

        } catch (ApiErrorException $e) {
            $this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
        }

    }

}
