<?php

namespace App\Http\Middleware;

use App\Core\Service\FindCountryCodeService;
use App\Core\Service\PropertyBookingEngineService;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Service\PropertyChannelService;
use App\Core\Service\PropertyWebService;
use App\Exceptions\ApiErrorException;
use Closure;
use Exception;
use App\Models\User;
use Firebase\JWT\JWT;
use Firebase\JWT\ExpiredException;

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

class BookingEngineTokenMiddleware
{

    private $propertyWebService;

    public function __construct(
        PropertyWebService $propertyWebService,
        PropertyChannelService $channelService,
        PropertyChannelMappingService $propertyChannelMappingService,
        PropertyBookingEngineService $propertyBookingEngineService,
        FindCountryCodeService $findCountryCodeService
    )
    {
        $this->propertyWebService = $propertyWebService;
        $this->channelService = $channelService;
        $this->propertyChannelMappingService = $propertyChannelMappingService;
        $this->propertyBookingEngineService = $propertyBookingEngineService;
        $this->findCountryCodeService = $findCountryCodeService;
    }

    public function handle($request, Closure $next, $guard = null)
    {
        $channelToken = $request->header('channelToken');
        $bookingEngineToken = $request->header('bookingEngineToken');

        if (!$channelToken) {
            return apiResponse(0, 'Token not provided.', null, 401);
        }

        $channelRequest = [
            'criteria' => [
                ['field' => 'token', 'condition' => '=', 'value' => $channelToken],
                ['field' => 'status', 'condition' => '=', 'value' => 1],
            ],
            'firstRow' => 1
        ];

        $channelCheck = $this->channelService->select($channelRequest);

        if ($channelCheck['status'] != 'success' || empty($channelCheck['data'])) {
            return apiResponse(0, 'Channel Token not found.', null, 401);
        }


        $bookingEnginePropertyId = null;
        if (in_array($channelCheck['data']['channel_category_id'], [2, 3, 7])) {

            if (is_null($bookingEngineToken)) {
                if (!in_array($channelCheck['data']['channel_category_id'], [7])) {
                    return apiResponse(0, 'Booking Engine Token not found.', null, 401);
                }
            }

            $bookingEngineRequest = [
                'criteria' => [
                    ['field' => 'token', 'condition' => '=', 'value' => $bookingEngineToken],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'firstRow' => 1
            ];

            $bookingEngineCheck = $this->propertyBookingEngineService->select($bookingEngineRequest);

            if ($bookingEngineCheck['status'] != 'success' || empty($bookingEngineCheck['data'])) {
                if (!in_array($channelCheck['data']['channel_category_id'], [7])) {
                    return apiResponse(0, 'Booking Engine Token not found.', null, 401);
                }
            }

            $bookingEnginePropertyId = isset($bookingEngineCheck['data']['property_id']) ? $bookingEngineCheck['data']['property_id'] : null;


            //channelToken Manipulation
            $params = json_decode($request->getContent(), 1);

            if (fillOnUndefined($params, 'ipAddress') && fillOnUndefined($params,'referrer') != 'google') {
                // Find Country Code with IP
                $ipResponse = $this->findCountryCodeService->findCountryWithIpAddress($params['ipAddress']);

                if ($ipResponse['status'] == 'success') {

                    $propertyChannelMappingParam = [
                        'criteria' => [
                            ['field' => 'property_id', 'condition' => '=', 'value' => $bookingEnginePropertyId],
                            ['field' => 'status', 'condition' => '=', 'value' => 1],
                        ],
                        'with' => ['channel'],
                    ];

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

                    $ipCountryCode = isset($ipResponse['data']['code']) ? $ipResponse['data']['code'] : 'tr';

                    if ($propertyChannelMapping['status'] == 'success') {

                        $propertyChannelMappingCollect = collect($propertyChannelMapping['data']);
                        $countryChannel = $propertyChannelMappingCollect
                            ->where('channel.channel_category_id', 3)
                            ->where('channel.country_code', $ipCountryCode)
                            ->where('channel.parent_id', 1)
                            ->first();

                        if (!empty($countryChannel)) {
                            $channelToken = $countryChannel['channel']['token'];
                            $channelCheck['data']['id'] = $countryChannel['channel']['id'];
                        }

                        //countryCodeGroup
                        if (empty($countryChannel)) {
                            $countryChannelGroup = $propertyChannelMappingCollect
                                ->where('channel.channel_category_id', 3)
                                ->where('channel.country_code', 'group')
                                ->where('channel.parent_id', 1)
                                ->toArray();

                            if (!empty($countryChannelGroup)) {
                                foreach ($countryChannelGroup as $country) {
                                    if (!empty($country['channel']['country_code_group'])) {
                                        if (in_array($ipCountryCode, $country['channel']['countryCodeGroupArray'])) {

                                            $channelToken = $country['channel']['token'];
                                            $channelCheck['data']['id'] = $country['channel']['id'];

                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        //countryCodeGroup

                    }

                }
                //channelToken Manipulation
            }

        }

        $request->channelId = $channelCheck['data']['id'];
        $request->channelToken = $channelToken;
        $request->bookingEngineToken = $bookingEngineToken;
        $request->bookingEnginePropertyId = $bookingEnginePropertyId;
        $request->bookingEngineChannelCategoryId = $channelCheck['data']['channel_category_id'];


        return $next($request);
    }
}
