<?php


namespace App\Http\Controllers\V1;

use App\Core\Repository\PropertyRoomRateChannelMapping\PropertyRoomRateChannelMappingRepository;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Service\PropertyQuickPricingService;
use App\Core\Service\PropertyRoomRateChannelMappingService;
use App\Core\Service\PropertyRoomRatePriceService;
use App\Exceptions\ApiErrorException;
use App\Export\PropertyCompetitorExport;
use App\Http\Controllers\Controller;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Log;
use Exception;
use Maatwebsite\Excel\Facades\Excel;

class PropertyQuickPricingController extends Controller
{

    private $params;
    private $propertyQuickPricingService;
    private $propertyRoomRateChannelMappingService;
    private $propertyChannelMappingService;
    private $propertyRoomRatePriceService;

    public function __construct(
        PropertyQuickPricingService $propertyQuickPricingService,
        PropertyRoomRateChannelMappingService $propertyRoomRateChannelMappingService,
        PropertyChannelMappingService $propertyChannelMappingService,
        PropertyRoomRatePriceService $propertyRoomRatePriceService
    )
    {
        $this->params = Input::all();
        $this->propertyQuickPricingService = $propertyQuickPricingService;
        $this->propertyRoomRateChannelMappingService = $propertyRoomRateChannelMappingService;
        $this->propertyChannelMappingService = $propertyChannelMappingService;
        $this->propertyRoomRatePriceService = $propertyRoomRatePriceService;
    }

    public function syncPropertyQuickPricing(Request $request)
    {

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

        try {

            //TODO Param validator

            $propertyRoomRateChannelIds = [];

            $channelRoomRateCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['params']['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['params']['channel_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ]
            ];


            $propertyRoomRateChannels = $this->propertyRoomRateChannelMappingService->select($channelRoomRateCriteria);

            if ($propertyRoomRateChannels['status'] != 'success') {
                throw new ApiErrorException($propertyRoomRateChannels['message']);
            }

            $propertyRoomRateChannelIds = pickItemFromArray('id', $propertyRoomRateChannels['data']);

            if (empty($propertyRoomRateChannelIds)) {
                throw new ApiErrorException('Not mapping room rate this channel.');
            }


            DB::beginTransaction();

            $quickPricingCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['params']['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['params']['channel_id']],
                ]
            ];

            $quickPricingResult = $this->propertyQuickPricingService->selectPropertyQuickPricingMapping($quickPricingCriteria);

            if ($quickPricingResult['status'] != 'success') {
                throw new ApiErrorException($quickPricingResult['message']);
            }

            if (!empty($quickPricingResult['data'])) {
                $deleteIds = pickItemFromArray('id', $quickPricingResult['data']);
                $deletePropertyQuickPricingMapping = $this->propertyQuickPricingService->deletePropertyQuickPricingMapping($deleteIds);
                if ($deletePropertyQuickPricingMapping['status'] != 'success') {
                    throw new ApiErrorException($deletePropertyQuickPricingMapping['message']);
                }
            }

            $roomRateChannelMappingIdCollect = collect($this->params['params']['room_rates'])->groupBy('room_rate_channel_mapping_id')->toArray();
            foreach ($roomRateChannelMappingIdCollect as $roomRateChannelMapping) {
                if (count($roomRateChannelMapping) > 1) {
                    throw new ApiErrorException('The same room rate channel id can not be processed.');
                }
            }


