<?php

namespace App\Core\Service;

use App\Core\Repository\Booking\BookingRepository;
use App\Core\Repository\UserPropertyMapping\UserPropertyMappingRepository;
use App\Core\Service\PropertyBrandService;
use Carbon\Carbon;
use Illuminate\Mail\Mailer;
use App\Core\Mail\NewBookingMail;


use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Exception;


class NewBookingMailService
{
    private $bookingRepository;
    private $userPropertyMappingRepository;
    private $mailer;
    private $propertyBrandService;


    public function __construct(
        Mailer $mailer,
        BookingRepository $bookingRepository,
        UserPropertyMappingRepository $userPropertyMappingRepository,
        PropertyBrandService $propertyBrandService
    )
    {
        $this->mailer = $mailer;
        $this->bookingRepository = $bookingRepository;
        $this->userPropertyMappingRepository = $userPropertyMappingRepository;
        $this->propertyBrandService = $propertyBrandService;

    }

    public function process($params = [])
    {
        try {
            $bookingDetailParam = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['booking_id']]
                ],
                'with' => [
                    'bookingPayment', 'bookingRoom.roomRateMapping.propertyRoom', 'bookingRoom.roomRateMapping.propertyRoomRate',
                    'bookingContact', 'bookingProperty.propertyBrand', 'bookingProperty.propertyExecutive',
                    'bookingPropertyWeb', 'propertyBookingEngine', 'propertyBookingChannel', 'bookingAddon.propertyChannelAddon.propertyAddon.fact',
                    'propertyChannelMapping.channelBookingPaymentType'
                ],
                'firstRow' => true
            ];

            $bookingData = $this->bookingRepository->findByCriteria($bookingDetailParam);
            if (!$bookingData) {
                throw new Exception('api-unknown_error');
            }

            $reservationExecutives = [];
            if (isset($bookingData['booking_property']['property_executive'])) {
                $reservationExecutives = collect($bookingData['booking_property']['property_executive'])
                    ->where('executive_type_id', '=', '7') // sadece rezervasyon yetkisi olanlar ...
                    ->values()->all();
            }

            $userPropertyMappingParam = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $bookingData['property_id']]
                ],
                'with' => ['user']
            ];
            $userData = $this->userPropertyMappingRepository->findByCriteria($userPropertyMappingParam);

            $bcc = [];
            foreach ($userData as $user) {
                if (!empty($user['user'])) {
                    $bcc[] = $user['user']['email'];
                }
            }


            foreach ($reservationExecutives as $reservationExecutive) {
                $bcc[] = $reservationExecutive['email'];
            }

            if (in_array($bookingData['property_booking_channel']['channel_category_id'], [3])) {
                $bcc[] = "sales@extranetwork.com";
            } else {
                $bcc[] = "channel@extranetwork.com";
            }


            //ENW kanalı harici tüm işlemlerde giden kısmı otel kullanıcısı olacak.
            if (in_array($bookingData['property_booking_channel']['channel_category_id'], [4, 7])) {
                $firstUserData = reset($userData);
                $mailData['to'] = [
                    'name' => $bookingData['booking_property']['name'],
                    'email' => $firstUserData['user']['email']
                ];
            } else {
                $mailData['to'] = [
                    'name' => $bookingData['booking_contact']['nameSurname'],
                    'email' => $bookingData['booking_contact']['email']
                ];
            }

            $mailData['bcc'] = $bcc;

            $hostAddress = Config::get('app.bookingEngineUrl') . '/' . $bookingData['property_booking_engine']['token'] . '/' . $bookingData['booking_contact']['language_code'] . '/booking-detail/' . $bookingData['booking_code'];

            $brandRequestData = ['property_id' => $bookingData['property_id']];
            $getPropertyBrand = $this->propertyBrandService->getPropertyBrand($brandRequestData);
            if ($getPropertyBrand['status'] != "success") {
                throw new Exception($getPropertyBrand['message']);
            }

            $propertyBrand = $getPropertyBrand['data'];
            $propertyBrandLogo = isset($propertyBrand['name'])
                ? Config::get('app.fileSystemDriver') . '/property-photos/' . $propertyBrand['property_id'] . "/logo/" . $propertyBrand['name'] . '_250x250.' . $propertyBrand['logo_file_ext']
                : null;

            $roomOrder = 1;
            $bookingChannelRoom = [];
            foreach ($bookingData['booking_room'] as $bookingRoom) {

                if (!empty($bookingRoom['room_rate_mapping']['property_room'])) {
                    $bookingRoom['room_name'] = $bookingRoom['room_rate_mapping']['property_room']['name'];
                }
                if (!empty($bookingRoom['room_rate_mapping']['property_room_rate'])) {
                    $bookingRoom['room_rate_name'] = $bookingRoom['room_rate_mapping']['property_room_rate']['name'];
                }

                $extraParam = null;
                if (!empty($bookingRoom['extra_param'])) {
                    $extraParamDecode = json_decode($bookingRoom['extra_param'], 1);

                    foreach ($extraParamDecode as $extraParamKey => $extraParamValue) {

                        $extraParamTitle = explode('_', $extraParamKey);
                        foreach ($extraParamTitle as $extraParamTitleKey => $extraParamTitleValue) {
                            $extraParamTitle[$extraParamTitleKey] = ucwords($extraParamTitleValue);
                        }
                        $extraParamTitle = implode(' ', $extraParamTitle);

                        $extraParam[$extraParamKey] = [
                            'title' => $extraParamTitle,
                            'value' => $extraParamValue,
                        ];
                    }

                }

                $additionalFee = null;
                if (!empty($bookingRoom['rate_detail'])) {
                    $rateDetail = json_decode($bookingRoom['rate_detail'], 1);
                    if (isset($rateDetail['taxes']) && $bookingData['channel_manager_id'] == 2) {
                        $additionalFee = $rateDetail['taxes'];
                    }
                }

                //$cancellationPolicy
                $cancellationPolicy = null;
                $cancellationPolicyRoom = json_decode($bookingRoom['cancellation_policy'], 1);
                if ($cancellationPolicyRoom) {
                    $cancellationPolicyTextFormatted = cancellationPolicyTextFormatted(
                        fillOnUndefined($cancellationPolicyRoom, 'isNonRefundable'),
                        fillOnUndefined($cancellationPolicyRoom, 'isFreeCancellation'),
                        fillOnUndefined($cancellationPolicyRoom, 'beforeArrivalDay'),
                        fillOnUndefined($cancellationPolicyRoom, 'type'),
                        fillOnUndefined($cancellationPolicyRoom, 'value'),
                        $bookingData['currency_code'],
                        $bookingData['booking_contact']['language_code']
                    );

                    if ($cancellationPolicyTextFormatted) {
                        $cancellationPolicy = $cancellationPolicyTextFormatted;
                    }
                }
                //$cancellationPolicy

                $bookingChannelRoom[] = [
                    'roomOrder' => $roomOrder,
                    'roomName' => $bookingRoom['room_name'],
                    'roomRateName' => $bookingRoom['room_rate_name'],
                    'occupancyCode' => $bookingRoom['occupancy_code'],
                    'occupancyText' => occupancyCodeFormatted($bookingRoom['occupancy_code']),
                    'amount' => $bookingRoom['amount'],
                    'discount_amount' => $bookingRoom['discount_amount'],
                    'total' => $bookingRoom['total'],
                    'currencyCode' => $bookingRoom['currency_code'],
                    'dailyAmount' => !empty($bookingRoom['daily_amount']) ? json_decode($bookingRoom['daily_amount'], 1) : null,
                    'extraParam' => $extraParam,
                    'occupancyFormatted' => occupancyCodeFormatted($bookingRoom['occupancy_code']),
                    'additionalFee' => $additionalFee,
                    'cancellationPolicy' => $cancellationPolicy
                ];

                //dd($bookingChannelRoom);

                //$bookingChannelRoom[] = $roomOrder . '. ' . $bookingRoom['room_name'] . ' - ' . $bookingRoom['room_rate_name'] . ' - ' . occupancyCodeFormatted($bookingRoom['occupancy_code']);
                $roomOrder++;
            }

            //$bookingChannelRoom = implode('<br /> ', $bookingChannelRoom);

            $bookingLanguageCode = isset($bookingData['booking_contact']['language_code']) ? $bookingData['booking_contact']['language_code'] : 'en';
            $bookingChannelPaymentType = __('property_booking_payment_type-pay_at_hotel', [], $bookingLanguageCode);
            $bookingChannelPaymentSource = null;
            if ($bookingData['booking_payment']['payment_type_code'] == 'CRD') {
                $bookingChannelPaymentType = __('property_booking_payment_type-credit_card', [], $bookingLanguageCode);
                if ($bookingData['booking_payment']['payment_source_code'] == 'OTA') {
                    $bookingChannelPaymentSource = __('enw-ota-credit_card', [], $bookingLanguageCode);
                }
                if ($bookingData['booking_payment']['payment_source_code'] == 'GST') {
                    $bookingChannelPaymentSource = __('enw-guest-credit_card', [], $bookingLanguageCode);
                }
            }

            $creditCardInformation = null;
            if (!is_null($bookingData['booking_payment']['extra_param'])) {
                $paymentData = json_decode($bookingData['booking_payment']['extra_param'], 1);

                if (isset($paymentData['attributes']['guarantee'])) {
                    $creditCardInformation['cardNumber'] = isset($paymentData['attributes']['guarantee']['card_number']) ? $paymentData['attributes']['guarantee']['card_number'] : null;
                    $creditCardInformation['cardHolderName'] = isset($paymentData['attributes']['guarantee']['cardholder_name']) ? $paymentData['attributes']['guarantee']['cardholder_name'] : null;
                    $creditCardInformation['expirationDate'] = isset($paymentData['attributes']['guarantee']['expiration_date']) ? $paymentData['attributes']['guarantee']['expiration_date'] : null;
                    $creditCardInformation['cvv'] = isset($paymentData['attributes']['guarantee']['cvv']) ? $paymentData['attributes']['guarantee']['cvv'] : null;
                }
            }

            //Genius Member
            $bookingContactExtraParam = null;
            if (!empty($bookingData['booking_contact']['extra_param'])) {
                $bookingContactExtraParam = json_decode($bookingData['booking_contact']['extra_param'], 1);
            }
            $isBookingGenius = false;
            if (isset($bookingContactExtraParam['is_genius']) && $bookingContactExtraParam['is_genius']) {
                $isBookingGenius = true;
            }


            //BOOKING ADDON
            $bookingAddonList = [];
            $bookingAddons = $bookingData['booking_addon'];
            foreach ($bookingAddons as $bookingAddon) {

                $bookingAddonAttributeList = [];
                $isHasAttribute = false;
                $attributeArray = [];

                if (!empty($bookingAddon['property_channel_addon']['property_addon']['attributeArray'])) {
                    $isHasAttribute = true;
                    $attributeArray = $bookingAddon['property_channel_addon']['property_addon']['attributeArray'];
                    $bookingAddonAttributes = json_decode($bookingAddon['attribute'], 1);
                    if (!is_null($bookingAddonAttributes)) {
                        foreach ($bookingAddonAttributes as $key => $bookingAddonAttribute) {
                            foreach ($bookingAddonAttribute as $bookingAddonAttributeKey => $bookingAddonAttributeValue) {

                                if (isset($bookingAddon['property_channel_addon']['property_addon']['attributeArray'][$bookingAddonAttributeKey])) {
                                    $bookingAddonAttributeList[] = [
                                        'key' => $bookingAddonAttributeKey,
                                        'name' => $bookingAddon['property_channel_addon']['property_addon']['attributeArray'][$bookingAddonAttributeKey]['name'],
                                        'language_key' => $bookingAddon['property_channel_addon']['property_addon']['attributeArray'][$bookingAddonAttributeKey]['language_key'],
                                        'value' => $bookingAddonAttributeValue,
                                    ];
                                }

                            }
                        }
                    }
                }

                $bookingAddonList[] = [
                    'id' => $bookingAddon['id'],
                    'booking_id' => $bookingAddon['booking_id'],
                    'property_channel_addon_id' => $bookingAddon['property_channel_addon_id'],
                    'count' => $bookingAddon['count'],
                    'amount' => $bookingAddon['amount'],
                    'total' => $bookingAddon['total'],
                    'currency_code' => $bookingAddon['currency_code'],
                    'name' => $bookingAddon['property_channel_addon']['property_addon']['fact']['name'],
                    'title' => $bookingAddon['property_channel_addon']['title'],
                    'language_key' => $bookingAddon['property_channel_addon']['property_addon']['fact']['language_key'],
                    'icon' => $bookingAddon['property_channel_addon']['property_addon']['fact']['icon'],
                    'isHasAttribute' => $isHasAttribute,
                    'attributeArray' => $attributeArray,
                    'attribute' => $bookingAddonAttributeList
                ];

            }

            $payAtHotelCreditCardCheck = false;
            if(isset($bookingData['property_channel_mapping']) && !empty($bookingData['property_channel_mapping'])) {
                $payAtHotelCreditCardCheck = collect($bookingData['property_channel_mapping']['channel_booking_payment_type'])->where('payment_type_id',2)->where('is_get_payment_data',1)->isNotEmpty();
            }

            $mailViewParams = [
                'bookingId' => $bookingData['id'],
                'bookingCode' => $bookingData['booking_code'],
                'propertyId' => $bookingData['booking_property']['id'],
                'booking_code' => $bookingData['booking_code'],
                'search_key' => $bookingData['search_key'],
                'channel_token' => $bookingData['channel_token'],
                'booking_engine_token' => $bookingData['booking_engine_token'],
                'checkin_date' => Carbon::parse($bookingData['checkin_date'])->format('d.m.Y'),
                'checkout_date' => Carbon::parse($bookingData['checkout_date'])->format('d.m.Y'),
                'payment_type_code' => $bookingData['booking_payment']['payment_type_code'],
                'payment_source_code' => $bookingData['booking_payment']['payment_source_code'],
                'room_amount' => $bookingData['room_amount'],
                'addon_amount' => $bookingData['addon_amount'],
                'discount_amount' => $bookingData['discount_amount'],
                'total' => $bookingData['total'],
                'currency_code' => $bookingData['currency_code'],
                'name_surname' => $bookingData['booking_contact']['nameSurname'],
                'countryCode' => upperCase($bookingData['booking_contact']['country_code']),
                'email' => $bookingData['booking_contact']['email'],
                'property_name' => $bookingData['booking_property']['name'],
                'url' => $hostAddress,
                'logo' => $bookingData['booking_property']['property_brand']['logoUrl'],
                'language_code' => $bookingData['booking_contact']['language_code'],
                'bookingChannelId' => $bookingData['channel_id'],
                'bookingChannelName' => fillOnUndefined($bookingData['property_booking_channel'], 'name'),
                'bookingChannelCategoryId' => $bookingData['property_booking_channel']['channel_category_id'],
                'bookingChannelCode' => $bookingData['channel_booking_code'],
                'bookingChannelContactNameSurname' => $bookingData['booking_contact']['nameSurname'],
                'bookingChannelContactEmail' => $bookingData['booking_contact']['email'],
                'bookingChannelContactPhone' => $bookingData['booking_contact']['phone_number'],
                'bookingChannelNote' => $bookingData['booking_contact']['note'],
                'bookingChannelRoom' => $bookingChannelRoom,
                'bookingAddon' => $bookingAddonList,
                'bookingChannelPaymentType' => $bookingChannelPaymentType,
                'bookingChannelPaymentSource' => $bookingChannelPaymentSource,
                'creditCardInformation' => $creditCardInformation,
                'payAtHotelCreditCardCheck' => $payAtHotelCreditCardCheck,
                'isBookingGenius' => $isBookingGenius,
                'web' => isset($bookingData['booking_property_web']['webProtocolUrl']) ? $bookingData['booking_property_web']['webProtocolUrl'] : null
            ];

            $mailViewParams['showCreditCardUrl'] = null;
            if (!empty($mailViewParams['creditCardInformation'])) {
                $mailViewParams['showCreditCardUrl'] = Config::get('app.client_server') . '/app/network/reservation/' . $mailViewParams['bookingId'] . '?propertyid=' . $mailViewParams['propertyId'];
            }

            $mailParams = [
                'mailData' => $mailData,
                'mailViewParams' => $mailViewParams

            ];

            $this->mailer->onQueue('newBookingMail', new NewBookingMail($mailParams));


        } catch
        (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            return output(['status' => -1, 'message' => $e->getMessage()]);
        }
    }

}
