<?php


namespace App\Core\Service\ChannelManager;


use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManagerBookingService;
use App\Core\Service\ChannelManagerMappingService;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use Exception;


class SistemOtel
{

    private $statusMapping;
    private $paymentTypeMapping;
    private $channelManagerId;
    private $channelManagerName;
    private $mailer;

    public function __construct(
        Client $restClient,
        Mailer $mailer,
        ChannelManagerPropertyMappingService $channelManagerPropertyMappingService,
        ChannelManagerMappingService $channelManagerMappingService,
        ChannelManagerBookingService $channelManagerBookingService
    )
    {
        $this->restClient = $restClient;
        $this->mailer = $mailer;
        $this->reservationPushUrl = 'https://cm.istbooking.com/push/extranetwork';


        $this->typeMapping = [
            'Booking' => 'Book',
            'Modify' => 'Modify',
            'Cancel' => 'Cancel'
        ];

        $this->channelManagerId = 6;
        $this->channelManagerName = 'SistemOtel';
        $this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
        $this->channelManagerMappingService = $channelManagerMappingService;
        $this->channelManagerBookingService = $channelManagerBookingService;

    }

    public function requestPostReservationPushParam($propertyId, $bookingId, $type, $param = [])
    {

        $type = $this->typeMapping[$type];
        $bookingDetail = $param['booking_detail'];


        $jsonResponse = [];
        $jsonResponse['hotel_id'] = $propertyId;


        $jsonResponse['reservation']['code'] = $bookingDetail['booking_code'];
        $jsonResponse['reservation']['status'] = $type;

        $jsonResponse['reservation']['time'] = Carbon::createFromTimestamp($param['booking_detail']['created_at'])->toDateTimeString();

        $jsonResponse['reservation']['checkin_date'] = $bookingDetail['checkin_date'];
        $jsonResponse['reservation']['checkout_date'] = $bookingDetail['checkout_date'];
        $jsonResponse['reservation']['currency'] = $bookingDetail['currency_code'];
        $jsonResponse['reservation']['total'] = $bookingDetail['total'];


        $jsonResponse['reservation']['contact'] = [
            'name' => $bookingDetail['booking_contact']['name'],
            'surname' => $bookingDetail['booking_contact']['surname'],
            'email' => $bookingDetail['booking_contact']['email'],
            'phone' => $bookingDetail['booking_contact']['phoneFormatted'],
            'note' => $bookingDetail['booking_contact']['note'],
        ];


        $jsonResponse['reservation']['rooms'] = [];


        $roomKey = 0;
        $additionalNoteText = [];
        foreach ($bookingDetail['booking_room'] as $roomKey => $roomDetail) {

            if ($roomDetail['status'] != 1) {
                continue;
            }

            $occupancy = occupancyCodeParser($roomDetail['occupancy_code']);

            $diffInDays = Carbon::parse($roomDetail['checkin_date'])->diffInDays(Carbon::parse($roomDetail['checkout_date']));
            $baseRateDaily = moneyDoubleFormatDecimal($roomDetail['total'] / $diffInDays);

            $dailyPrices = [];
            $currentDate = $roomDetail['checkin_date'];
            for ($i = 0; $i < $diffInDays; $i++) {
                $dailyPrices[] = [
                    'date' => $currentDate,
                    'amount' => $baseRateDaily
                ];
                $currentDate = Carbon::parse($currentDate)->addDay()->toDateString();
            }

            $roomPax = [];
            foreach ($roomDetail['room_pax'] as $pax) {
                $roomPax[] = [
                    'type' => $pax['type'],
                    'name' => $pax['name'],
                    'surname' => $pax['surname'],
                    'gender' => $pax['gender'],
                    'citizen' => $pax['citizen'],
                    'birth_date' => $pax['birth_date'],
                ];
            }

            $cancellationPolicy = [];
            $cancellationPolicyRoom = json_decode($roomDetail['cancellation_policy'], 1);
            if ($cancellationPolicyRoom) {
                $cancellationPolicy = [
                    'is_nonrefundable' => fillOnUndefined($cancellationPolicyRoom, 'isNonRefundable') == 1 ? true : false,
                    'is_freecancellation' => fillOnUndefined($cancellationPolicyRoom, 'isFreeCancellation') == 1 ? true : false,
                    'before_arrival_day' => fillOnUndefined($cancellationPolicyRoom, 'isFreeCancellation') == 1 ? fillOnUndefined($cancellationPolicyRoom, 'beforeArrivalDay') : null,
                    'type' => fillOnUndefined($cancellationPolicyRoom, 'type') == 1 ? fillOnUndefined($cancellationPolicyRoom, 'type') : null,
                    'value' => fillOnUndefined($cancellationPolicyRoom, 'value') == 1 ? fillOnUndefined($cancellationPolicyRoom, 'value') : null,
                    'text' => null,
                ];

                $cancellationPolicyTextFormatted = cancellationPolicyTextFormatted(
                    fillOnUndefined($cancellationPolicyRoom, 'isNonRefundable'),
                    fillOnUndefined($cancellationPolicyRoom, 'isFreeCancellation'),
                    fillOnUndefined($cancellationPolicyRoom, 'beforeArrivalDay'),
                    fillOnUndefined($cancellationPolicyRoom, 'type'),
                    fillOnUndefined($cancellationPolicyRoom, 'value'),
                    $bookingDetail['currency_code'],
                    'en'
                );

                if($cancellationPolicyTextFormatted) {
                    $cancellationPolicy['text'] = $cancellationPolicyTextFormatted;
                }
            }

            $jsonResponse['reservation']['rooms'][$roomKey] = [
                'id' => $roomDetail['id'],
                'room_id' => $roomDetail['room_id'],
                'room_name' => $roomDetail['room_name'],
                'rate_id' => $roomDetail['room_rate_mapping_id'],
                'rate_name' => $roomDetail['room_rate_name'],
                'cancellation_policy' => $cancellationPolicy,
                'occupancy' => [
                    'adults' => $occupancy['ADT'],
                    'children' => $occupancy['CHD'],
                    'age' => $occupancy['AGE'],
                ],
                'daily' => $dailyPrices,
                'pax' => $roomPax,

            ];

            if(isset($jsonResponse['reservation']['rooms'][$roomKey]['cancellation_policy']['text'])) {
                $additionalNoteText[] = ($roomKey + 1).'. '.$jsonResponse['reservation']['rooms'][$roomKey]['room_name'].' - '.$jsonResponse['reservation']['rooms'][$roomKey]['rate_name']. ' ('.$jsonResponse['reservation']['rooms'][$roomKey]['cancellation_policy']['text'].')';
            }

        }

        $additionalNoteText[] = 'Payment: '.$bookingDetail['booking_payment_type']['code'].' - '.$bookingDetail['booking_payment_type']['name'];

        $jsonResponse['reservation']['contact']['note'].=implode(', ',$additionalNoteText);

        $jsonResponse['reservation']['channel'] = [
            'id' => $bookingDetail['booking_channel']['id'],
            'name' => $bookingDetail['booking_channel']['id'] == 1 ? 'Extranetwork' : $bookingDetail['booking_channel']['name'],
        ];

        $jsonResponse['reservation']['payment'] = [
            'code' => $bookingDetail['booking_payment_type']['code'],
            'name' => $bookingDetail['booking_payment_type']['name'],
        ];

        return json_encode($jsonResponse);

    }

