<?php

namespace App\Core\Service;

use App\Core\Repository\PropertyRoomRateChannelMapping\PropertyRoomRateChannelMappingRepository;
use App\Core\Repository\PropertyChannelMapping\PropertyChannelMappingRepository;
use App\Core\Validator\PropertyRoomRateChannelMapping\PropertyRoomRateChannelMappingAddValidator;
use App\Core\Validator\PropertyRoomRateChannelMapping\PropertyRoomRateChannelMappingUpdateValidator;
use App\Core\Repository\PropertyRoom\PropertyRoomRepository;
use App\Core\Repository\PropertyAvailabilityType\PropertyAvailabilityTypeRepository;
use \App\Core\Service\PropertyChannelMappingService;


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 PropertyRoomRateChannelMappingService
{

    private $propertyRoomRateChannelMappingRepository;
    private $propertyRoomRateChannelMappingAddValidator;
    private $propertyRoomRateChannelMappingUpdateValidator;
    private $propertyChannelMappingRepository ;
    private $propertyRoomRepository;
    private $propertyAvailabilityTypeRepository;
    private $propertyChannelMappingService;


    public function __construct(

        PropertyRoomRateChannelMappingRepository $propertyRoomRateChannelMappingRepository,
        PropertyChannelMappingRepository $propertyChannelMappingRepository,
        PropertyRoomRateChannelMappingUpdateValidator $propertyRoomRateChannelMappingUpdateValidator,
        PropertyRoomRateChannelMappingAddValidator $propertyRoomRateChannelMappingAddValidator,
        PropertyRoomRepository $propertyRoomRepository,
        PropertyAvailabilityTypeRepository $propertyAvailabilityTypeRepository,
        PropertyChannelMappingService $propertyChannelMappingService

    )
    {

        $this->propertyRoomRateChannelMappingRepository = $propertyRoomRateChannelMappingRepository;
        $this->propertyRoomRateChannelMappingAddValidator = $propertyRoomRateChannelMappingAddValidator;
        $this->propertyRoomRateChannelMappingUpdateValidator = $propertyRoomRateChannelMappingUpdateValidator;
        $this->propertyChannelMappingRepository = $propertyChannelMappingRepository;
        $this->propertyRoomRepository = $propertyRoomRepository ;
        $this->propertyAvailabilityTypeRepository = $propertyAvailabilityTypeRepository ;
        $this->propertyChannelMappingService = $propertyChannelMappingService ;


    }


    public function addPropertyRoomRateChannelMapping($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            DB::beginTransaction();
            $validateData =
                [
                    'room_rate_mapping_id' => fillOnUndefined($params, 'room_rate_mapping_id'),
                    'channels' => fillOnUndefined($params, 'channels'),
                    "created_by" => fillOnUndefined($params, "user_id"),
                    "updated_by" => fillOnUndefined($params, "user_id")
                ];

            $validationResult = $this->propertyRoomRateChannelMappingAddValidator->validate($validateData);


            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $deleteCriteria = [
                'criteria' => [
                    ['field' => 'room_rate_mapping_id', 'condition' => '=', 'value' => $validateData['room_rate_mapping_id']],
                ]
            ];

            $this->propertyRoomRateChannelMappingRepository->delete($deleteCriteria);


            foreach ($validateData["channels"] as $fact){
                $insertData = [
                    'property_id' => $params['property_id'] ,
                    'room_rate_mapping_id' => $validateData['room_rate_mapping_id'] ,
                    'channel_id' => $fact,
                    'status' => 1,
                    "created_by" => $validateData['created_by'] ,
                    "updated_by" =>$validateData['updated_by']  ,

                ];


                $userCreateResult = $this->propertyRoomRateChannelMappingRepository->create($insertData);
                if ($userCreateResult['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }
            }

            $response = [
                'status' => true,
                'data' => null,
            ];
            DB::commit();

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

        return output($response);
    }

    public function getPropertyRoomRateChannelMapping($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $criteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ]
            ];

            $data = $this->propertyRoomRateChannelMappingRepository->findByCriteria($criteria, ['id', 'room_rate_mapping_id', 'channel_id']);
            $data =  $data ? $data : [];
            $rateChannelMapping = [];
            foreach ($data as $mapping){
                $rateChannelMapping[$mapping['channel_id'].'|'.$mapping['room_rate_mapping_id']] = $mapping ;
            }


            $criteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'property_id')],
                ],
                'with' => ['propertyRoomRateMapping.propertyRoomRate']
            ];

            $data = $this->propertyRoomRepository->findByCriteria($criteria, ['id','property_id','name','room_type_id','max_occupancy','max_adult','max_child','exclude_occupancy','room_size','room_size_type', 'room_type_count', 'room_count', 'bathroom_count',  'toilet_count', 'lounge_count', 'max_child_number']);
            $roomData =  $data ? $data : [];
            $channels = [] ;
            foreach ($params['channels'] as $channelItem) {
                $rooms = [] ;
                $channel = $channelItem;
                foreach ($roomData as $roomItem) {
                    $room = $roomItem;
                    unset($room['property_room_rate_mapping']);
                    $rates = [] ;
                    foreach ($roomItem['property_room_rate_mapping'] as $roomRate) {
                        $rate = $roomRate ;
                        $checkKey = $channel['id'].'|'.$roomRate['id'];
                        unset($rate['property_room_rate']) ;
                        $rate['rate_name'] = $roomRate['property_room_rate']['name'];
                        $rate['rate_description'] = $roomRate['property_room_rate']['name'];
                        $rate['min_stay'] = $roomRate['property_room_rate']['min_stay'];
                        $rate['max_stay'] = $roomRate['property_room_rate']['max_stay'];
                        $rate['is_selected'] = isset($rateChannelMapping[$checkKey]);
                        $rates[] = $rate;
                    }
                    $room['rates'] = $rates ;
                    $rooms[] = $room ;
                }
                $channel['rooms'] = $rooms ;
                $channels[] = $channel ;
            }

            $response = [
                'status' => true,
                'data' => $channels,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    public function updatePropertyRoomRateChannelMapping($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            DB::beginTransaction();
            $validateData =
                [
                    'room_rate_channel_mapping' => fillOnUndefined($params, 'room_rate_channel_mapping'),
                    "created_by" => fillOnUndefined($params, "user_id"),
                    "updated_by" => fillOnUndefined($params, "user_id")
                ];

            $validationResult = $this->propertyRoomRateChannelMappingUpdateValidator->validate($validateData);
            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }


            foreach ($params['room_rate_channel_mapping'] as $mapping) {
                $hasDate  = isset($mapping['has_date'])  ? $mapping['has_date'] : 0 ;
                $startDate  = isset($mapping['start_date'])  ? $mapping['start_date'] : null ;
                $endDate  = isset($mapping['end_date'])  ? $mapping['end_date'] : null ;


                $checkData = [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $mapping['channel_id']],
                    ['field' => 'room_rate_mapping_id', 'condition' => '=', 'value' => $mapping['room_rate_mapping_id']],

                ];

                $checkParams = [
                    'property_id' => $params['property_id'],
                    'channel_id' => $mapping['channel_id'],
                ] ;

                $checkMappingStatus =$this->propertyChannelMappingService->checkPropertyChannelMapping($checkParams);
                if ($checkMappingStatus['status'] != 'success') {
                    return Exception('api-unknown_error');
                }

                if($mapping['is_selected'] == true){
                    $addData = [
                        'property_id' => $params['property_id'] ,
                        'room_rate_mapping_id' => $mapping['room_rate_mapping_id'] ,
                        'channel_id' => $mapping['channel_id'] ,
                        'has_date' => $hasDate ,
                        'start_date' => $startDate ,
                        'end_date' => $endDate ,
                        'status' => 1,
                        "created_by" => $validateData['created_by'],
                        "updated_by" =>$validateData['updated_by'],
                        'created_at' => Carbon::now()->timestamp,
                        'updated_at' => Carbon::now()->timestamp,
                    ];
                    $createStatus = $this->propertyRoomRateChannelMappingRepository->updateOrCreate($checkData, $addData );
                    if ($createStatus['status'] != 'success') {
                        throw new Exception('api-unknown_error');
                    }
                }else {

                    $softDeleteData = [
                        'status' => 0,
                        'has_date' => $hasDate ,
                        'start_date' => $startDate ,
                        'end_date' => $endDate ,
                        "updated_by" =>$validateData['updated_by'],
                        'updated_at' => Carbon::now()->timestamp,
                    ];

                    $deleteCriteria = ['criteria' => $checkData ];
                    $softDelete = $this->propertyRoomRateChannelMappingRepository->updateWhere($deleteCriteria, $softDeleteData );
                    if ($softDelete['status'] != 'success') {
                        throw new Exception('api-unknown_error');
                    }
                }


            }

            $response = [
                'status' => true,
                'data' => null,
            ];
            DB::commit();

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

        return output($response);
    }

    public function select($param = [], $column = ['*'])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $data = $this->propertyRoomRateChannelMappingRepository->findByCriteria($param, $column);
            $response['status'] = 1;
            $response['data'] = $data;

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

        return output($response);
    }

    public function selectChannelAvailabilityType($param = [], $column = ['*'])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $data = $this->propertyAvailabilityTypeRepository->findByCriteria($param, $column);
            $response['status'] = 1;
            $response['data'] = $data;

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

        return output($response);
    }


}