            $requestResultData = [];
            foreach ($this->params['params']['room_rates'] as $roomRate) {

                if (!in_array($roomRate['room_rate_channel_mapping_id'], $propertyRoomRateChannelIds)) {
                    continue;
                }

                $requestParam = [
                    'property_id' => $this->params['params']['property_id'],
                    'channel_id' => $this->params['params']['channel_id'],
                    'room_rate_channel_mapping_id' => $roomRate['room_rate_channel_mapping_id'],
                    'action_type' => fillOnUndefined($roomRate, 'action_type'),
                    'price_type' => fillOnUndefined($roomRate, 'price_type'),
                    'price_value' => fillOnUndefined($roomRate, 'price_value'),
                    'created_by' => $request->auth->id,
                    'updated_by' => $request->auth->id,
                ];


                $requestResult = $this->propertyQuickPricingService->createPropertyQuickPricingMapping($requestParam);

                if ($requestResult['status'] != 'success') {
                    throw new ApiErrorException($requestResult['message']);
                }

                $requestResultData[] = $requestResult['data'];

            }

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

        } 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;
        }

        if ($response['status']) {
            DB::commit();
        } else {
            DB::rollBack();
        }

        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);

    }

    public function getPropertyQuickPricing(Request $request)
    {

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

        try {

            $requestSelectCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['params']['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['params']['channel_id']],
                ],
                'with' => ['propertyRoomRateChannelMapping.propertyRoomRateMapping']
            ];

            $columns = ['id', 'property_id', 'channel_id', 'room_rate_channel_mapping_id', 'action_type', 'price_type', 'price_value'];
            $requestSelectResult = $this->propertyQuickPricingService->selectPropertyQuickPricingMapping($requestSelectCriteria, $columns);

            if ($requestSelectResult['status'] != 'success') {
                throw new ApiErrorException($requestSelectResult['message']);
            }

            $requestSelectResultData = [];
            foreach ($requestSelectResult['data'] as $key => $value) {
                $requestSelectResultData[$value['room_rate_channel_mapping_id']] = [
                    'property_id' => $value['property_id'],
                    'channel_id' => $value['channel_id'],
                    'room_id' => $value['property_room_rate_channel_mapping']['property_room_rate_mapping']['room_id'],
                    'room_rate_id' => $value['property_room_rate_channel_mapping']['property_room_rate_mapping']['room_rate_id'],
                    'room_rate_mapping_id' => $value['property_room_rate_channel_mapping']['room_rate_mapping_id'],
                    'room_rate_channel_mapping_id' => $value['room_rate_channel_mapping_id'],
                    'action_type' => $value['action_type'],
                    'price_type' => $value['price_type'],
                    'price_value' => $value['price_value'],
                ];

            }

            $channelRoomRateCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['params']['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['params']['channel_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => ['propertyRoomRateMapping.propertyRoom', 'propertyRoomRateMapping.propertyRoomRate']
            ];


            $propertyRoomRateChannels = $this->propertyRoomRateChannelMappingService->select($channelRoomRateCriteria);

            if ($propertyRoomRateChannels['status'] != 'success') {
                throw new ApiErrorException($propertyRoomRateChannels['message']);
            }

            $propertyRoomRateChannelQp = [];
            foreach ($propertyRoomRateChannels['data'] as $propertyRoomRateChannel) {

                //Best Available Rate Manipulate
                if($propertyRoomRateChannel['property_room_rate_mapping']['property_room_rate']['name'] == 'Best Available Rate') {
                    continue;
                }

                $roomId = $propertyRoomRateChannel['property_room_rate_mapping']['room_id'];

                //dd($propertyRoomRateChannel['property_room_rate_mapping']['property_room']['name']);

                $propertyRoomRateChannelQp['rooms'][$roomId]['name'] = $propertyRoomRateChannel['property_room_rate_mapping']['property_room']['name'];

                $propertyRoomRateChannelQp['rooms'][$roomId]['property_room_rate_mapping'][$propertyRoomRateChannel['room_rate_mapping_id']] = [
                    'name' => $propertyRoomRateChannel['property_room_rate_mapping']['property_room_rate']['name'],
                    'room_rate_channel_mapping_id' => $propertyRoomRateChannel['id'],
                    'action_type' => null,
                    'price_type' => null,
                    'price_value' => null
                ];

                if (isset($requestSelectResultData[$propertyRoomRateChannel['id']])) {
                    $propertyRoomRateChannelQp['rooms'][$roomId]['property_room_rate_mapping'][$propertyRoomRateChannel['room_rate_mapping_id']] = [
                        'name' => $propertyRoomRateChannel['property_room_rate_mapping']['property_room_rate']['name'],
                        'room_rate_channel_mapping_id' => $propertyRoomRateChannel['id'],
                        'action_type' => $requestSelectResultData[$propertyRoomRateChannel['id']]['action_type'],
                        'price_type' => $requestSelectResultData[$propertyRoomRateChannel['id']]['price_type'],
                        'price_value' => $requestSelectResultData[$propertyRoomRateChannel['id']]['price_value'],
                    ];
                }

            }


            //array_values
            foreach ($propertyRoomRateChannelQp['rooms'] as $roomId => $rooms) {
                $propertyRoomRateChannelQp['rooms'][$roomId]['property_room_rate_mapping'] = array_values($rooms['property_room_rate_mapping']);
            }

            $propertyRoomRateChannelQp['rooms'] = array_values($propertyRoomRateChannelQp['rooms']);

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

        } 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 propertyQuickPricingRate(Request $request)
    {

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

        try {

            //Burada kanal ve  proeprty ile kanal maping detaylatı çekilmeli property_channel_mapping tablosundan

            $propertyChannelMappingCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['params']['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['params']['channel_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'firstRow' => true
            ];


            $propertyChannelMapping = $this->propertyChannelMappingService->select($propertyChannelMappingCriteria);

            if ($propertyChannelMapping['status'] != 'success') {
                throw new ApiErrorException($propertyChannelMapping['message']);
            }

            $propertyChannelMapping = $propertyChannelMapping['data'];


            //CONNECTED CHANNEL RATE CHECK
            $propertyChannelConnectedList = [];
            $propertyChannelConnectedCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['params']['property_id']],
                    ['field' => 'connected_channel_id', 'condition' => '=', 'value' => $this->params['params']['channel_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ]
            ];

            $propertyChannelConnected = $this->propertyChannelMappingService->select($propertyChannelConnectedCriteria);
            if ($propertyChannelConnected['status'] == 'success') {
                $propertyChannelConnectedList = $propertyChannelConnected['data'];

            }
            //CONNECTED CHANNEL RATE CHECK

            /*

              "property_id" => 1
              "channel_id" => 1
              "currency_code" => "EUR"
              "property_booking_type_id" => 1
              "property_availability_type_id" => 1

             * */

            //Property ve Kanala ait mapping yapılan room rate ler
            $propertyRoomRateChannelIds = [];
            $channelRoomRateCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['params']['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['params']['channel_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ]
            ];


            $propertyRoomRateChannels = $this->propertyRoomRateChannelMappingService->select($channelRoomRateCriteria);

            if ($propertyRoomRateChannels['status'] != 'success') {
                throw new ApiErrorException($propertyRoomRateChannels['message']);
            }

            $propertyRoomRateChannelIds = pickItemFromArray('id', $propertyRoomRateChannels['data']);

            if (empty($propertyRoomRateChannelIds)) {
                throw new ApiErrorException('Not mapping room rate this channel.');
            }

            $propertyQuickPricingMapping = [];
            $requestSelectCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['params']['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['params']['channel_id']],
                ],
                'with' => ['propertyRoomRateChannelMapping.propertyRoomRateMapping', 'propertyRoomRateChannelMapping.propertyRoomRateMapping']
            ];

            $columns = ['id', 'property_id', 'channel_id', 'room_rate_channel_mapping_id', 'action_type', 'price_type', 'price_value'];
            $requestSelectResult = $this->propertyQuickPricingService->selectPropertyQuickPricingMapping($requestSelectCriteria, $columns);

            if ($requestSelectResult['status'] != 'success') {
                throw new ApiErrorException($requestSelectResult['message']);
            }

            $propertyQuickPricingMapping = $requestSelectResult['data'];

            DB::beginTransaction();

            foreach ($propertyQuickPricingMapping as $quickPricing) {

                //Eğer kanalda kapalı bir room rate var ise onun fiyatı güncellenmez
                if (!in_array($quickPricing['room_rate_channel_mapping_id'], $propertyRoomRateChannelIds)) {
                    continue;
                }

                //dd($quickPricing,$propertyChannelMapping,$this->params);


                $requestParams = [
                    'property_id' => $quickPricing['property_id'],
                    'channel_id' => $quickPricing['channel_id'],
                    'user_id' => $request->auth->id,
                    'availability' => []
                ];

                $requestParams['rates'] = [];

                foreach ($this->params['params']['data'] as $date => $amount) {


                    $dateForSql = substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2);

                    if (!Carbon::parse($dateForSql)) {
                        throw new ApiErrorException('Invalid date format.');
                    }

                    if (Carbon::parse($dateForSql)->isBefore(Carbon::now()->toDateString())) {
                        throw new ApiErrorException('Date to be updated cannot be earlier than today');
                    }

                    $dateKeyParam = [];
                    $dateKeyParam[] = $propertyChannelMapping['property_availability_type_id'];
                    $dateKeyParam[] = $quickPricing['property_room_rate_channel_mapping']['property_room_rate_mapping']['room_id'];
                    $dateKeyParam[] = $quickPricing['property_room_rate_channel_mapping']['room_rate_mapping_id'];
                    $dateKeyParam[] = $dateForSql;
                    $dateKey = implode('|', $dateKeyParam);


                    $amountCalculated = $amount;

                    $amountAffected = 0;
                    if ($quickPricing['price_type'] == 'PER') {
                        $amountAffected = ($amount * $quickPricing['price_value']) / 100;
                    } elseif ($quickPricing['price_type'] == 'FIX') {
                        $amountAffected = $quickPricing['price_value'];
                    }

                    if ($quickPricing['action_type'] == 'INC') {
                        $amountCalculated = $amountCalculated + $amountAffected;
                    }

                    if ($quickPricing['action_type'] == 'DEC') {
                        $amountCalculated = $amountCalculated - $amountAffected;
                    }

                    if ($amountCalculated <= 0) {
                        throw new ApiErrorException('Calculated amount cannot be 0 or less.');
                    }


                    $requestParams['rates'][$dateKey] = [
                        "setup_type_id" => $propertyChannelMapping['property_availability_type_id'],
                        "room_id" => $quickPricing['property_room_rate_channel_mapping']['property_room_rate_mapping']['room_id'],
                        "room_rate_mapping_id" => $quickPricing['property_room_rate_channel_mapping']['room_rate_mapping_id'],
                        "date" => $dateForSql,
                        "amount" => $amountCalculated
                    ];

                }

                $requestParams['quickPricing'] = true;

                $roomRateUpdate = $this->propertyRoomRatePriceService->roomRateUpdate($requestParams);

                if ($roomRateUpdate['status'] != 'success') {
                    throw new ApiErrorException($roomRateUpdate['message']);
                }


                //CONNECTED CHANNEL RATE UPDATE
                foreach ($propertyChannelConnectedList as $propertyChannelConnected) {
                    $requestParams['channel_id'] = $propertyChannelConnected['channel_id'];
                    $roomRateUpdate = $this->propertyRoomRatePriceService->roomRateUpdate($requestParams);
                    if ($roomRateUpdate['status'] != 'success') {
                        throw new ApiErrorException($roomRateUpdate['message']);
                    }
                }
                //CONNECTED CHANNEL RATE UPDATE


            }


            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, '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;
        }

        if ($response['status']) {
            DB::commit();
        } else {
            DB::rollBack();
        }

        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);

    }


}

