<?php


namespace App\Http\Controllers\V1;

use App\Console\Commands\CurrencyRates\CurrencyRatesService;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Core\Service\CompetitorPriceAnalysisService;
use App\Core\Service\CurrencyService;
use App\Core\Service\PropertyChannelCouponService;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Service\PropertyPromotionService;
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 CompetitorPriceAnalysisController extends Controller
{

    private $params;
    private $tripAdvisorCookie;
    private $competitorPriceAnalysisService;
    private $maxCompetitorPropertyAdd;

    public function __construct(
        CompetitorPriceAnalysisService $competitorPriceAnalysisService,
        CurrencyService $currencyService,
        PropertyChannelMappingService $propertyChannelMappingService,
        PropertyRoomRatePriceService $propertyRoomRatePriceService,
        PropertyChannelCouponService $propertyChannelCouponService,
        PropertyPromotionService $propertyPromotionService,
        ChannelManagerPropertyMappingService $channelManagerPropertyMappingService
    )
    {

        //$this->tripAdvisorCookie = 'TADCID=X6AlsdAQPb0JGrWnABQCFdpBzzOuRA-9xvCxaMyI12kGsGqfJg45fcvAP84z1sQ0l6BdP8fUu-L4qe5Zh7uINoyb1usbZKS8xpY; ak_bmsc=1D49AF2E3BEE0E197E48F537CB620AA3~000000000000000000000000000000~YAAQTLOvw+g4QVN8AQAARPc0rQ3fR0x3SZUbtbLJX5hS76gF80zdg9dmKzmyonlGUQ5dyEnGt6odg1kTQUj74Xg3FeuvUX3RZZ0Oqg/HiEAMSuEbC9QgS6fugmOZLJDsJ0Vyt29BuAOYMPf/OX7lt7pCPCgfb6iQClwqh1L5ZfsjPwLrd8B9KjIKMY9hjOdpjTacei9gZoM7eR0Q3Xe2r5BoIoV4CDpM8kde/BD6rKcZbRjfNAc0KTUpHUawTS3unZ9y145u8H/99xxZCbjqrUW25g+x+hpBdI7IBr6FTXw5sljsl5V7iwfNob0NGTJF4y/37RA5KBqGatwkeMp/qdMUPBK76TyDx0q6hIwBiVxTm3y0Hq999VUmrl7Kg2IEvrACcDQNM4gKo+zjxnse+g==';
        //$this->tripAdvisorCookie = 'TNI1625!AC8GutJQ28ZxO8jorf9FRDmeZ1UQdBgLItfITy8i77flGfQpI+UIoZd+cEfErXSR8VMnvDTKEW1MdkNx2GdRoJdWitJp5OC+ZjGozmfw/z8AfgvQ/IPIym57VSEZN06vcVmQulCtCPaM/q+OdmNYoEc7A3kcekslH9yl2sBLchIS';
        $this->tripAdvisorCookie = '4c4b806c8afc9ae6f0d9f62e0951c53c17d4d7964446a664f74de11087849ec3';

        $this->restClient = new Client([
                'max' => 5,
                'strict' => false,
                'referer' => false,
                'protocols' => ['https'],
                'track_redirects' => false,
                'allow_redirects' => false,
                'timeout' => 5
            ]
        );

        $this->params = Input::all();
        $this->currencyService = $currencyService;
        $this->competitorPriceAnalysisService = $competitorPriceAnalysisService;
        $this->propertyChannelMappingService = $propertyChannelMappingService;
        $this->propertyRoomRatePriceService = $propertyRoomRatePriceService;
        $this->propertyChannelCouponService = $propertyChannelCouponService;
        $this->propertyPromotionService = $propertyPromotionService;
        $this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
        $this->maxCompetitorPropertyAdd = 5;
    }

    public function property(Request $request)
    {

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

        try {

            $this->restClientFroTripadvisr = new Client([
                    'max' => 5,
                    'verify' => false,
                    'http_errors' => false
                ]
            );

            $query[] = [
                'query' => '84b17ed122fbdbd4',
                'variables' => [
                    'request' => [
                        'query' => $this->params['keyword'],
                        'limit' => 10,
                        'scope' => 'WORLDWIDE',
                        'locale' => 'tr-TR',
                        'scopeGeoId' => 1,
                        'searchCenter' => null,
                        'types' => ['LOCATION'],
                        'locationTypes' => [
                            'ACCOMMODATION'
                        ],
                        'userId' => null,
                        'context' => [
                            'listResultType' => 'HOTEL'
                        ],
                        'articleCategories' => [
                            'default',
                            'love_your_local',
                            'insurance_lander'
                        ],
                        'enabledFeatures' => [
                            'typeahead-q'
                        ]
                    ]
                ],
                "extensions" => [
                    "preRegisteredQueryId" => "5ddff5cef01e3cfd"
                ]
            ];

            $result = $this->restClientFroTripadvisr->post('https://www.tripadvisor.com/data/graphql/ids', [
                    'headers' => [
                        'accept-encoding' => 'gzip, deflate',
                        'content-type' => 'application/json',
                        'origin' => 'https://www.tripadvisor.com',
                        'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
                        'x-requested-by' => $this->tripAdvisorCookie,
                        'Cookie' => 'TAUnique=%1%enc%3AB8gsSVzcYv%2Fy%2FQcUCC8NkwTAxw1PuWKMN7hDUF0uFMBsFY3v8WCw%2B6S4L8prdRoSNox8JbUSTxk%3D; TATrkConsent=eyJvdXQiOiIiLCJpbiI6IkFMTCJ9; TASSK=enc%3AAGWI%2Fjlo8Bi8BIsq9syl2j66bc48e82FdKzTyCz99EMkiPVMHbfZ6ngS%2F%2FZ%2FLHG6rhp8Sul%2BflsMdGktQml1d%2Fv7%2BwaYcOfHfgNDsKFC%2FJK4vpvZ5AbBpyN8zPlNHh5kAQ%3D%3D; _lc2_fpi=eb26cb8958b8--01kg7mzmk5gj81kjyacda52m8t; _lc2_fpi_meta=%7B%22w%22%3A1769783415397%7D; _gcl_au=1.1.656612842.1769783416; _ga=GA1.1.959970588.1769783416; PMC=V2*MS.44*MD.20260130*LD.20260130; CM=%1%mds%2C1769783421921%2C1769869821%7C; _ga_QX0Q50ZC9P=GS2.1.s1769783415$o1$g1$t1769784141$j57$l0$h0; TASID=2CE514F9A73746734B5866FC46F2C79C; TADCID=JXGuyvNjCnVXf8NBABQChrLCR-aOT_K5vlfY_RXuc4v8CctrMv3z7OyJhtqOIyA2jOwugGFgO4oUe5amkFV2bF3B1pi0-C11DE0; TASession=V2ID.2CE514F9A73746734B5866FC46F2C79C*SQ.1*LS.Hotel_Review*HS.recommended*ES.popularity*DS.5*SAS.popularity*FPS.oldFirst*FA.1*DF.0*TRA.true; PAC=AJfQGZeJqolH8Hzh3aZ4aFh_W2_NwTyw1iLgJX-tGmLLLPZwnNUwZE10W5UpsGahNGHg2Ks3ir6Z_6VMT-2nePlhd0jEjv2wl51LQbZqgAxsvoqWpjsPObiKX0VGg8bLCCUuPQCm1PWMu6iQhRW8tlJasIUq89-o5gswGEJueIGjz6bk-Ugzm1MP8oxQBgQcCaCNPMtS5PvVLfz2craf2Xs%3D; SRT=TART_SYNC; TART=%1%enc%3Aego6iAgRUncSBJJBqhWUc6MS72Gdmrlbyt6LsE1hcOb28uizb4wsXf5kB4qidaAdxJICaUS3Vk4%3D; OptanonConsent=isGpcEnabled=0&datestamp=Mon+Mar+02+2026+15%3A44%3A46+GMT%2B0300+(GMT%2B03%3A00)&version=202601.2.0&browserGpcFlag=0&isIABGlobal=false&hosts=&consentId=65f573db-6363-4747-9874-4ef7843acd7e&interactionCount=1&isAnonUser=1&landingPath=https%3A%2F%2Fwww.tripadvisor.de%2FHotel_Review-g293974-d295165-Reviews-Grand_Yavuz_Hotel-Istanbul.html&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1%2CC0004%3A1&prevHadToken=0; _li_dcdm_c=.tripadvisor.de; pbjs_sharedId=04024d25-0c58-462b-a8df-f66362c4dfa8; pbjs_sharedId_cst=zix7LPQsHA%3D%3D; _lr_retry_request=true; _lr_env_src_ats=false; _gcl_aw=GCL.1772455489.null; pbjs_unifiedID=%7B%22TDID_LOOKUP%22%3A%22FALSE%22%2C%22TDID_CREATED_AT%22%3A%222026-03-02T12%3A44%3A48%22%7D; pbjs_unifiedID_cst=zix7LPQsHA%3D%3D; pbjs_li_nonid=%7B%7D; pbjs_li_nonid_cst=zix7LPQsHA%3D%3D; __gads=ID=1cd3edce1a02a3a9:T=1769783416:RT=1772455490:S=ALNI_MZw9YE9xOBfuT3GptcwBZz1kk9y8A; __gpi=UID=000012ed05a9c113:T=1769783416:RT=1772455490:S=ALNI_MZjriFWmZQ4byU9h5qi7PxTySAUPA; __eoi=ID=5e090e36e225d6f3:T=1769783416:RT=1772455490:S=AA-AfjaO0smbZgTBvQkXOeDLsC_b; _lr_sampling_rate=100; datadome=jUF6V7MInCDT_e60vxsoUawgoBJ~kcHXw8wWQdbdAkpYR1DUqrYEcBuA9knMvbo2Q67tacHuwfJkQIk9aIeMFP5dfkY4ZQhZyeNyekXYunHAxxhaJ19q4AqV0_oha73O; __vt=y16Z4GVTSrBGH8EoABQCT24E-H_BQo6gx1APGQJPtzvZqhsLjxQLo2PGhRdDojXJUj-NQn9d3uXlRiKs37Gm9slng8tYN5Ykvbhr99p9t0D5jo3uHrNEzrIfiJ_F87BCZBZZH0h1u-4d1B0A0JmN31zUaQ',
                    ],
                    'body' => json_encode($query),
                    'decode_content' => true
                ]
            );

            $result = $result->getBody()->getContents();
            $result = json_decode($result, 1);

            $dataResults = $result[0]['data']['Typeahead_autocomplete']['results'];

            $dataHotels = [];
            foreach ($dataResults as $dataResult) {

                $hotelKeyRegex = '/Hotel_Review-(.*)-Reviews/m';
                preg_match_all($hotelKeyRegex, $dataResult['details']['url'], $hotelKeyMatch, PREG_SET_ORDER, 0);
                $hotelKey = $hotelKeyMatch[0][1];

                $dataHotels[] = [
                    'name' => $dataResult['details']['localizedName'],
                    'location' => $dataResult['details']['localizedAdditionalNames']['longOnlyHierarchy'],
                    'key' => $hotelKey
                ];
            }

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

        } 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 getPropertyCompetitorPrice($params = [])
    {

        $response = ['status' => false, 'message' => ''];

        try {


            $currency = 'USD';
            $currencyRequest = fillOnUndefined($params, 'currency', 'USD');
            $competitorPropertyKey = $params['competitor_property_key'];
            $startDate = $params['date'];//$params['startDate'];
            $hotelIdExplode = explode('-d', $competitorPropertyKey, 2);
            $hotelId = $hotelIdExplode[1];


            $dailyPrices = [];
            $dailyPricesCache = [];

            $timeStartOverall = Carbon::now();

            $date = Carbon::parse($startDate)->toDateString();

            //$cacheKey = 'competitorPropertyHash-' . md5($competitorPropertyKey . '-' . $day . '-' . $currencyRequest);
            $cacheKey = 'competitorPropertyHash-' . md5($competitorPropertyKey . '-' . $currencyRequest);

            //Cache::forget($cacheKey);

            if (Cache::has($cacheKey)) {
                $dailyPricesCache = Cache::get($cacheKey);
            }

            if (isset($dailyPricesCache[$competitorPropertyKey]) && isset($dailyPricesCache[$competitorPropertyKey][$date])) {

                $dailyPrices = $dailyPricesCache[$competitorPropertyKey][$date];

            } else {

                $lastExchangeRate = $this->currencyService->lastExchangeRate($currency, $currencyRequest);
                $currencyList = $this->currencyService->getCurrencyList();
                if ($currencyList['status'] != 'success') {
                    throw new ApiErrorException($currencyList['message']);
                }

                $currencyList = pickItemFromArray('code', $currencyList['data']);
                if (!in_array($currencyRequest, $currencyList)) {
                    throw new ApiErrorException('Invalid currency code');
                }


                $dailyPrices['date'] = $date;
                $dailyPrices['competitorPropertyKey'] = $competitorPropertyKey;
                $dailyPrices['amount'] = null;
                $dailyPrices['currency'] = null;
                $dailyPrices['provider'] = null;

                $timeStart = Carbon::now();
                try {

                    $query = [
                        "detailId" => (integer)$hotelId,
                        "checkIn" => $date,
                        "checkOut" => Carbon::parse($date)->addDay()->toDateString(),
                        "rooms" => [
                            [
                                "adults" => 2,
                                "childrenAges" => []
                            ]
                        ]
                    ];

                    $client = new \GuzzleHttp\Client([
                            'max' => 5,
                            'strict' => false,
                            'referer' => false,
                            'protocols' => ['https'],
                            'timeout' => 5,
                            'headers' => [
                                'X-RapidAPI-Host' => 'travel-advisor.p.rapidapi.com',
                                'X-RapidAPI-Key' => 'baad80dc1cmsha3959d133378f89p1c7844jsnd2bbb8c1b529',
                                'Accept' => 'application/json',
                                'Content-Type' => 'application/json',
                                'Cache-Control' => 'no-cache',
                                'Connection' => 'keep-alive',
                                'Accept-Encoding' => 'gzip',
                                //'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
                            ]
                        ]
                    );

                    $result = $client->post('https://travel-advisor.p.rapidapi.com/hotels/v2/get-offers?currency=USD', [
                        'body' => json_encode($query)
                    ]);

                    $result = $result->getBody()->getContents();
                    $result = json_decode($result, 1);

                    //$result = json_decode('{"data":{"AppPresentation_queryHotelCommerceV2":{"__typename":"AppPresentation_HotelCommerceResponseV2","impressions":[{"__typename":"AppPresentation_ImpressionLog","data":"noClientLog"}],"sections":[{"__typename":"AppPresentation_HotelCommerceOfferList","trackingKey":"{\"ik\":\"031acedb-8ad1-4e60-83b7-f420f74270d2_0\",\"lid\":295165,\"hlk\":\"d933245d-57cc-41bb-abe7-65c56de1dbd4\",\"sn\":\"HotelCommerceDeals\",\"haik\":\"2b2dd3584c074bf1aa0fd27e0515ee34\",\"login\":false,\"plus\":false,\"hbfk\":\"a952489d18264e5dadc24707d6e912e7\"}","trackingTitle":"HotelOfferListSection_HOTEL_COMMERCE_OFFERS","stableDiffingType":"HotelOfferListSection_HOTEL_COMMERCE_OFFERS","isComplete":false,"clusterId":"HOTEL_COMMERCE_OFFERS","offersV2":[{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=BookingCom&src=32477061&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=1&matchID=1&oos=0&cnt=13&silo=10500&bucket=903023&nrank=1&crank=1&clt=M&ttype=MobileCR&tm=286615964&managed=false&capped=false&gosox=8odt39lfF_8t2Lfd3qE3zpQ0bxS-DfXQEVCGCu56GjFwnVeP40ut1Q002MbPq6-GJ6vB_j_RINgMP7TOHy-KvSCdi6d4Z8La-qnaZPCa-GEiuUaN_QJF7VccooTGz6JmhU8LApaUfO047k4rSkKAbSnSXPyL7p4B7_t3niacNpO2A0QC9DiwQuNiQC8EQLE_tDRUphklFjaKlLCkmWspYTT4-PvHv3rN5yphvdPwOS3NkNHYdexTPEJU7pHbjPOzsXI_bXJoAOHM2nApL3ce2g&priceShown=70&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=700&rq=P&rate=62.7700&fees=7.5400&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rdex=RDEX_637ab6e45797e5e16d5d775b08bcb864&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=19aaa73e178a8f07cd8f023359c51db95&ik=a952489d18264e5dadc24707d6e912e7&aok=ca2e78acd4e24a049ddd6ec13becaa79&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus0_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":"img2/branding/hotels/Booking_Com_v2_384x164_Blue.png","providerName":"Booking.com","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=HotelsCom2&src=34516980&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=2&matchID=1&oos=0&cnt=13&silo=6103&bucket=901739&nrank=2&crank=2&clt=M&ttype=MobileCR&tm=286615964&managed=false&capped=false&gosox=3hpVWWn59hLMfGrDq-0PCWG0EYNU_kg7POsPF6ThFAsDLVIH9gwfrcn3KKhOJ77Hs9AhHIzsICyJ0mI3s8HKXpv7jGezH5fXhsJqGmqdraP3tSka3ZDOkJoU7EIJ70o5dfkzgxFaWMjETOgqmxodjD1lXD1fYejoKeMUXnsa3xIWLHmXb6IRJ4xhf-0yHS8BVJTNTk4sr1oaCXYVIZq4lELuOzeOFUU6d4EYfZ4AxRhyztoG3Eb2AOJCs0ZKWt6hRj9B443Hfn2gtB2jjrSYxtg2QAMYK-T84MC4H3H0X3M&priceShown=70&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=700&rq=P&rate=62.8200&fees=7.5400&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rdex=RDEX_24b0d2a6ed870a6180e189a001b79dd5&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=12cc54312b2eb45f0ce07e66a5c1c33f6&ik=a952489d18264e5dadc24707d6e912e7&aok=c2783e8f360947db94f58e9d83893781&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus1_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"Hotels.com","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$63","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=Destinia&src=38799788&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=3&matchID=1&oos=0&cnt=13&silo=17847&bucket=941214&nrank=13&crank=13&clt=M&ttype=MobileCR&tm=286615964&managed=false&capped=false&gosox=swfzbqjFSX7gVvosEdYcyYIGyfWsITpUvJQf-vEJqDHm9NwKePRSjyIPgYDOS3Zu3lVB4dzt7cLJszgYOeRqxckOHll06lzUQrVe3cN6hK12F3yN-JD5PgYUe25vWygGqyUJllLEK0WqQnKNdJYH_ZPUgiXvFP7XXyp0h7lT9ou0NFSmGSUWNoqUsKSZaylhNPj4-8e_es3nKmG90_A5Lc2Q0dh17FM8QlTukduM87Oxcj9tcmgA4czacCkvdx7a&priceShown=63&pm=AIWE&hac=AVAILABLE&mbl=BEAT&mbldelta=0&rq=P&rate=56.4000&fees=7.5700&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rdex=RDEX_463dd3f7e09ddac3184dd5e74ad235d4&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=1b6dc44a7278cc8c32567e3a520bb93b6&ik=a952489d18264e5dadc24707d6e912e7&aok=97efe91fd2da40e78e184ad7b9c8b7e9&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$63","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus2_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"Destinia.com","strikeThroughPrice":{"__typename":"AppPresentation_LocalizedString","string":"$74","debugValueKey":null},"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=Expedia&src=32697091&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=4&matchID=1&oos=0&cnt=13&silo=4310&bucket=910482&nrank=3&crank=3&clt=M&ttype=MobileCR&tm=286615964&managed=false&capped=false&gosox=A9XDoEHOyR8iEoOswVX8y-cW5J59D7A7N0XHbUPeLv66diINev9wjgAObbDdrO6yX5d0Q1ez6ijY2HLxwIX5W9XpaS5zSbmuZK_8Gu7vLuTAD9SGrijsQAT4286JgdpRReQPdO0gi8p8HjzLpSV7beb1PKJh4qVLBTlLxU6LEb1krsYnSBNbM8o5e0dlEj_EjuMEKK-PIa-Wjo5kGgO767Q0VKYZJRY2ipSwpJlrKWE0-Pj7x796zecqYb3T8DktzZDR2HXsUzxCVO6R24zzs7FyP21yaADhzNpwKS93Hto&priceShown=70&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=700&rq=P&rate=62.8200&fees=7.5400&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rdex=RDEX_75d1f38b85875ca0bf26dcc0945b80d7&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=13cf902d80cadc2e02215c3661782bd91&ik=a952489d18264e5dadc24707d6e912e7&aok=cc924d45a89847e890676c53a4749cce&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus3_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"Expedia.com","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":null,"commerceLink":null,"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"otelz.com","strikeThroughPrice":null,"status":"IN_PROGRESS","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=TravelocityEWS&src=54221039&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=6&matchID=1&oos=0&cnt=13&silo=11456&bucket=860112&nrank=5&crank=5&clt=M&ttype=MobileCR&tm=286615964&managed=true&capped=false&gosox=MahhiGPAvYM26fgM1Fs4y0LVZilal8soQAd2MInZ40In_xelT2u3Ixjgz2DgbhROuqk_NPFo6jTPJtKMwVpV-CMX2PFFS0t0R3BGfZbK-b9Y1Jq0QYdwPNWnPIX2GiSyMqshHc50jde-NsAl4bH3ts_GhD0pIqyi4lT55BblhQcYWrVvWWB70uU03PUBEl4af9tWrpjsJHFaPzLyh2ldrULuOzeOFUU6d4EYfZ4AxRhyztoG3Eb2AOJCs0ZKWt6hRj9B443Hfn2gtB2jjrSYxtg2QAMYK-T84MC4H3H0X3M&priceShown=70&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=700&rq=P&rate=62.8200&fees=7.5400&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=16948884fd24b04e1043a4fb842aa97be&ik=a952489d18264e5dadc24707d6e912e7&aok=82abbe08c2104f3e80985e9b18d71158&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus5_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"Travelocity","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=Agoda&src=48793666&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=7&matchID=1&oos=0&cnt=13&silo=5122&bucket=895087&nrank=6&crank=6&clt=M&ttype=MobileCR&tm=286615964&managed=false&capped=false&gosox=AVPDU6RbcFVwDmbzu1YYBtZP2QUi_h128CKV_kPJuS07F_gMAdHJfUdZc8AvnTrys1pvQMRoQTuIgA976JCaSbt03vCzSlET_r8sQ_dNDrbRg9T-G1NQPHxYQ_TbM2jw-UtdbO2VUIE_TgNh3iknx_9MM4l1otBv9IETF1TlsG1h_2lMxYV4LzkEOncYyHUB0LI9QnHjhVUlnK50nbopfWyJVyDQFH6wPS4euHOGtm6Hz1FMFNk3jN9MF76vIS3C&priceShown=70&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=700&rq=P&rate=62.8200&fees=7.5300&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rdex=RDEX_6977b14032c41291e33b975570bcb286&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=1ce3884332c82f010606b95510eb54183&ik=a952489d18264e5dadc24707d6e912e7&aok=60e8134067604ba487e187f96f906c5a&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus6_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"Agoda.com","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=CtripTA&src=79214115&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=8&matchID=1&oos=0&cnt=13&silo=13669&bucket=899272&nrank=7&crank=7&clt=M&ttype=MobileCR&tm=286615964&managed=false&capped=false&gosox=lsSswv72QfbQgHuBbiLSFYE96DuL8ibgqcCcE_kHNN_Km9dkuLDm3L_m7RS8TJ3HivMyOCtiFJw9AfjfwuKpbEVsJk90QOwx9LCM4T2yPAJh7pkq6NTEKg0WDZ-hQs8lqb4uKT8BvbntHGMsxczemosM8iUgx9LuUm4EROAIHrXC9Gj0-zlbhNnfi4QogBrlrJpHfyCEDtt94CM_z-5cGGHhfsgOsRiGcJYkNnQrWhC3R27nhgsncVtnNAe50s6W&priceShown=70&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=700&rq=P&rate=62.8100&fees=7.5400&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rdex=RDEX_596afd5c88483c206cc4318df651709e&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=18f2d4afbf696d011dbe4059cc42ee964&ik=a952489d18264e5dadc24707d6e912e7&aok=12a5b5ad33374d5dbf7c1ee6c3d83798&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus7_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"Trip.com","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$74","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=Mirai&src=255621478&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=9&matchID=1&oos=0&cnt=13&silo=26106&bucket=979000&nrank=8&crank=8&clt=M&ttype=MobileCR&tm=286615964&managed=true&capped=false&gosox=sb95c4IBPXymK172SEJwTOq17gLqU_oE5TJLTjytnMaxAedRBBXUYoekoR-d9PMVNvrpLlBCaSTqtFK0EoJ2boOmn7uhCcmC2KGSJKrEybT4gR0orTS2T-AArDVYrR6dYi4oq6NjBVtyuYK5lmWSSKlSNP1ISAz8UxD3Fybyaf0M96yboyeG0iMId70TR_Fd28BM-yClSZkKZcUCt5Qj4mfpsweKUIlmCaDUaTygVHxh4X7IDrEYhnCWJDZ0K1oQt0du54YLJ3FbZzQHudLOlg&priceShown=74&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=1100&rq=P&rate=67.0700&fees=6.7100&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rdex=RDEX_1b7639ec01898e034557cc27443ed58d&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=17098edcf450ce800b98a43c64c737828&ik=a952489d18264e5dadc24707d6e912e7&aok=dddc0118d4ec4025b3bd3a8c56cd61f0&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$74","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus8_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"Official website","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$67","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=StayForLong&src=143811959&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=10&matchID=1&oos=0&cnt=13&silo=40511&bucket=944068&nrank=9&crank=9&clt=M&ttype=MobileCR&tm=286615964&managed=false&capped=false&gosox=iU3wCxpEHfKz1_yraLhvgLECmoIxDl97J66m2TgHHDHBaXRNIPUumERknooRzmLhEf1P3JKVjztLN-P06N6ZoJs7YuP0twV4ttX9T7P2xCVP6M-JfITK9FzYFiRtslp_bNXI4HjtY-enzYzJfOrNNoE1QjUcqgXJchXu2mYd5xM21Y_InGFgm4ssJnJCe_hHYf9pTMWFeC85BDp3GMh1AdCyPUJx44VVJZyudJ26KX1siVcg0BR-sD0uHrhzhrZuh89RTBTZN4zfTBe-ryEtwg&priceShown=67&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=400&rq=P&rate=66.0100&fees=0.9900&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rdex=RDEX_1a2c43030be33dc2825829366987f63a&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=18f8f91cf2b981d48d9a18cd57013d982&ik=a952489d18264e5dadc24707d6e912e7&aok=ced593da26634a0d99b705e4a8d92827&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$67","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus9_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"StayForLong","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=Vio&src=256849928&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=11&matchID=1&oos=0&cnt=13&silo=47493&bucket=997319&nrank=10&crank=10&clt=M&ttype=MobileCR&tm=286615964&managed=false&capped=false&gosox=qi8Pk1Rxoc1dwj6TlSgFnDHmTstrv7hj9b7zE8y_bU1UhxfB0tE_98RArd2AGTDUfqleSf3zWjw73eZ_KKqYWhD2WpKqmjNXuuKaHjmd90ShD8E-GDEqX0YFTdRe7DHJnw-aMYVFolfl6BPtHd2VDX3OrZqMMJuXF4BjH4EnXAghnAXWcstQ_ATM_czA23uMxrvsCe2kVfhGH30bQ8AVpnzO-4h0JzsHHOAlD7-2zqL5HNWwqmBPMFSYFlkr7Hpm9lTNXFfW_xzFOmhEb7yupJBLokGIyXFrxUiGNMxHAZU&priceShown=70&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=700&rq=P&rate=62.7800&fees=7.5300&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rdex=RDEX_1db480d711ee619f011e9cb65cc805d7&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=184590a69616cbf405d1409a6ec8a78b8&ik=a952489d18264e5dadc24707d6e912e7&aok=fa05ea300e294464b826633eae70aa87&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus10_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"Vio.com","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=BookingeDreamsWL&src=60220887&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=12&matchID=1&oos=0&cnt=13&silo=35404&bucket=914257&nrank=11&crank=11&clt=M&ttype=MobileCR&tm=286615964&managed=true&capped=false&gosox=wAYrrGjW7Bydo3kUpJXG9x-_rTT4xfM27ciwH-8l-DFHQoXiw53-HkoXH2woreUgPEQGNzWoU0UWdeapcHF6TC2ZZTDzaMEmDVNA1Ju9Ksf3PkgqLsaIz3LZAuwdMtNPvqhfyhXVqIaPY00bJD0LJE-0Cn622zDgb7Kfys-XrUCA00kLdR6Ct3D621MI2FwsqpyEGSk8F_hZm79XabgIE9lfMxamOainLytCpOUDBa13BFhBr8Q51Y0eTw8h_GtuOIcjIhb4Huqemyr-_eDENA&priceShown=70&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=700&rq=P&rate=62.7700&fees=7.5400&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=1780cec9318b617c63e6e6c6e2f041d05&ik=a952489d18264e5dadc24707d6e912e7&aok=e4d17c75ad2a42529ce22b377ebafcea&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus11_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"eDreams","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]},{"__typename":"AppPresentation_HotelCommerceOfferDeal","displayPrice":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"commerceLink":{"__typename":"AppPresentation_ExternalLink","externalUrl":"/Commerce?p=OrbitzEWS&src=78874101&geo=295165&from=HotelDateSearch_HotelCommerceDeals&slot=13&matchID=1&oos=0&cnt=13&silo=20728&bucket=862895&nrank=11&crank=12&clt=M&ttype=MobileCR&tm=286615964&managed=true&capped=false&gosox=duEJfdKRjSaUExDPyWiVTxfzxv14vo3_X57IHuv-PENZzSU0u_qCcSugyEI21SUpyTdJYppCoBfhowdBz1tytuSVcY2ctKopxjdDSR4zUA8bk_9BDHix8tffG7gOF9URKgwSVrp1OniloXJJ3ME0EJzucmES6J8quJoqj2ReWepGgoURtfMoOFl-stDivIvoQmMxR6jRfSXd2WGXNXtHBnzO-4h0JzsHHOAlD7-2zqL5HNWwqmBPMFSYFlkr7Hpm9lTNXFfW_xzFOmhEb7yupJBLokGIyXFrxUiGNMxHAZU&priceShown=70&pm=AIWE&hac=AVAILABLE&mbl=LOSE&mbldelta=700&rq=P&rate=62.8200&fees=7.5400&cur=USD&adults=2&child_rm_ages=&inDay=18&outDay=19&rdex=RDEX_445cc1f599f38d72d456f6729697e683&rooms=1&inMonth=3&inYear=2024&outMonth=3&outYear=2024&auid=a087cf4c-7eeb-4052-9492-74e1ec4dc0d4&def_d=false&bld=L_1,D_47,G_2,W_1,U_0,C_240318,T_15&bh=true&cs=10084d859975c54482a6a57bb7df14f32&ik=a952489d18264e5dadc24707d6e912e7&aok=c3ebd3b4b4534b04b485a5d5ebfa84d3&tp=APS-HotelCommerceDeals&pageLocId=295165","text":{"__typename":"AppPresentation_LocalizedString","string":"$70","debugValueKey":null},"accessibilityString":null,"trackingContext":"server_nonPlus12_hotelCommerceLink"},"details":[{"__typename":"AppPresentation_LocalizedString","string":"Free breakfast included","debugValueKey":null}],"providerLogoUrl":null,"providerName":"Orbitz.com","strikeThroughPrice":null,"status":"AVAILABLE","roomUrgencyMessage":null,"labels":[]}]},{"__typename":"AppPresentation_LogicalBreak","stableDiffingType":"LogicalBreakSection","spacing":"spacing-03","clusterId":null,"divider":null,"background":null},{"__typename":"AppPresentation_OmnibusDisclosure","link":null,"contentText":{"__typename":"AppPresentation_HtmlString","htmlString":"Prices are provided by our partners, and reflect average nightly room rates, including taxes and fees that are fixed, known to our partners, and due at time of booking. Other miscellaneous taxes and hotel fees which are not fixed or due at time of booking may be payable at the property at time of stay. Please see our partners for more details."},"trackingTitle":"HotelDealsDisclaimerSection","trackingKey":"{\"dt\":\"HOTEL_DEALS\",\"ik\":\"031acedb-8ad1-4e60-83b7-f420f74270d2_1\",\"sn\":\"HotelCommerceDeals\"}","stableDiffingType":"HotelDealsDisclaimerSection","clusterId":null},{"__typename":"AppPresentation_LogicalBreak","stableDiffingType":"LogicalBreakSection_1","spacing":"spacing-03","clusterId":null,"divider":null,"background":null}],"statusV2":{"__typename":"AppPresentation_SuccessQueryResponseStatus","partial":false,"pollingStatus":{"__typename":"AppPresentation_QueryResponsePollingStatus","delayForNextPollInMillis":10,"updateToken":"eyJ2ZXIiOiJ2MiIsInR5cCI6IkpXVCIsImFsZyI6IkVTMjU2IiwidmVyc2lvbiI6IjEifQ.eyJvYmplY3QiOiJ7XCJAY1wiOlwiLlVwZGF0ZVRva2VuXCIsXCJ0eXBlXCI6XCJQT0xMSU5HXCIsXCJjbHVzdGVySWRzXCI6W1wiSE9URUxfQ09NTUVSQ0VfT0ZGRVJTXCJdLFwicHJvdmlkZXJVcGRhdGVUb2tlbnNcIjp7XCJIT1RFTF9ERVRBSUxfUFJPVklERVJcIjp7XCJAY1wiOlwiLlN0cmluZ1ZhbHVlUHJvdmlkZXJVcGRhdGVUb2tlblwiLFwidmFsdWVcIjpudWxsfX0sXCJwb2xsaW5nU2VxdWVuY2VOdW1cIjoxfSJ9.MjRlNTU4MmItMGIyNS00YTI1LTk4NDUtYTY0YjFiNzYxODc0Lk1FVUNJRVNiQlU2bWIxTjlvYV80VWx3eEwtTXY4UmZRal9fMGFvOXB1WGMtRG5rVUFpRUFsUDJPVUdMYzBHY2NpRTlXLVJOUXBtT3FLNlZKSHpfV3NmSFZmNlpjaFhV"}},"updatedClusterIds":[]}}}', 1);

                    if (isset($result['data']['AppPresentation_queryHotelCommerceV2']['sections'][0]['offersV2'])) {

                        $dataResults = $result['data']['AppPresentation_queryHotelCommerceV2']['sections'][0]['offersV2'];

                        $dailyPricesByProvider = [];
                        foreach ($dataResults as $dataResult) {

                            if ($dataResult['displayPrice']) {
                                $priceText = str_replace('$', '', $dataResult['displayPrice']['string']);
                                $provider = $dataResult['providerName'];

                                if ($priceText) {

                                    $taxesAndFeesText = empty($taxesAndFeesText) ? 0 : $taxesAndFeesText;
                                    $dailyPricesByProvider[] = [
                                        'amount' => round(moneyDoubleFormatDecimal((($priceText + $taxesAndFeesText)) * $lastExchangeRate['data'])),
                                        'currencyCode' => $currencyRequest,
                                        'provider' => $provider,
                                        'logo' => config('app.url') . '/img/channel-icons/' . mb_strtolower(str_replace('.', '', $provider)) . '.png',
                                    ];

                                }
                            }

                        }

                        if (!empty($dailyPricesByProvider)) {

                            $rateCollect = collect($dailyPricesByProvider);
                            $rateCollect = $rateCollect->sortBy('amount')->toArray();
                            $minRate = reset($rateCollect);

                            $dailyPrices['amount'] = $minRate['amount'];
                            $dailyPrices['currency'] = $currencyRequest;
                            $dailyPrices['provider'] = $minRate['provider'];
                            $dailyPrices['all'] = array_values($rateCollect);

                            if (Cache::has($cacheKey)) {
                                $dailyPricesCache = Cache::get($cacheKey);
                            }

                            $dailyPrices['cacheTime'] = Carbon::now()->toDateTimeString();

                            $dailyPricesCache[$dailyPrices['competitorPropertyKey']][$dailyPrices['date']] = $dailyPrices;

                            Cache::put($cacheKey, $dailyPricesCache, 60 * 5);//600 10 dk
                        }


                    }


                } catch (Exception $e) {
                    Log::debug($e->getMessage());
                    //dd($e->getMessage());
                }

                $timeEnd = Carbon::now();
                $timeDiff = Carbon::parse($timeStart)->floatDiffInRealSeconds(Carbon::parse($timeEnd));
                //$dailyPrices[$hotelKey][$day]['time'] = $timeDiff;
                $dailyPrices['time'] = $timeDiff;

            }

            $timeEndOverall = Carbon::now();
            $timeDiffOverall = Carbon::parse($timeStartOverall)->floatDiffInRealSeconds(Carbon::parse($timeEndOverall));

            //$dailyPrices['responseTime'] = $timeDiffOverall;

            $response = ['status' => true, 'message' => null, 'data' => $dailyPrices];

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

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

        try {

            $params = $request->all();


            if (isset($params['property_id'])) {


                $channelManagerPropertyMappingCriteria = [
                    'criteria' =>
                        [
                            ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                            ['field' => 'channel_manager_id', 'condition' => '=', 'value' => 12],
                            ['field' => 'status', 'condition' => '=', 'value' => 1],
                        ],
                    'firstRow' => true
                ];

                $channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria);

                if ($channelManagerPropertyMapping['status'] == 'success' && !empty($channelManagerPropertyMapping['data'])) {
                    $params['competitor_property_key'] = $channelManagerPropertyMapping['data']['channel_manager_property_id'];
                } else {
                    throw new ApiErrorException('Mapping not found.');
                }


            }

            $paramCompetitorPrice = [
                'date' => $params['date'],
                'competitor_property_key' => $params['competitor_property_key'],
                'currency' => $params['currency'],
            ];

            $propertyCompetitorPrice = $this->getPropertyCompetitorPrice($paramCompetitorPrice);

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

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $propertyCompetitorPrice['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;
        }
        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);

    }

    public function createPropertyCompetitor(Request $request)
    {

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

        try {

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


            $requestSelectResult = $this->competitorPriceAnalysisService->selectPropertyCompetitorMapping($requestSelectCriteria);

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

            if (count($requestSelectResult['data']) >= $this->maxCompetitorPropertyAdd) {
                //throw new ApiErrorException('Up to 5 records can be added.');
            }


            $requestParam = [
                'property_id' => $this->params['params']['property_id'],
                'competitor_property_name' => $this->params['params']['competitor_property_name'],
                'competitor_property_key' => $this->params['params']['competitor_property_key'],
                'created_by' => $request->auth->id,
                'updated_by' => $request->auth->id,
            ];

            $requestResult = $this->competitorPriceAnalysisService->createPropertyCompetitorMapping($requestParam);

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


            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $requestResult['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;
        }
        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);

    }

    public function syncPropertyCompetitor(Request $request)
    {

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

        try {

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


            $requestSelectResult = $this->competitorPriceAnalysisService->selectPropertyCompetitorMapping($requestSelectCriteria);

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

            DB::beginTransaction();

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


            $competitorProperty = $this->params['params']['competitor'];


            if (count($competitorProperty) > $this->maxCompetitorPropertyAdd) {
                //throw new ApiErrorException('Up to 5 records can be added.');
            }

            $requestResultData = [];
            foreach ($competitorProperty as $property) {

                $requestParam = [
                    'property_id' => $this->params['params']['property_id'],
                    'competitor_property_name' => $property['name'],
                    "competitor_property_source" => fillOnUndefined($property, "competitor_property_source"),
                    'competitor_property_key' => $property['key'],
                    'created_by' => $request->auth->id,
                    'updated_by' => $request->auth->id,
                ];

                $requestResult = $this->competitorPriceAnalysisService->createPropertyCompetitorMapping($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 getPropertyCompetitor(Request $request)
    {

        $params = $request->all();

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

        try {

            $requestSelectCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['params']['property_id']],
                ]
            ];

            $columns = ['id', 'property_id', 'competitor_property_name', 'competitor_property_key','competitor_property_source'];
            $requestSelectResult = $this->competitorPriceAnalysisService->selectPropertyCompetitorMapping($requestSelectCriteria, $columns);

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

            if (empty($requestSelectResult['data'])) {
                throw new ApiErrorException(lang('Mapping data not found'));
            }

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $requestSelectResult['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;
        }
        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);

    }

    public function deletePropertyCompetitor(Request $request)
    {

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

        try {

            $requestSelectCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['params']['property_id']],
                    ['field' => 'id', 'condition' => '=', 'value' => $this->params['params']['property_competitor_mapping_id']]
                ], 'firstRow' => true
            ];


            $requestSelectResult = $this->competitorPriceAnalysisService->selectPropertyCompetitorMapping($requestSelectCriteria);

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

            if (empty($requestSelectResult['data'])) {
                throw new ApiErrorException(lang('Mapping data not found'));
            }

            $deletePropertyCompetitorMapping = $this->competitorPriceAnalysisService->deletePropertyCompetitorMapping($requestSelectResult['data']['id']);

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

            $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;
        }
        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);

    }

    public function propertyCompetitorExcel(Request $request)
    {

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

        try {

            $params = $this->params['params'];

            if (Carbon::parse($params['start_date'])->isBefore(Carbon::now()) && !Carbon::parse($params['start_date'])->isToday()) {
                throw new ApiErrorException('Comparison possible for today and next days.');
            }

            if (Carbon::parse($params['start_date'])->diffInDays(Carbon::parse($params['finish_date'])) > 14) {
                throw new ApiErrorException('A maximum of 14 days of data can be retrieved.');
            }

            $requestSelectCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];

            $columns = ['id', 'property_id', 'competitor_property_name', 'competitor_property_key','competitor_property_source'];
            $propertyCompetitor = $this->competitorPriceAnalysisService->selectPropertyCompetitorMapping($requestSelectCriteria, $columns);

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

            if (empty($propertyCompetitor['data'])) {
                throw new ApiErrorException(lang('Mapping data not found'));
            }

            $dataTableData = [];

            $dateFirst = $params['start_date'];
            $dateDiff = Carbon::parse($params['start_date'])->diffInDays(Carbon::parse($params['finish_date']));
            foreach ($propertyCompetitor['data'] as $property) {
                for ($i = 0; $i <= $dateDiff; $i++) {

                    $date = Carbon::parse($dateFirst)->addDays($i)->toDateString();


                    $propertyCompetitorPrice = [
                        'status' => false,
                        'data' => []
                    ];

                    $cacheKey = 'competitorPropertyHash-' . md5($property['key'] . '-' . $params['currency']);

                    if (Cache::has($cacheKey)) {
                        $dailyPricesCache = Cache::get($cacheKey);

                        if (isset($dailyPricesCache[$property['key']][$date])) {
                            $propertyCompetitorPrice = [
                                'status' => true,
                                'data' => $dailyPricesCache[$property['key']][$date]
                            ];
                        }
                    }

                    /*if(empty($propertyCompetitorPrice)) {
                        $paramCompetitorPrice = [
                            'date' => $date,
                            'competitor_property_key' => $property['key'],
                            'currency' => $params['currency'],
                        ];

                        $propertyCompetitorPrice = $this->getPropertyCompetitorPrice($paramCompetitorPrice);
                    }*/

                    $dailyAmount = null;
                    if ($propertyCompetitorPrice['status']) {
                        $dailyAmount = $propertyCompetitorPrice['data']['amount'];
                    }

                    $dataTableData['value'][$property['key']][$date] = [
                        'amount' => $dailyAmount,
                        'currency' => $params['currency']
                    ];

                    $dataTableData['property'][$property['key']] = $property['name'];
                    $dataTableData['date'][$date] = Carbon::parse($date)->format('d.m.Y');

                }

            }


            $fileName = 'PropertyCompetitorExport-' . md5(implode('-', $params)) . '.xlsx';
            $fileNamePath = 'excel/' . $fileName;
            $fileNamePublic = config('app.url') . '/' . $fileNamePath;

            $excelStore = Excel::store(new PropertyCompetitorExport($dataTableData), $fileNamePath, 'public');

            if (!$excelStore) {
                throw new ApiErrorException(lang('Mapping data not found'));
            }

            $data = [
                'url' => $fileNamePublic
            ];

            //Delete files older than 1 hours
            $excelFileDir = public_path('excel');
            foreach (glob($excelFileDir . '/' . "*") as $file) {
                if (filemtime($file) < time() - 3600) { // 6 hours 21600
                    unlink($file);
                }
            }

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $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;
        }
        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);

    }


    public function bestAvailablePrice(Request $request)
    {

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

        try {

            $params = json_decode($request->getContent(), 1);
            $params = $this->params['params'];

            $params['type'] = fillOnUndefined($params, 'type', 'range');
            $bookingEnginePropertyId = $params['property_id'];

            $cacheKeyParam[] = $params['type'];
            $cacheKeyParam[] = $bookingEnginePropertyId;
            if ($params['type'] == 'range') {

                if (Carbon::parse($params['start_date'])->isBefore(Carbon::now()) && !Carbon::parse($params['start_date'])->isToday()) {
                    throw new ApiErrorException('Comparison possible for today and next days.');
                }

                if (Carbon::parse($params['start_date'])->diffInDays(Carbon::parse($params['finish_date'])) > 14) {
                    throw new ApiErrorException('A maximum of 14 days of data can be retrieved.');
                }

                $cacheKeyParam[] = $params['start_date'] . '|' . $params['finish_date'];
            } else if ($params['type'] == 'date') {
                $cacheKeyParam[] = $params['date'] . '|' . $params['currency'];
            }

            $cacheKey = 'CRR:' . md5(implode(',', $cacheKeyParam));


            //Cache::forget($cacheKey);
            if (Cache::has($cacheKey)) {
                $responseData = Cache::get($cacheKey);
            } else {

                $requestParam = [
                    'criteria' => [
                        ['field' => 'channel_id', 'condition' => '=', 'value' => 5],
                        ['field' => 'property_id', 'condition' => '=', 'value' => $bookingEnginePropertyId],
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ],
                    'with' => ['currency'],
                    'firstRow' => true
                ];

                $getChannelProperty = $this->propertyChannelMappingService->select($requestParam);
                $getChannelProperty = $getChannelProperty['status'] == 'success' && !empty($getChannelProperty['data']) ? $getChannelProperty['data'] : null;

                if (!$getChannelProperty) {
                    throw new ApiErrorException('Property Channel not found');
                }


                switch ($params['type']) {

                    case 'range' :

                        $requestParam = [
                            'criteria' => [
                                ['field' => 'channel_id', 'condition' => '=', 'value' => 5],
                                ['field' => 'property_id', 'condition' => '=', 'value' => $bookingEnginePropertyId],
                                ['field' => 'stop_sell', 'condition' => '=', 'value' => 0],
                                ['field' => 'date', 'condition' => '>=', 'value' => \Carbon\Carbon::parse($params['start_date'])->format('Y-m-d')],
                                ['field' => 'date', 'condition' => '<', 'value' => Carbon::parse($params['finish_date'])->addDay()->format('Y-m-d')],
                                ['field' => 'amount', 'condition' => '<>', 'value' => null],
                                ['field' => 'amount', 'condition' => '<>', 'value' => 0],
                                ['field' => 'status', 'condition' => '=', 'value' => 1],
                            ],
                            'with' => [
                                'roomRateMapping.propertyRoomRate'
                            ],
                            'orderBy' => [
                                ['field' => 'date', 'value' => 'ASC'],
                                ['field' => 'amount', 'value' => 'ASC']
                            ],
                        ];

                        $getPropertyRoomRatePrice = $this->propertyRoomRatePriceService->select($requestParam);

                        if ($getPropertyRoomRatePrice['status'] != 'success' || empty($getPropertyRoomRatePrice['data'])) {
                            throw new ApiErrorException(lang('PropertyRoomRatePrice not found'));
                        }

                        $getPropertyRoomRatePrice = $getPropertyRoomRatePrice['status'] == 'success' && !empty($getPropertyRoomRatePrice['data']) ? $getPropertyRoomRatePrice['data'] : [];

                        $firstDate = Carbon::parse($params['start_date'])->format('Y-m-d');
                        $lastDate = Carbon::parse($params['finish_date'])->addDay()->format('Y-m-d');
                        $dateDiff = Carbon::parse($firstDate)->diffInDays(Carbon::parse($lastDate));

                        $rateAndAvailability = [];
                        for ($i = 0; $i < $dateDiff; $i++) {
                            $date = Carbon::parse($firstDate)->addDays($i)->toDateString();

                            $bestPrice = collect($getPropertyRoomRatePrice)
                                ->where('date', $date)
                                ->where('room_rate_mapping.property_room_rate.name', 'Best Available Rate')
                                ->sortBy('amount')->first();
                            $bestPrice = $bestPrice ? $bestPrice['amount'] : null;

                            $rateAndAvailability[$date] = [
                                'rate' => round($bestPrice),
                                'available' => $bestPrice ? true : false,
                            ];

                        }

                        $responseData = [
                            'currency' => $getChannelProperty['currency']['code'],
                            'currency_icon' => $getChannelProperty['currency']['symbol'],
                            'date' => $rateAndAvailability
                        ];


                        if (count($rateAndAvailability) == collect($rateAndAvailability)->where('available', false)->count()) {
                            $responseData = null;
                        }

                        Cache::put($cacheKey, $responseData, 60 * 60);//1h 60 * 60

                        break;

                    case 'date' :

                        $requestParam = [
                            'criteria' => [
                                ['field' => 'channel_id', 'condition' => '=', 'value' => 5],
                                ['field' => 'property_id', 'condition' => '=', 'value' => $bookingEnginePropertyId],
                                ['field' => 'stop_sell', 'condition' => '=', 'value' => 0],
                                ['field' => 'date', 'condition' => '=', 'value' => Carbon::parse($params['date'])->format('Y-m-d')],
                                ['field' => 'amount', 'condition' => '<>', 'value' => null],
                                ['field' => 'amount', 'condition' => '<>', 'value' => 0],
                                ['field' => 'status', 'condition' => '=', 'value' => 1],
                            ],
                            'with' => [
                                'roomRateMapping.propertyRoomRate'
                            ],
                            'orderBy' => [
                                ['field' => 'date', 'value' => 'ASC'],
                                ['field' => 'amount', 'value' => 'ASC']
                            ],
                        ];

                        $getPropertyRoomRatePrice = $this->propertyRoomRatePriceService->select($requestParam);

                        if ($getPropertyRoomRatePrice['status'] != 'success' || empty($getPropertyRoomRatePrice['data'])) {
                            throw new ApiErrorException(lang('PropertyRoomRatePrice not found'));
                        }

                        $getPropertyRoomRatePrice = $getPropertyRoomRatePrice['status'] == 'success' && !empty($getPropertyRoomRatePrice['data']) ? $getPropertyRoomRatePrice['data'] : [];


                        $rateAndAvailability = [];
                        $bestPriceSelect = collect($getPropertyRoomRatePrice)
                            ->where('date', $params['date'])
                            ->where('room_rate_mapping.property_room_rate.name', 'Best Available Rate')
                            ->sortBy('amount')->first();

                        $bestPrice = $bestPriceSelect ? $bestPriceSelect['amount'] : null;

                        if ($params['currency'] != $bestPriceSelect['currency']) {
                            $lastExchangeRate = $this->currencyService->lastExchangeRate($bestPriceSelect['currency'], $params['currency']);
                            $bestPrice = $bestPrice * $lastExchangeRate['data'];

                        }

                        $rateAndAvailability[$params['date']] = [
                            'rate' => round($bestPrice),
                            'available' => $bestPrice ? true : false,
                        ];

                        $responseData = [
                            'currency' => $params['currency'],
                            'date' => $rateAndAvailability
                        ];

                        if (count($rateAndAvailability) == collect($rateAndAvailability)->where('available', false)->count()) {
                            $responseData = null;
                        }

                        Cache::put($cacheKey, $responseData, 60 * 60);//1h 60 * 60

                        break;

                }


            }

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

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

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

        try {

            $data = null;
            $params = $this->params['params'];

            $openAiToken = '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';

            $client = new \GuzzleHttp\Client([
                    'max' => 5,
                    'strict' => false,
                    'referer' => false,
                    'protocols' => ['https'],
                    'timeout' => 30,
                    'headers' => [
                        'Authorization' => 'Bearer ' . $openAiToken,
                        'Content-Type' => 'application/json',
                        'Cache-Control' => 'no-cache',
                        'Connection' => 'keep-alive',
                        'Accept-Encoding' => 'gzip'
                    ]
                ]
            );


            $query = [
                'model' => 'gpt-4o',
                'response_format' => [
                    'type' => 'json_object'
                ],
                'messages' => [
                    [
                        'role' => 'system',
                        'content' => 'Sen bir otel gelir yönetimi (revenue management) uzmanısın. Görev: 1. Verilen fiyatları analiz et. 2. İstenen dilde yorum ve öneri üret. Cevap alanları: {"property": "string", "currency": "string", "average_price": "float", "average_difference": "float (10,2)", "price_position": "string", "competitor_average_price": "float (10,2)", "highest_difference_day": "string (format: d.m.Y)", "highest_difference_percent": "float", "language": "string", "comment": "string", "recommendation": "string"}. price_position değeri higher, lower veya similar olabilir. highest_difference_day ve highest_difference_percent rakiplere göre en yüksek kalan güne göre, format: float(10.2). price_position, average_difference ve competitor_average_price, rakiplerin ortalamalarına göre, format: float. Sadece geçerli JSON döndür, başka açıklama veya metin ekleme.'
                    ],
                    [
                        'role' => 'user',
                        'content' => json_encode($params)
                    ]
                ]

            ];

            $result = $client->post('https://api.openai.com/v1/chat/completions', [
                'body' => json_encode($query)
            ]);

            $result = $result->getBody()->getContents();
            $result = json_decode($result, 1);

            $choiceMessage = reset($result['choices']);

            if (isset($choiceMessage['message']['content'])) {
                $choiceMessage = json_decode($choiceMessage['message']['content'], 1);
                $data = $choiceMessage;
            }

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

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

    }

    public function promotionAvailable(Request $request)
    {

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

        $promotionAvailableData = [];

        try {

            $data = null;
            $params = $this->params['params'];


            //property_channel_coupon
            $propertyChannelCouponData = null;
            $propertyChannelCouponCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => 1],
                    ['field' => 'start_date', 'condition' => '<=', 'value' => Carbon::parse($params['date'])->toDateString()],
                    ['field' => 'end_date', 'condition' => '>=', 'value' => Carbon::parse($params['date'])->toDateString()],
                    ['field' => 'is_notify', 'condition' => '=', 'value' => 1],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'orderBy' => [
                    ['field' => 'value', 'value' => 'DESC']
                ],
            ];

            $propertyChannelCoupon = $this->propertyChannelCouponService->select($propertyChannelCouponCriteria);

            if ($propertyChannelCoupon['status'] == 'success') {
                foreach ($propertyChannelCoupon['data'] as $coupon) {
                    if (!empty($coupon['reservation_start_date']) && !empty($coupon['reservation_end_date'])) {
                        if (Carbon::parse($params['date'])->betweenIncluded(Carbon::parse($coupon['reservation_start_date']), Carbon::parse($coupon['reservation_end_date']))) {
                            $propertyChannelCouponData = [
                                'type' => $coupon['type'],
                                'value' => $coupon['value'],
                            ];
                            break;
                        } else {
                            continue;
                        }
                    } else {
                        $propertyChannelCouponData = [
                            'type' => $coupon['type'],
                            'value' => $coupon['value'],
                        ];
                    }
                }
            }
            $promotionAvailableData['popup'] = $propertyChannelCouponData;
            //property_channel_coupon


            //property_promotion


            //property_promotion
            $propertyPromotionData = null;
            $promotionTypes = ['PRD', 'BFD', 'LST', 'DSC'];
            $propertyPromotionCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => ['promotionType'],
                'orderBy' => [
                    ['field' => 'promotion_type_id', 'value' => 'ASC']
                ],
            ];

            $propertyPromotions = $this->propertyPromotionService->select($propertyPromotionCriteria);

            $propertyPromotionGroup = null;
            if ($propertyPromotions['status'] == 'success') {

                foreach ($propertyPromotions['data'] as $propertyPromotion) {
                    $propertyPromotionGroup[$propertyPromotion['promotion_type']['type_code']][$propertyPromotion['id']] = $propertyPromotion;
                }


                foreach ($promotionTypes as $promotionType) {

                    $propertyPromotionData[$promotionType] = null;
                    if (isset($propertyPromotionGroup[$promotionType])) {

                        switch ($promotionType) {

                            case 'PRD':

                                $propertyPromotionSelected = collect($propertyPromotionGroup[$promotionType])
                                    ->where('start_date', '<=', Carbon::parse($params['date'])->toDateString())
                                    ->where('end_date', '>=', Carbon::parse($params['date'])->toDateString())
                                    ->where('reservation_start_date', '<=', Carbon::parse($params['date'])->toDateString())
                                    ->where('reservation_end_date', '>=', Carbon::parse($params['date'])->toDateString())
                                    ->sortByDesc('amount')
                                    ->first();

                                if ($propertyPromotionSelected) {

                                    $propertyPromotionData[$promotionType] = [
                                        'type' => 'PER',
                                        'value' => $propertyPromotionSelected['amount'],
                                        'is_mobile' => $propertyPromotionSelected['is_mobile'],
                                    ];

                                }


                                break;

                            case 'BFD' || 'LST':


                                $propertyPromotionSelected = collect($propertyPromotionGroup[$promotionType])
                                    ->sortByDesc('amount')
                                    ->toArray();

                                if ($propertyPromotionSelected) {

                                    foreach ($propertyPromotionSelected as $perPromotion) {

                                        if (Carbon::parse($params['date'])->subDays($perPromotion['day_before'])->lessThanOrEqualTo(Carbon::now())) {
                                            $propertyPromotionData[$promotionType] = [
                                                'type' => 'PER',
                                                'value' => $perPromotion['amount'],
                                                'is_mobile' => $perPromotion['is_mobile'],
                                            ];
                                            break;
                                        }

                                    }
                                }

                                break;
                            case 'DSC':


                                $propertyPromotionSelected = collect($propertyPromotionGroup[$promotionType])
                                    ->sortByDesc('amount')
                                    ->first();

                                if ($propertyPromotionSelected) {
                                    $propertyPromotionData[$promotionType] = [
                                        'type' => 'PER',
                                        'value' => $propertyPromotionSelected['amount'],
                                        'is_mobile' => $propertyPromotionSelected['is_mobile'],
                                    ];
                                }


                                break;

                        }

                    }

                }

                //dd($propertyPromotionGroup);

                $promotionAvailableData['promotion'] = $propertyPromotionData;


            }


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

        } 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']);

    }


}

