<?php

namespace App\Http\Controllers\V1;

use App\Http\Controllers\Controller;
use App\Core\Service\PropertyChannelGroupService;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Service\PropertyRoomService;
use App\Core\Repository\PropertyChannelGroup\PropertyChannelGroupChannelMappingRepository;
use Illuminate\Http\Request;

use App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
use Exception;
use App\Exceptions\ApiErrorException;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class PropertyChannelGroupController extends Controller
{


    private $request;
    private $propertyChannelGroupService;
    private $propertyChannelMappingService;
    private $propertyRoomService;
    private $propertyChannelGroupChannelMappingRepository;


    public function __construct(
        Request $request,
        PropertyChannelGroupService $propertyChannelGroupService,
        PropertyChannelGroupChannelMappingRepository $propertyChannelGroupChannelMappingRepository,
        PropertyChannelMappingService $propertyChannelMappingService,
        PropertyRoomService $propertyRoomService
    )
    {
        $this->request = $request;
        $this->propertyChannelGroupService = $propertyChannelGroupService;
        $this->propertyChannelGroupChannelMappingRepository = $propertyChannelGroupChannelMappingRepository;
        $this->propertyChannelMappingService = $propertyChannelMappingService;
        $this->propertyRoomService = $propertyRoomService;
    }


    public function getPropertyChannelGroup(Request $request)
    {

        $response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
        try {

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = $this->request->params;

            $requestParams = [
                'property_id' => fillOnUndefined($params, 'property_id'),
            ];

            if(isset($request->params['group_id'])){
                $requestParams = [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'id' => fillOnUndefined($params, 'group_id'),
                ];
            }

            $propertyChannelGroup = $this->propertyChannelGroupService->getPropertyChannelGroup($requestParams);
            if($propertyChannelGroup['status'] != 'success'){
                throw new ApiErrorException($propertyChannelGroup['message']);
            }

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $propertyChannelGroup['data']];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
            $response['statusCode'] = 400;
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            $response['statusCode'] = 500;
        }
        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


    }

    public function addPropertyChannelGroup(Request $request)
    {

        $response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
        try {

            DB::beginTransaction();

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = $this->request->params;

            $requestParams = [
                'property_id' => fillOnUndefined($params, 'property_id', null),
                'name' => fillOnUndefined($params, 'name', null),
                'created_by' => $this->request->auth->id,
                'updated_by' => $this->request->auth->id,
            ];


            $propertyChannelGroup = $this->propertyChannelGroupService->create($requestParams);
            if($propertyChannelGroup['status'] != 'success'){
                throw new ApiErrorException($propertyChannelGroup['message']);
            }

            $channels = fillOnUndefined($params, 'channels',[]);

            $insertData = [];
            foreach ($channels as $channel){
                $insertData[] = [
                    'channel_group_id' => $propertyChannelGroup['data']['id'],
                    'channel_id' => $channel,
                    'status' => 1,
                    'created_by' => $this->request->auth->id,
                    'updated_by' => $this->request->auth->id,
                    'created_at' => time(),
                    'updated_at' => time()
                ];
            }

            $propertyChannelGroupChannels = $this->propertyChannelGroupChannelMappingRepository->insert($insertData);
            if($propertyChannelGroupChannels['status'] != 'success'){
                throw new ApiErrorException($propertyChannelGroupChannels['message']);
            }

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $propertyChannelGroup['data']];
            DB::commit();

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
            $response['statusCode'] = 400;
            DB::rollBack();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            $response['statusCode'] = 500;
            DB::rollBack();
        }
        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


    }

    public function updatePropertyChannelGroup(Request $request)
        {

            $response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
            try {

                DB::beginTransaction();

                if (is_null($this->request->getContent())) {
                    throw new ApiErrorException(lang('Parameter Error.'));
                }

                $params = $this->request->params;

                $requestParams = [
                    'name' => fillOnUndefined($params, 'name', null),
                    'updated_by' => $this->request->auth->id,
                    'updated_at' => time()
                ];


                $propertyChannelGroup = $this->propertyChannelGroupService->update($params['group_id'], $requestParams);
                if($propertyChannelGroup['status'] != 'success'){
                    throw new ApiErrorException($propertyChannelGroup['message']);
                }

                $channels = fillOnUndefined($params, 'channels',[]);

                $channelRequest = [
                    'criteria' => [
                        ['field' => 'channel_group_id', 'condition' => '=', 'value' => $params['group_id']],
                    ]
                ];

                $propertyChannelGroupChannelDelete = $this->propertyChannelGroupChannelMappingRepository->delete($channelRequest);

                $insertData = [];
                foreach ($channels as $channel){
                    $insertData[] = [
                        'channel_group_id' => $params['group_id'],
                        'channel_id' => $channel,
                        'status' => 1,
                        'created_by' => $this->request->auth->id,
                        'updated_by' => $this->request->auth->id,
                        'created_at' => time(),
                        'updated_at' => time()
                    ];
                }

                $propertyChannelGroupChannels = $this->propertyChannelGroupChannelMappingRepository->insert($insertData);
                if($propertyChannelGroupChannels['status'] != 'success'){
                    throw new ApiErrorException($propertyChannelGroupChannels['message']);
                }

                $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $propertyChannelGroup['data']];
                DB::commit();

            } catch (ApiErrorException $e) {
                $response['message'] = implode(', ', $e->getMessageArr());
                $response['statusCode'] = 400;
                DB::rollBack();
            } catch (Exception $e) {
                $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
                Log::error($message);
                $response['message'] = $e->getMessage();
                $response['statusCode'] = 500;
                DB::rollBack();
            }
            return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


        }

    public function getPropertyGroupInventory(Request $request)
    {

        $response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
        try {

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = $this->request->params;


            $startDate = fillOnUndefinedAndEmpty($params, 'start_date', date('Y-m-d')) ;
            $endDate = fillOnUndefinedAndEmpty($params, 'end_date', Carbon::parse($startDate)->addDay(15)->format('Y-m-d')) ;

            if($endDate < $startDate){
                throw new ApiErrorException('date error') ;
            }
            $diffInDays = Carbon::parse($startDate)->diffInDays($endDate);
            if($diffInDays > 15){
                throw new ApiErrorException('date error') ;
            }


            $requestParams = [
                'locale' => fillOnUndefined($params, 'locale'),
                'property_id' => fillOnUndefined($params, 'property_id'),
                'channel_group_id' => fillOnUndefined($params, 'channel_group_id'),
                'start_date' => fillOnUndefined($params, 'start_date'),
                'end_date' => fillOnUndefined($params, 'end_date'),

            ];

            $groupActiveChannels = $this->propertyChannelGroupService->getPropertyChannelGroupActiveChannels($requestParams);
            if($groupActiveChannels['status'] != 'success'){
                throw new ApiErrorException($groupActiveChannels['message']);
            }

            $inventoryData = $groupActiveChannels["data"];
            $inventoryData['channel_ids'] = [];
            $inventoryData['currencies'] = [];
            foreach ($groupActiveChannels['data']['channel_group_active_channels'] as $groupActiveChannel){

                $channelId = $groupActiveChannel['channel_id'];

                $checkPropertyChannelMappingRequestParams = [
                    'criteria' => [
                        ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                        ['field' => 'channel_id', 'condition' => '=', 'value' => $channelId],
                        ['field' => 'status', 'condition' => '=', 'value' => 1]
                    ]
                ];

                $checkPropertyChannelMapping = $this->propertyChannelMappingService->select($checkPropertyChannelMappingRequestParams,['id', 'property_id', 'status']) ;
                if($checkPropertyChannelMapping['status'] != 'success'){
                    throw new ApiErrorException($checkPropertyChannelMapping['message']);
                }

                if(!empty($checkPropertyChannelMapping['data'])){
                    $inventoryData['channels'][$channelId] = $groupActiveChannel['channel'];
                    $inventoryData['channel_ids'][$channelId] = $channelId;
                }
            }

            if(!count($inventoryData['channel_ids'])){
                throw new ApiErrorException("There isn't any active channel in this channel group");
            }

            $channelMappingRequestParams = [
                'locale' => fillOnUndefined($params, 'locale'),
                'property_id' => $params['property_id'],
                'channel_ids' => $inventoryData['channel_ids'],
            ];

            $getChannelMappingResponse = $this->propertyChannelMappingService->getPropertyChannelMappingForChannelGroup($channelMappingRequestParams) ;
            if($getChannelMappingResponse['status'] != 'success'){
                throw new ApiErrorException($getChannelMappingResponse['message']);
            }

            foreach ($getChannelMappingResponse["data"] as $channelMapping){
                $channelId = $channelMapping['channel_id'];

                $inventoryData['channels'][$channelId]['currency_code'] = $channelMapping['currency_code'];
                $inventoryData['channels'][$channelId]['property_availability_type_id'] = $channelMapping['property_availability_type_id'];

                $inventoryData['currencies'][$channelMapping['currency_code']] = $channelMapping['currency_code'];
            }


            foreach ($inventoryData['channel_ids'] as $channelId){

                $getGroupInventoryRequestParams = [
                    'locale' => fillOnUndefined($params, 'locale'),
                    'property_id' => $params['property_id'],
                    'channel_id' => $channelId,
                ];

                $inventoryData['channels'][$channelId]['rooms_temp'] = $this->propertyRoomService->inventoryRoomList($getGroupInventoryRequestParams);

            }


            foreach ($inventoryData['channels'] as $channel){

                $channelId = $channel['id'];
                $currency = $channel['currency_code'];

                foreach ($channel['rooms_temp'] as $roomTemp){

                    $roomId = $roomTemp['id'];

                    $dateKey = Carbon::parse($params['start_date']);
                    for ($i = 0; $i <= $diffInDays; $i++) {

                        $responseAVAKey = 'AVA_1_'.$roomId.'_'. '0' .'_'.$dateKey->format('Ymd') ;
                        $responseSTSKey = 'STS_1_'.$roomId.'_'. '0' .'_'.$dateKey->format('Ymd') ;

                        $roomAvailability[$dateKey->format('Y-m-d')] = [
                            'key' => $responseAVAKey,
                            'value' => null,
                            'stop_sell' => 0
                        ];

                        $roomStopSell[$dateKey->format('Y-m-d')] = [
                            'key' => $responseSTSKey,
                            'value' => 0,
                        ];

                        $dateKey = $dateKey->addDay();
                    }

                    foreach ($roomTemp['property_room_rate_mapping'] as $roomRateMapping ){

                        $roomRate = $roomRateMapping['property_room_rate'];
                        $roomRateId = $roomRate['id'];
                        $roomRateChannel = $roomRateMapping['property_room_rate_channel'];


                        foreach ($roomRateChannel as $roomRateChan){

                            if($roomRateChan['channel_id'] == $channelId && $roomRateChan['status'] == 1){

                                $inventoryData['rooms'][$roomId]['id'] = $roomTemp['id'];
                                $inventoryData['rooms'][$roomId]['name'] = $roomTemp['name'];
                                $inventoryData['rooms'][$roomId]['room_selected'] = false;
                                $inventoryData['rooms'][$roomId]['availability'] = $roomAvailability;
                                $inventoryData['rooms'][$roomId]['room_stop_sell'] = $roomStopSell;

                                $rate['id'] = $roomRateId;
                                $rate['name'] = $roomRate['name'];
                                $rate['currency'] = $currency;
                                $rate['rate_selected'] = false;
                                $rate['room_rate_mapping_id'] = $roomRateChan['room_rate_mapping_id'];


                                $dateKey = Carbon::parse($params['start_date']);
                                for ($i = 0; $i <= $diffInDays; $i++) {

                                    $responsePRCKey = 'PRC_1'.'_'.$roomRateMapping['room_id'].'_'. $roomRateMapping['id'].'_'.$dateKey->format('Ymd').'_'.$currency ;
                                    $responseSTSKey = 'STS_1'.'_'.$roomRateMapping['room_id'].'_'. $roomRateMapping['id'].'_'.$dateKey->format('Ymd');
                                    $responseMNSKey = 'MNS_1'.'_'.$roomRateMapping['room_id'].'_'. $roomRateMapping['id'].'_'.$dateKey->format('Ymd');

                                    $price[$dateKey->format('Y-m-d')] = [
                                        'key' => $responsePRCKey,
                                        'value' => null,
                                        'stop_sell' => 0
                                    ];

                                    $stopSell[$dateKey->format('Y-m-d')] = [
                                        'key' => $responseSTSKey,
                                        'value' => 0,
                                    ];

                                    $minStay[$dateKey->format('Y-m-d')] = [
                                        'key' => $responseMNSKey,
                                        'value' => 1,
                                    ];

                                    $dateKey = $dateKey->addDay();
                                }

                                $rate['price'] = $price;
                                $rate['stop_sell'] = $stopSell;
                                $rate['min_stay'] = $minStay;


                                $inventoryData['rooms'][$roomId]['rates'][$roomRateId][$currency] = $rate;

                            }
                        }
                    }
                }

            }

            if(isset($inventoryData['channel_group_active_channels'])){
                unset($inventoryData['channel_group_active_channels']);
            }

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $inventoryData];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
            $response['statusCode'] = 400;
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            $response['statusCode'] = 500;
        }
        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


    }

    public function createPropertyChannelGroup(Request $request)
    {

        $response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
        try {

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = $this->request->params;


            $mappedChannelCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => ['channel'],
            ];

            $propertyChannelsForGroup = $this->propertyChannelMappingService->select($mappedChannelCriteria);
            if($propertyChannelsForGroup['status'] != 'success'){
                throw new ApiErrorException($propertyChannelsForGroup['message']);
            }

            $channels = [];

            foreach ($propertyChannelsForGroup['data'] as $data){
                if($data['property_availability_type_id'] == 1 && $data['channel']['parent_id'] == null){
                    $channels[$data['id']] = $data['channel'];
                }
            }

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $channels];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
            $response['statusCode'] = 400;
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            $response['statusCode'] = 500;
        }
        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


    }


}