    public function requestPostReservationPush($jsonPayload)
    {
        $response = ['status' => false, 'message' => ''];


        try {
            $this->restClient = new Client(['http_errors' => false]);
            $res = $this->restClient->post($this->reservationPushUrl,
                [
                    'headers' => [
                        'Content-Type' => 'application/json'
                    ],
                    'body' => $jsonPayload,
                ]
            );

            $getResponseBody = $res->getBody();
            $getResponseJsonBase = $getResponseBody->getContents();

            $getResponse = json_decode($getResponseJsonBase, 1);

            if (!$getResponse['status']) {
                if($getResponse['message'] == 'HOTEL_TANIMLI_DEGIL') {

                    $jsonPayloadArray = json_decode($jsonPayload,1);
                    $bookingCriteria = [
                        'criteria' =>
                            [
                                ['field' => 'channel_manager_id', 'condition' => '=', 'value' => $this->channelManagerId],
                                ['field' => 'type', 'condition' => '=', 'value' => array_search($jsonPayloadArray['reservation']['status'], $this->typeMapping)],
                                ['field' => 'request', 'condition' => 'LIKE', 'value' => '%'.$jsonPayloadArray['reservation']['code'].'%'],
                            ],
                        'firstRow' => true
                    ];

                    $channelManagerBookingDetail = $this->channelManagerBookingService->select($bookingCriteria);
                    if($channelManagerBookingDetail['status'] == 'success' && !empty($channelManagerBookingDetail['status'])) {
                        $channelManagerBookingDetail = $channelManagerBookingDetail['data'];
                        $this->channelManagerBookingService->update($channelManagerBookingDetail['id'], ['status' => 2]);
                    }

                }
                throw new ApiErrorException($getResponse['message']);
            }

            $response = ['status' => true, 'message' => '', 'response' => json_encode($getResponse)];

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


        return $response;

    }


}
