<?php

namespace App\Console\Commands\ChannelManager;

use App\Core\Mail\LogMail;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyMeta;
use App\Models\PropertyMetaRoomRate;
use App\Models\PropertyMetaRoomRatePrice;
use App\Models\PropertyRoomRatePrice;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class PropertyMetaRoomRatePriceService extends Command
{
    protected $signature = 'cron:propertymeta-roomrateprice-service {--property_id=}';

    protected $description = '';
    protected $mailer;

    public function __construct(
        Mailer $mailer
    )
    {
        parent::__construct();
        $this->mailer = $mailer;
    }

    public function handle()
    {

        $this->info(date('Y-m-d H:i:s') . ' : Start');


        if (!is_null($this->option('property_id'))) {
            $propertyMeta = PropertyMeta::where('status', 1)->where('property_id', $this->option('property_id'))->with('property')->orderBy('id', 'ASC')->get(['id', 'property_id', 'cancellation_policy', 'adult_policy', 'child_policy', 'promotion', 'status'])->toArray();
        } else {
            $propertyMeta = PropertyMeta::where('status', 1)->with('property')->orderBy('id', 'ASC')->get(['id', 'property_id', 'cancellation_policy', 'adult_policy', 'child_policy', 'promotion', 'status'])->toArray();
        }

        foreach ($propertyMeta as $property) {


            $this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Price Start: ' . $property['property']['name']);


            $roomRateOccupancyPriceParam = [];

            $propertyId = $property['property_id'];
            $startDate = Carbon::now()->toDateString();
            $finishDate = Carbon::parse($startDate)->addDays(360)->toDateString();

            $propertyCancellationPolicy = json_decode($property['cancellation_policy'], 1);
            $propertyAdultPolicy = json_decode($property['adult_policy'], 1);
            $propertyChildPolicy = json_decode($property['child_policy'], 1);
            $propertyPromotion = json_decode($property['promotion'], 1);

            $propertyRoomRatePrice = PropertyRoomRatePrice::where('property_id', $propertyId)
                ->where('date', '>=', $startDate)
                ->where('date', '<=', $finishDate)
                ->where('channel_id', 1)
                //->where('room_rate_mapping_id', 79)//TODO: Delete
                //->where('date', '2024-09-01')//TODO: Delete
                ->where('availability_type_id', 1)
                ->where('status', 1)
                ->get(['id', 'property_id', 'property_room_id', 'room_rate_mapping_id', 'date', 'amount', 'currency', 'min_stay', 'stop_sell']);

            $propertyRoomRatePrice = $propertyRoomRatePrice->toArray();

            $roomRateOccupancy = PropertyMetaRoomRate::where('property_id', $propertyId)->get()->toArray();

            //TODO: DEL
            //$roomRateOccupancy = collect($roomRateOccupancy)->where('occupancy_code', 'A')->toArray();

            $propertyAllPriceCounter = 0;

            $roomRateOccupancyPrice = [];
            foreach ($propertyRoomRatePrice as $perPropertyRoomRatePrice) {

                $roomRateOccupancySelected = collect($roomRateOccupancy)->where('room_rate_mapping_id', $perPropertyRoomRatePrice['room_rate_mapping_id'])->toArray();

                foreach ($roomRateOccupancySelected as $roomRateOccupancyKey => $perRoomRateOccupancy) {

                    $baseAmount = $perPropertyRoomRatePrice['amount'];

                    $roomRateOccupancyKey = $perRoomRateOccupancy['code'];

                    $affectedAmountArray = [];

                    $roomRateMappingId = $perPropertyRoomRatePrice['room_rate_mapping_id'];
                    $cancellationPolicy = isset($propertyCancellationPolicy[$roomRateMappingId]) ? $propertyCancellationPolicy[$roomRateMappingId] : [];
                    $adultPolicy = isset($propertyAdultPolicy[$roomRateMappingId]) ? $propertyAdultPolicy[$roomRateMappingId] : [];
                    $childPolicy = isset($propertyChildPolicy[$roomRateMappingId]) ? $propertyChildPolicy[$roomRateMappingId] : [];
                    $promotions = isset($propertyPromotion[$roomRateMappingId]) ? $propertyPromotion[$roomRateMappingId] : [];

                    //dd($promotions,$perPropertyRoomRatePrice,$baseAmount);


                    $perPersonAmount = $baseAmount / $perRoomRateOccupancy['included_occupancy'];

                    //Kişi bazlı fiyat hesaplamada baz fiyat dikkate alınır, daha sonra $perPersonAmount baz fiyat üzerinden alınıp çocuk hespaplanır.


                    //Adult Policy
                    $affectedAmount = 0;
                    if ($perRoomRateOccupancy['included_occupancy'] != strlen($perRoomRateOccupancy['occupancy_code'])) {
                        if (!empty($adultPolicy)) {

                            if ($perRoomRateOccupancy['included_occupancy'] > strlen($perRoomRateOccupancy['occupancy_code'])) {

                                $occupancyDifference = $perRoomRateOccupancy['included_occupancy'] - strlen($perRoomRateOccupancy['occupancy_code']);
                                $adultPolicySelected = collect($adultPolicy)
                                    ->where('adult', $occupancyDifference)
                                    ->where('adult_action_type', 'DEC')
                                    ->first();

                                if (!empty($adultPolicySelected)) {
                                    if ($adultPolicySelected['type'] == 'PER') {
                                        $affectedAmount = ($baseAmount * $adultPolicySelected['value'] / 100);
                                    } elseif ($adultPolicySelected['type'] == 'FIX') {
                                        $affectedAmount = $adultPolicySelected['value'];
                                    }

                                    $affectedAmountArray[] = $adultPolicySelected['action_type'] == 'DEC' ? ($affectedAmount * -1) : $affectedAmount;

                                }

                            }

                            if (strlen($perRoomRateOccupancy['occupancy_code']) > $perRoomRateOccupancy['included_occupancy']) {

                                $occupancyDifference = strlen($perRoomRateOccupancy['occupancy_code']) - $perRoomRateOccupancy['included_occupancy'];
                                $adultPolicySelected = collect($adultPolicy)
                                    ->where('adult', $occupancyDifference)
                                    ->where('adult_action_type', 'INC')
                                    ->first();


                                if (!empty($adultPolicySelected)) {
                                    if ($adultPolicySelected['type'] == 'PER') {
                                        $affectedAmount = ($baseAmount * $adultPolicySelected['value'] / 100);
                                    } elseif ($adultPolicySelected['type'] == 'FIX') {
                                        $affectedAmount = $adultPolicySelected['value'];
                                    }

                                    $affectedAmountArray[] = $adultPolicySelected['action_type'] == 'DEC' ? ($affectedAmount * -1) : $affectedAmount;

                                }


                            }

                        }

                    }
                    //Adult Policy

                    //Önce Oda Fiyatı Hesaplanır, Yetişkine Göre
                    $roomAmount = $baseAmount + array_sum($affectedAmountArray);


                    //Oluşan fiyata göre de iptal politikası uygulanır
                    //$cancellationPolicy
                    $affectedAmount = 0;
                    $isCancellationPolicyActive = false;
                    if (isset($cancellationPolicy[$perRoomRateOccupancy['cancellation_policy_id']])) {
                        $cancellationPolicySelected = $cancellationPolicy[$perRoomRateOccupancy['cancellation_policy_id']];

                        //dd($cancellationPolicy,$perRoomRateOccupancy,$cancellationPolicySelected,$perPropertyRoomRatePrice['date']);


                        //if ($cancellationPolicySelected['is_affected_price'] == 1) {

                        $isDateRange = $cancellationPolicySelected['is_date_range'];
                        $isDateRangeDate = Carbon::parse($perPropertyRoomRatePrice['date'])->between($cancellationPolicySelected['start_date'], $cancellationPolicySelected['finish_date']);

                        if (($isDateRange && $isDateRangeDate) || empty($isDateRange)) {

                            if ($cancellationPolicySelected['affect_price_type'] == 'PER') {
                                $affectedAmount = ($roomAmount * $cancellationPolicySelected['affect_price_value'] / 100);
                            } elseif ($cancellationPolicySelected['affect_price_type'] == 'FIX') {
                                $affectedAmount = $cancellationPolicySelected['affect_price_value'];
                            }

                            $affectedAmountArray[] = $cancellationPolicySelected['affect_price_action_type'] == 'DEC' ? ($affectedAmount * -1) : $affectedAmount;

                            $isCancellationPolicyActive = true;

                        }

                        //}

                    }
                    //$cancellationPolicy


                    //dd($perRoomRateOccupancy, $perPropertyRoomRatePrice, $cancellationPolicy);

                    $isCancellationPolicyActive = true;
                    if ($isCancellationPolicyActive) {

                        $calculatedAmount = $baseAmount + array_sum($affectedAmountArray);

                        $promotionsGrouped = collect($promotions)->groupBy('type')->toArray();

                        /**** PROMOTION START ****/
                        $totalPromotionDiscount = 0;
                        foreach ($promotionsGrouped as $promotionsGroupKey => $promotions) {

                            $promotions = collect($promotions)->sortByDesc('amount')->toArray();

                            foreach ($promotions as $promotion) {

                                if ($promotion['min_stay'] > 1) {
                                    continue;
                                }

                                if ($promotion['is_mobile']) {
                                    continue;
                                }

                                $daysArray = !empty($promotion['days']) ? json_decode($promotion['days'], 1) : [];
                                if (!in_array((Carbon::parse($perPropertyRoomRatePrice['date'])->dayOfWeek + 1), $daysArray)) {
                                    continue;
                                }

                                if ($promotion['type'] == 'PRD') {

                                    if (!Carbon::now()->startOfDay()->between(Carbon::parse($promotion['start_date'])->toDateString(), Carbon::parse($promotion['end_date'])->toDateString())) {
                                        continue;
                                    }

                                    if (!Carbon::parse($perPropertyRoomRatePrice['date'])->startOfDay()->between(Carbon::parse($promotion['reservation_start_date'])->toDateString(), Carbon::parse($promotion['reservation_end_date'])->toDateString())) {
                                        continue;
                                    }

                                    $totalPromotionDiscount += ($calculatedAmount * $promotion['amount']) / 100;

                                    break;

                                }

                                if ($promotion['type'] == 'BFD') {

                                    if (Carbon::parse($perPropertyRoomRatePrice['date'])->diffInDays(Carbon::now()->startOfDay()->toDateString()) < $promotion['day_before']) {
                                        continue;
                                    }

                                    $totalPromotionDiscount += ($calculatedAmount * $promotion['amount']) / 100;

                                    break;
                                }

                                if ($promotion['type'] == 'DSC') {
                                    $totalPromotionDiscount += ($calculatedAmount * $promotion['amount']) / 100;

                                    break;
                                }


                            }
                        }


                        $calculatedAmount = moneyDoubleFormatDecimal($calculatedAmount - $totalPromotionDiscount);
                        $calculatedAmount = $calculatedAmount > 0 ? $calculatedAmount : 0;
                        /**** PROMOTION FINISHED ****/

                        $roomRateOccupancyPriceParam[] = [
                            'property_id' => $property['property_id'],
                            'room_id' => $perRoomRateOccupancy['room_id'],
                            'room_rate_mapping_id' => $roomRateMappingId,
                            'date' => $perPropertyRoomRatePrice['date'],
                            'code' => $roomRateOccupancyKey,
                            //'title' => $perRoomRateOccupancy['title'],
                            //'baseAmount' => $perPropertyRoomRatePrice['amount'],
                            'amount' => $calculatedAmount,
                            'currency' => $perPropertyRoomRatePrice['currency'],
                            'status' => 1,
                            'created_by' => 1,
                            'updated_by' => 1,
                            'created_at' => Carbon::now()->unix(),
                            'updated_at' => Carbon::now()->unix(),
                        ];

                        $propertyAllPriceCounter++;

                    }

                }


            }


            $this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Price Finished: ' . $property['property']['name']);

            //dd(collect($roomRateOccupancyPriceParam)->sortBy('room_id')->sortBy('amount')->toArray());


            $insertRows = [];
            $updateRows = [];
            $rowChunk = 0;
            foreach ($roomRateOccupancyPriceParam as $roomRateOccupancyPrice) {

                $insertRows[$rowChunk][] = $roomRateOccupancyPrice;
                if (count($insertRows[$rowChunk]) > 1000) {
                    $rowChunk++;
                }

            }


            $this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Price to DB Start: ' . $property['property']['name']);

            DB::beginTransaction();

            PropertyMetaRoomRatePrice::where('property_id', $propertyId)->delete();

            if (!empty($insertRows)) {
                foreach ($insertRows as $insertRow) {
                    PropertyMetaRoomRatePrice::insert($insertRow);
                }
            }

            DB::commit();

            $this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Price to DB Finished: ' . $property['property']['name']);


        }


        $this->info(date('Y-m-d H:i:s') . ' : Finished');


    }
}
