<?php


namespace App\Core\Service\ChannelManager;


use App\Core\Mail\LogMail;
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 HotelRunner
{

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

    public function __construct(
        Client $restClient,
        Mailer $mailer,
        ChannelManagerPropertyMappingService $channelManagerPropertyMappingService,
        ChannelManagerMappingService $channelManagerMappingService
    )
    {
        $this->restClient = $restClient;
        $this->mailer = $mailer;
        //$this->reservationPushUrl = 'https://cm-staging.hotelrunner.com/api/push/reservation/28fb9e7b18903126e9d71a10ced00db0edec8710';
        $this->reservationPushUrl = 'https://cm.hotelrunner.com/api/push/reservation/da120fb30eae007e41034f5ab7824608ab8250de';


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

        $this->roomStatusTypeMapping = [
            1 => 'Confirm',
            0 => 'Cancel'
        ];

        $this->channelManagerId = 3;
        $this->channelManagerName = 'HotelRunner';
        $this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
        $this->channelManagerMappingService = $channelManagerMappingService;

    }

    public function requestPost($method, $xmlPayload)
    {
        $response = ['status' => false, 'message' => ''];

        try {
            $this->restClient = new Client(['http_errors' => false]);
            $res = $this->restClient->post($this->url . $method,
                [
                    'headers' => [
                        'Content-Type' => 'text/xml; charset=UTF8',
                        'Accept' => 'text/xml'
                    ],
                    'body' => $xmlPayload,
                ]
            );

            $getResponseBody = $res->getBody();
            $getResponse = $getResponseBody->getContents();
            $getResponseXml = new \SimpleXMLElement($getResponse, LIBXML_NOCDATA);
            $getResponse = json_decode(json_encode($getResponseXml), 1);

            $response = ["status" => true, 'message' => '', "data" => $getResponse];

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

        return $response;

    }

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

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

        $xmlResponse = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><reservation></reservation>');

        $xmlResponse->addChild('status', $type);
        $xmlResponse->addChild('code', $bookingDetail['booking_code']);
        $xmlResponse->addChild('time_zone', 'UTC');

        if (in_array($type, ['Modify', 'Cancel'])) {
            $xmlResponse->addChild('date', Carbon::createFromTimestamp($param['booking_detail']['updated_at'], 'UTC')->toDateTimeString());
        } else {
            $xmlResponse->addChild('date', Carbon::createFromTimestamp($param['booking_detail']['created_at'], 'UTC')->toDateTimeString());
        }

        //$xmlResponse->addChild('name', $bookingDetail['booking_contact']['nameSurname']);
        $xmlResponse->addChild('name', '<![CDATA[' . htmlentities($bookingDetail['booking_contact']['nameSurname']) . ']]>');
        $xmlResponse->addChild('mail', $bookingDetail['booking_contact']['email']);
        $xmlResponse->addChild('address');
        $xmlResponse->addChild('city');

        $firstRoom = reset($bookingDetail['booking_room']);
        $firstPax = reset($firstRoom['room_pax']);

        $xmlResponse->addChild('country', $firstPax['pax_country']['name']);
        $xmlResponse->addChild('telephone', $bookingDetail['booking_contact']['phoneFormatted']);

        $xmlResponse->addChild('property_id', $bookingDetail['property_id']);

        $totalAdultCount = 0;
        $totalChildrenCount = 0;
        $roomSearchOccupancy = json_decode($bookingDetail['rooms'], 1);
        foreach ($roomSearchOccupancy as $roomOccupancy) {
            $totalAdultCount += $roomOccupancy['adults'];
            $totalChildrenCount += $roomOccupancy['children'];
        }

        $xmlResponse->addChild('adult_count', $totalAdultCount);
        $xmlResponse->addChild('child_count', $totalChildrenCount);


        $xmlResponse->addChild('total_cost', $bookingDetail['total']);
        $xmlResponse->addChild('currency', $bookingDetail['currency_code']);

        if (!empty($bookingDetail['booking_contact']['note'])) {
            $xmlResponse->addChild('remark', '<![CDATA[' . htmlentities($bookingDetail['booking_contact']['note']) . ']]>');
        } else {
            $xmlResponse->addChild('remark', $bookingDetail['booking_contact']['note']);
        }


        $xmlResponse->addChild('arrival_date', $bookingDetail['checkin_date']);
        $xmlResponse->addChild('departure_date', $bookingDetail['checkout_date']);

        $xmlResponse->addChild('card');//Credit Card


        $rooms = $xmlResponse->addChild('rooms');

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

            $room = $rooms->addChild('room');

            $roomStatusType = isset($this->roomStatusTypeMapping[$roomDetail['status']]) ? $this->roomStatusTypeMapping[$roomDetail['status']] : 1;

            if (in_array($type, ['Modify']) && $roomDetail['status'] == 1) {
                $roomStatusType = $type;
            }

            if (in_array($type, ['Cancel'])) {
                $roomStatusType = $type;
            }

            $room->addChild('room_id', $roomDetail['room_id']);
            $room->addChild('rate_id', $roomDetail['room_rate_mapping_id']);
            $room->addChild('code', $roomDetail['room_id'] . ':' . $roomDetail['room_rate_mapping_id']);


            $isNonRefundable = false;
            $cancellationPolicy = json_decode($roomDetail['cancellation_policy'], 1);
            if (!empty($cancellationPolicy)) {
                if (isset($cancellationPolicy['isNonRefundable']) && $cancellationPolicy['isNonRefundable'] == 1) {
                    $isNonRefundable = true;
                }
            }

            if ($isNonRefundable) {
                $roomName = $roomDetail['room_name'] . ' - ' . $roomDetail['room_rate_name'].' - NonRefundable';
            } else {
                $roomName = $roomDetail['room_name'] . ' - ' . $roomDetail['room_rate_name'];
            }

            $room->addChild('name', '<![CDATA[' . htmlentities($roomName) . ']]>');

            $roomPaxCollect = collect($roomDetail['room_pax']);
            $room->addChild('adult_count', $roomPaxCollect->where('type', 'ADT')->count());
            $room->addChild('child_count', $roomPaxCollect->where('type', 'CHD')->count());

            $childAges = isset($roomSearchOccupancy[$roomKey]) && $roomSearchOccupancy[$roomKey]['children'] > 0 ? '[' . implode(',', $roomSearchOccupancy[$roomKey]['age']) . ']' : null;

            $room->addChild('child_ages', $childAges);


            $room->addChild('arrival_date', $roomDetail['checkin_date']);
            $room->addChild('departure_date', $roomDetail['checkout_date']);

            $room->addChild('total_cost', $roomDetail['total']);
            $room->addChild('status', $roomStatusType);


            $room->addChild('non_refundable', $isNonRefundable);


            $dailyPrices = $room->addChild('daily_prices');

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

            $currentDate = $roomDetail['checkin_date'];
            for ($i = 0; $i < $diffInDays; $i++) {
                $dailyPrice = $dailyPrices->addChild('daily_price');
                $dailyPrice->addChild('date', $currentDate);
                $dailyPrice->addChild('price', $baseRateDaily);

                $currentDate = Carbon::parse($currentDate)->addDay()->toDateString();
            }

        }

        //Log::debug($xmlResponse->asXML());

        //dd(html_entity_decode($xmlResponse->asXML()));

        return html_entity_decode($xmlResponse->asXML());

    }

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

        $propertyId = null;
        $xmlPayloadData = simplexml_load_string($xmlPayload);
        $xmlPayloadData = json_decode(json_encode($xmlPayloadData), 1);

        try {
            $this->restClient = new Client(['http_errors' => false]);
            $res = $this->restClient->post($this->reservationPushUrl . '/' . $xmlPayloadData['property_id'],
                [
                    'headers' => [
                        'Content-Type' => 'text/xml; charset=UTF8',
                        //'Authorization' => 'Basic dUV4dHJhbmV0V29yazpFeHRybnRXcmsyMSEqMjI=',
                        'Accept' => 'text/xml'
                    ],
                    'body' => $xmlPayload,
                ]
            );

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

            $getResponseXml = new \SimpleXMLElement($getResponseXmlBase, LIBXML_NOCDATA);
            $getResponse = json_decode(json_encode($getResponseXml), 1);

            //Log::debug($xmlPayload);
            //Log::debug($getResponse);

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

            $response = ['status' => true, 'message' => '', 'response' => $getResponseXmlBase];

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


        return $response;

    }


}
