<?php

namespace App\Core\Service;

use App\Core\Repository\Offer\OfferRepository;
use App\Core\Validator\Offer\OfferCreateValidator;
use App\Core\Service\OfferRoomMappingService;
use App\Core\Service\OfferImportantNotesService;
use App\Core\Service\OfferFactMappingService;
use App\Core\Service\OfferContactMappingService;
use App\Core\Service\OfferPhotoMappingService;
use App\Core\Service\OfferCancellationPolicyService;
use App\Core\Service\OfferAccommodationMappingService;
use App\Core\Service\OfferPriceService;
use App\Core\Validator\Offer\OfferUpdateValidator;
use App\Core\Validator\Offer\OfferStatusValidator;
use App\Core\Service\PropertyRoomService;
use App\Core\Repository\OfferConfirmType\OfferConfirmTypeRepository;

use App;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Exception;
use App\Exceptions\ApiErrorException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Config;
use Carbon\Carbon;


class OfferService
{

    private $offerRepository;
    private $offerCreateValidator;
    private $offerFactMappingService;
    private $offerContactMappingService;
    private $offerRoomMappingService;
    private $offerImportantNotesService;
    private $offerPhotoMappingService;
    private $offerCancellationPolicyService;
    private $offerAccommodationMappingService;
    private $offerPriceService;
    private $offerUpdateValidator;
    private $offerStatusValidator;
    private $propertyRoomService;


    public function __construct(

        OfferRepository $offerRepository,
        OfferConfirmTypeRepository $offerConfirmTypeRepository,
        OfferCreateValidator $offerCreateValidator,
        OfferFactMappingService $offerFactMappingService,
        OfferContactMappingService $offerContactMappingService,
        OfferRoomMappingService $offerRoomMappingService,
        OfferImportantNotesService $offerImportantNotesService,
        OfferPhotoMappingService $offerPhotoMappingService,
        OfferCancellationPolicyService $offerCancellationPolicyService,
        OfferAccommodationMappingService $offerAccommodationMappingService,
        OfferPriceService $offerPriceService,
        OfferUpdateValidator $offerUpdateValidator,
        PropertyRoomService $propertyRoomService,
        OfferStatusValidator $offerStatusValidator

    )
    {
        $this->offerRepository = $offerRepository;
        $this->offerConfirmTypeRepository = $offerConfirmTypeRepository;
        $this->offerCreateValidator = $offerCreateValidator;
        $this->offerFactMappingService = $offerFactMappingService;
        $this->offerContactMappingService = $offerContactMappingService;
        $this->offerRoomMappingService = $offerRoomMappingService;
        $this->offerImportantNotesService = $offerImportantNotesService;
        $this->offerPhotoMappingService = $offerPhotoMappingService;
        $this->offerCancellationPolicyService = $offerCancellationPolicyService;
        $this->offerAccommodationMappingService = $offerAccommodationMappingService;
        $this->offerPriceService = $offerPriceService;
        $this->offerUpdateValidator = $offerUpdateValidator;
        $this->offerStatusValidator = $offerStatusValidator;
        $this->propertyRoomService = $propertyRoomService;

    }

    public function create($param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $validationResult = $this->offerCreateValidator->validate($param);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $insertData =
                [
                    "property_id" => fillOnUndefined($param, "property_id"),
                    "ticket_code" => $this->generateTicket(6),
                    "offer_code" => generateRandomString(16),
                    "title" => fillOnUndefined($param, "title"),
                    "email" => fillOnUndefined($param, "email"),
                    "expire_date" => fillOnUndefined($param, "expire_date"),
                    "confirm_type" => fillOnUndefined($param, "confirm_type", 'INS'),
                    "language" => fillOnUndefined($param, "language"),
                    "currency" => fillOnUndefined($param, "currency"),
                    "total" => fillOnUndefined($param, "total", 0),
                    "payment_type_id" => fillOnUndefined($param, "payment_type_id"),
                    "payment_type_mapping_id" => fillOnUndefined($param, "payment_type_mapping_id"),
                    "status" => fillOnUndefined($param, "status", 1),
                    "accept_status" => fillOnUndefined($param, "accept_status", 2),
                    "created_by" => fillOnUndefined($param, "created_by"),
                    "updated_by" => fillOnUndefined($param, "updated_by"),
                    "created_at" => time(),
                    "updated_at" => time(),
                ];

            $userCreateResult = $this->offerRepository->create($insertData);
            if ($userCreateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $userData = $userCreateResult["data"];
            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } 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 output($response);
    }

    public function select($param = [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $data = $this->offerRepository->findByCriteria($param, $column);

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

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

        return output($response);
    }

    public function selectOfferConfirmType($param = [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $data = $this->offerConfirmTypeRepository->findByCriteria($param, $column);

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

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

        return output($response);
    }

    public function update($id, $param = [])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $updateResult = $this->offerRepository->update($id, $param);
            if ($updateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $updateData = $updateResult["data"];
            $response = [
                'status' => true,
                'data' => $updateData,
            ];

        } 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 output($response);
    }

    public function updateOrCreate($criteria = [], $saveData = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $data = $this->offerRepository->updateOrCreate($criteria, $saveData);
            if ($data['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $response = [
                'status' => true,
                'data' => $data,
            ];

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

        return output($response);


    }


    public function addNewOffer($param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            DB::beginTransaction();

            $offerData =
                [
                    "property_id" => fillOnUndefined($param, "property_id"),
                    "title" => fillOnUndefined($param, "title"),
                    "email" => fillOnUndefined($param, "email"),
                    "expire_date" => fillOnUndefined($param, "expire_date"),
                    "confirm_type" => fillOnUndefined($param, "confirm_type"),
                    "language" => fillOnUndefined($param, "language"),
                    "currency" => fillOnUndefined($param, "currency"),
                    "total" => fillOnUndefined($param, "total"),
                    "payment_type_id" => fillOnUndefined($param, "payment_type_id"),
                    "payment_type_mapping_id" => fillOnUndefined($param, "payment_type_mapping_id"),
                    "status" => fillOnUndefined($param, "status", 1),
                    "accept_status" => 3, //Pending Customer Confirm
                    "created_by" => fillOnUndefined($param, "user_id"),
                    "updated_by" => fillOnUndefined($param, "user_id"),

                ];

            $offerCreateResult = $this->create($offerData);

            if ($offerCreateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $offerData = $offerCreateResult["data"];

            $offerData = [
                'offer_id' => $offerData['id'],
                'property_id' => fillOnUndefined($param, "property_id"),
                'user_id' => fillOnUndefined($param, "user_id"),
                'fact_mapping' => fillOnUndefined($param, 'fact_mapping', []),
                'contact_mapping' => fillOnUndefined($param, 'contact_mapping', []),
                'room_mapping' => fillOnUndefined($param, 'room_mapping', []),
                'important_notes' => fillOnUndefined($param, 'important_notes', []),
                'photo_mapping' => fillOnUndefined($param, 'photo_mapping', []),
                'cover_photos' => fillOnUndefined($param, 'cover_photos', []),
                'has_cancellation_policy' => fillOnUndefined($param, 'has_cancellation_policy', false),
                'cancellation_policy' => fillOnUndefined($param, 'cancellation_policy', []),
                'accommodation_mapping' => fillOnUndefined($param, 'accommodation_mapping', []),
                'hotel_features_mapping' => fillOnUndefined($param, 'hotel_features_mapping', []),
            ];
            $addOfferFactResponse = $this->offerFactMappingService->insertNewOfferFacts($offerData);
            if ($addOfferFactResponse['status'] != 'success') {
                throw new ApiErrorException($addOfferFactResponse['message']);
            }

            $offerContactResponse = $this->offerContactMappingService->insertContactMapping($offerData);
            if ($offerContactResponse['status'] != 'success') {
                throw new ApiErrorException($offerContactResponse['message']);
            }

            $offerRoomResponse = $this->offerRoomMappingService->insertRoomMapping($offerData);
            if ($offerRoomResponse['status'] != 'success') {
                throw new ApiErrorException($offerRoomResponse['message']);
            }

            $offerRoomResponse = $this->offerAccommodationMappingService->insertAccommodationMapping($offerData);
            if ($offerRoomResponse['status'] != 'success') {
                throw new ApiErrorException($offerRoomResponse['message']);
            }


            $offerImportantNotesResponse = $this->offerImportantNotesService->insertImportantNotes($offerData, []);
            if ($offerImportantNotesResponse['status'] != 'success') {
                throw new ApiErrorException($offerImportantNotesResponse['message']);
            }

            $offerPhotoMapping = $this->offerPhotoMappingService->insertPhotoMapping($offerData);
            if ($offerPhotoMapping['status'] != 'success') {
                throw new ApiErrorException($offerPhotoMapping['message']);
            }

            $offerCoverPhotoMapping = $this->offerPhotoMappingService->insertCoverPhotoMapping($offerData);
            if ($offerCoverPhotoMapping['status'] != 'success') {
                throw new ApiErrorException($offerCoverPhotoMapping['message']);
            }

            $offerCancellationPolicy = $this->offerCancellationPolicyService->insertCancellationPolicy($offerData, []);
            if ($offerCancellationPolicy['status'] != 'success') {
                throw new ApiErrorException($offerCancellationPolicy['message']);
            }


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

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

        return output($response);
    }

    public function getPriceList($param = [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $offerRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $param['offer_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $param['property_id']],
                ],
                'with' => ['offerAccommodationMapping.propertyAccommodation', 'offerPrice', 'offerRoomMapping.propertyRoom'],
                'firstRow' => 1
            ];
            $columns = [
                "id",
                "property_id",
                "ticket_code",
                "offer_code",
                "title",
                "description",
                "expire_date",
                "language",
                "currency",
                "total",
                "payment_type_id",
                "accept_status",
                "status"
            ];

            $offerData = $this->offerRepository->findByCriteria($offerRequest, $columns);
            if (!$offerData) {
                throw new ApiErrorException('Offer data not found');
            }


            $offerAccommodationMapping = collect($offerData['offer_accommodation_mapping'])->map(function ($value) {
                return $value['property_accommodation'];
            })->values()->all();

            $offerPrice = $offerData['offer_price'];
            $offerRoomMapping = collect($offerData['offer_room_mapping'])->map(function ($value) {
                return $value['property_room'];
            })->values()->all();

            $responseOfferData = [

                "id" => $offerData['id'],
                "property_id" => $offerData['property_id'],
                "ticket_code" => $offerData['ticket_code'],
                "offer_code" => $offerData['offer_code'],
                "title" => $offerData['title'],
                "expire_date" => $offerData['expire_date'],
                "language" => $offerData['language'],
                "currency" => $offerData['currency'],
                "total" => $offerData['total'],
                "accept_status" => $offerData['accept_status'],
                "status" => $offerData['status'],

            ];


            $priceDataStartDate = collect($offerPrice)->keyBy('date')->keys()->min();
            $startDate = Carbon::parse($priceDataStartDate);
            $endDate = collect($offerPrice)->keyBy('date')->keys()->max();

            $diffInDays = collect($offerPrice)->count() > 0 ? $startDate->diffInDays(Carbon::parse($endDate)) : -1;

            $roomArray = [];
            $priceArray = [];
            foreach ($offerPrice as $price) {

                $priceArray[$offerData['id'] . "|" . $price['property_room_id'] . "|" . $price['property_accommodation_id'] . "|" . $price['date']] = $price;
            }

            foreach ($offerRoomMapping as $room) {
                $roomItem = [
                    'room_id' => $room['id'],
                    'room_name' => $room['name'],
                ];
                $accommodationArray = [];
                foreach ($offerAccommodationMapping as $offerAccommodation) {

                    $accommodationItem = [
                        'id' => $offerAccommodation['id'],
                        'name' => $offerAccommodation['name'],
                        'language_key' => $offerAccommodation['language_key'],
                    ];
                    $roomPrice = [];
                    $startDate = Carbon::parse($priceDataStartDate);
                    $numberOfRooms = null;
                    for ($i = 0; $i <= $diffInDays; $i++) {
                        $checkKey = $offerData['id'] . "|" . $room['id'] . "|" . $offerAccommodation['id'] . "|" . $startDate->format('Y-m-d');
                        if (isset($priceArray[$checkKey])) {
                            $roomPrice[$startDate->format('Y-m-d')] = $priceArray[$checkKey]['amount'];
                            $numberOfRooms = $priceArray[$checkKey]['number_of_rooms'];
                        } else {
                            $roomPrice[$startDate->format('Y-m-d')] = null;
                        }
                        $startDate = $startDate->addDay();
                    }
                    $accommodationItem['number_of_rooms'] = $numberOfRooms;
                    $accommodationItem['price'] = $roomPrice;
                    $accommodationArray[] = $accommodationItem;
                }
                $roomItem['accommodation'] = $accommodationArray;
                $roomArray[] = $roomItem;
            }

            $responseOfferData['room_price'] = $roomArray;
            $responseOfferData['start_date'] = $priceDataStartDate;
            $responseOfferData['end_Date'] = $endDate;

            $response = [
                'status' => true,
                'data' => $responseOfferData,
            ];

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

        return output($response);
    }

    public function getPrice($param = [])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $offerRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $param['offer_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $param['property_id']],
                ],
                'with' => [
                    'offerAccommodationMapping.propertyAccommodation',
                    'offerPrice',
                    'offerRoomMapping.propertyRoom.propertyRoomType',
                    'offerRoomMapping.propertyRoom.propertyRoomFactMapping.propertyFact',
                    'offerRoomMapping.propertyRoom.PropertyRoomPhotoMapping.propertyRoomPhoto',
                    'offerRoomMapping.propertyRoom.propertyRoomViewMapping.PropertyRoomViewType'
                ],
                'firstRow' => 1
            ];
            $columns = [
                "id",
                "property_id",
                "title",
                "description",
                "expire_date",
                "language",
                "currency",
                "total",
                "payment_type_id",
                "accept_status",
                "status"
            ];

            $offerData = $this->offerRepository->findByCriteria($offerRequest, $columns);
            if (!$offerData) {
                throw new ApiErrorException('Offer data not found');
            }

            if(empty($offerData['offer_price'])) {
                throw new ApiErrorException('Offer prices not include');
            }

            $offerAccommodationMapping = collect($offerData['offer_accommodation_mapping'])->map(function ($value) {
                return $value['property_accommodation'];
            })->values()->all();

            $offerPrice = $offerData['offer_price'];
            $offerRoomMapping = collect($offerData['offer_room_mapping'])->map(function ($value) {
                return $value['property_room'];
            })->values()->all();


            $roomArray = [];

            $offerPrice = collect($offerPrice);

            $sumAmount = 0;
            $sumTotalAmount = 0;
            foreach ($offerRoomMapping as $room) {
                $accommodationArray = [];

                $room['property_room_type'] = collect($room['property_room_type'])->first();
                $room['exclude_occupancy'] = json_decode($room['exclude_occupancy']);


                $occupancyParams = [
                    'max_adult' => $room['max_adult'],
                    'max_child' => $room['max_child'],
                    'max_occupancy' => $room['max_occupancy'],
                    'exclude_occupancy' => $room['exclude_occupancy'],
                ];
                $room['include_occupancy'] = $this->propertyRoomService->roomIncludeOccupancies($occupancyParams);


                $roomFact = collect($room['property_room_fact_mapping'])->map(function ($value) use ($param) {
                    return collect($value['property_fact']);
                })->values()->all();

                $room['room_fact'] = $roomFact;

                $roomViews = collect($room['property_room_view_mapping'])->map(function ($value) use ($param) {
                    return collect($value['property_room_view_type']);
                })->values()->all();

                $room['room_views'] = $roomViews;

                $offerRoomMapping = collect($room['property_room_photo_mapping'])->map(function ($value) use ($param) {

                    $photoUrlFilePath = Config::get('app.fileSystemDriver') . '/property-photos/' . $param['property_id'] . '/' . $value['property_room_photo']['photo_name'] . '_1024x768.' . $value['property_room_photo']['file_ext'];
                    $photoUrlThumbFilePath = Config::get('app.fileSystemDriver') . '/property-photos/' . $param['property_id'] . '/' . $value['property_room_photo']['photo_name'] . '_200x200.' . $value['property_room_photo']['file_ext'];

                    if (File::exists($photoUrlFilePath)) {
                        $photoUrlFilePath = Config::get('app.imageUrl') . '/property-photos/' . $param['property_id'] . '/' . $value['property_room_photo']['photo_name'] . '_1024x768.' . $value['property_room_photo']['file_ext'];
                    } else {
                        $photoUrlFilePath = Config::get('app.imageUrl') . '/property-photos/' . $param['property_id'] . '/' . $value['property_room_photo']['photo_name'] . '_medium.' . $value['property_room_photo']['file_ext'];
                    }
                    if (File::exists($photoUrlThumbFilePath)) {
                        $photoUrlThumbFilePath = Config::get('app.imageUrl') . '/property-photos/' . $param['property_id'] . '/' . $value['property_room_photo']['photo_name'] . '_200x200.' . $value['property_room_photo']['file_ext'];
                    } else {
                        $photoUrlThumbFilePath = Config::get('app.imageUrl') . '/property-photos/' . $param['property_id'] . '/' . $value['property_room_photo']['photo_name'] . '_thumbnail.' . $value['property_room_photo']['file_ext'];
                    }

                    $original = Config::get('app.imageUrl') . '/property-photos/' . $param['property_id'] . '/' . $value['property_room_photo']['photo_name'] . '.' . $value['property_room_photo']['file_ext'];
                    return [
                        'default' => $original,
                        'fixed' => $photoUrlFilePath,
                        'thumb' => $photoUrlThumbFilePath
                    ];
                })->values()->all();
                $room['room_photos'] = $offerRoomMapping;


                unset($room['property_room_fact_mapping']);
                unset($room['property_room_photo_mapping']);
                unset($room['property_room_view_mapping']);


                $roomItem = $room;

                foreach ($offerAccommodationMapping as $offerAccommodation) {

                    $accommodationItem = $offerAccommodation;

                    $amount = $offerPrice->where('property_room_id', '=', $room['id'])
                        ->where('property_accommodation_id', '=', $offerAccommodation['id'])
                        ->sum('amount');

                    $totalAmount = $offerPrice->where('property_room_id', '=', $room['id'])
                        ->where('property_accommodation_id', '=', $offerAccommodation['id'])
                        ->sum('total_amount');

                    $numberOfRooms = $offerPrice->where('property_room_id', '=', $room['id'])
                        ->where('property_accommodation_id', '=', $offerAccommodation['id'])->sortBy('date')
                        ->pluck('number_of_rooms')->first();

                    $roomAccommodationPrices = $offerPrice->where('property_room_id', '=', $room['id'])
                        ->where('property_accommodation_id', '=', $offerAccommodation['id'])->sortBy('date')
                        ->toArray();


                    $accommodationItem['price_daily'] = [];

                    if ($roomAccommodationPrices) {

                        foreach ($roomAccommodationPrices as $dailyPrice) {
                            $accommodationItem['price_daily'][] = [
                                'date' => $dailyPrice['date'],
                                'date_formatted' => Carbon::parse($dailyPrice['date'])->format('d/m/Y'),
                                'amount' => moneyDoubleFormat($dailyPrice['amount']),
                                'number_of_rooms' => $dailyPrice['number_of_rooms'],
                                'total' => moneyDoubleFormat($dailyPrice['total_amount']),
                                //'currency' => $dailyPrice['currency'],
                            ];
                        }


                        $sumAmount += $amount;
                        $sumTotalAmount += $totalAmount;
                        $accommodationItem['price'] = [
                            'amount' => moneyDoubleFormat($amount),
                            'total_amount' => moneyDoubleFormat($totalAmount),
                            'number_of_rooms' => $numberOfRooms
                        ];

                        $accommodationArray[] = $accommodationItem;
                    }
                }
                if ($accommodationArray) {
                    $roomItem['accommodation'] = $accommodationArray;
                    $roomArray[] = $roomItem;
                }
            }

            $response = [
                'status' => true,
                'data' => [
                    'room_list' => $roomArray,
                    'amount' => moneyDoubleFormat($sumAmount),
                    'total_amount' => moneyDoubleFormat($sumTotalAmount)

                ],
            ];

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

        return output($response);
    }

    public function storePriceList($param = [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            DB::beginTransaction();

            $offerData =
                [
                    "check_in" => fillOnUndefined($param, "start_date"),
                    "check_out" => fillOnUndefined($param, "end_date")
                ];

            $offerCheckInCheckOutUpdate = $this->update($param["offer_id"], $offerData);

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

            $checkOfferApprovedParam = [
                'offer_id' => $param['offer_id']
            ];
            $checkOfferApprovedStatus = $this->checkOfferApprovedStatus($checkOfferApprovedParam);
            if ($checkOfferApprovedStatus['status'] != 'success') {
                throw new ApiErrorException($checkOfferApprovedStatus['message']);
            }

            $offerRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $param['offer_id']],
                ],
                'with' => ['offerPrice'],
                'firstRow' => 1
            ];
            $columns = [
                "id",
                "property_id",
                "title",
                "description",
                "expire_date",
                "language",
                "currency",
                "total",
                "payment_type_id",
            ];

            $offerData = $this->offerRepository->findByCriteria($offerRequest, $columns);
            if (!$offerData) {
                throw new ApiErrorException('Offer data not found');
            }


            $oldOfferPrices = $offerData['offer_price'];
            $newRoomPrices = $param['room_price'];
            $checkTotalAmount = 0;

            $insertPrices = [];
            foreach ($newRoomPrices as $room) {
                foreach ($room['accommodation'] as $accommodation) {
                    if (
                        isset($accommodation['number_of_rooms']) &&
                        !empty($accommodation['number_of_rooms']) &&
                        $accommodation['number_of_rooms'] !== "" &&
                        is_numeric($accommodation['number_of_rooms'])
                    ) {
                        foreach ($accommodation['price'] as $date => $price) {
                            if (is_numeric($price)) {
                                $totalAmount = $price * $accommodation['number_of_rooms'];
                                $insertItem = [
                                    'offer_id' => $offerData['id'],
                                    'date' => $date,
                                    'property_room_id' => $room['room_id'],
                                    'property_accommodation_id' => $accommodation['id'],
                                    'number_of_rooms' => $accommodation['number_of_rooms'],
                                    'currency' => $offerData['currency'],
                                    'amount' => $price,
                                    'total_amount' => $totalAmount,
                                    'status' => fillOnUndefined($param, "status", 1),
                                    'created_by' => fillOnUndefined($param, "user_id", 0),
                                    'updated_by' => fillOnUndefined($param, "user_id", 0),
                                    'created_at' => Carbon::now()->timestamp,
                                    'updated_at' => Carbon::now()->timestamp,
                                ];
                                $checkTotalAmount += $price;
                                $insertPrices[] = $insertItem;
                            }
                        }
                    } else {
                        throw new ApiErrorException(lang('Room (' . $room['room_name'] . '-' . $accommodation['name'] . ') number of rooms data not valid', []));
                    }
                }
            }

            $deleteThis = collect($oldOfferPrices)->keyBy('id')->keys()->toArray();

            if ($deleteThis) {
                $deleteRoomRatePrices = $this->offerPriceService->destroy($deleteThis);
                if ($deleteRoomRatePrices['status'] != 'success') {
                    throw new ApiErrorException($deleteRoomRatePrices['message']);
                }
            }

            $insertRoomRatePrices = $this->offerPriceService->insert($insertPrices);
            if ($insertRoomRatePrices['status'] != 'success') {
                throw new ApiErrorException($insertRoomRatePrices['message']);
            }

            if ($checkTotalAmount <= 0) {
                throw new ApiErrorException('Total amount cannot be zero. Please check your number of rooms and rates.');
            }


            $offerPriceParams = [
                "offer_id" => fillOnUndefined($param, "offer_id"),
                "property_id" => fillOnUndefined($param, "property_id"),
                "user_id" => fillOnUndefined($param, "user_id"),
            ];

            $offerPriceTotal = $this->offerPriceTotalUpdate($offerPriceParams);
            if ($offerPriceTotal['status'] != 'success') {
                throw new ApiErrorException($offerPriceTotal['message']);
            }

            $response = [
                'status' => true,
                'data' => null,
            ];
            DB::commit();

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

        return output($response);
    }

    private function offerPriceTotalUpdate($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $checkOfferApprovedParam = [
                'offer_id' => $params['offer_id']
            ];
            $checkOfferApprovedStatus = $this->checkOfferApprovedStatus($checkOfferApprovedParam);
            if ($checkOfferApprovedStatus['status'] != 'success') {
                throw new ApiErrorException($checkOfferApprovedStatus['message']);
            }

            $offerPriceTotalRequest = [
                'criteria' => [
                    ['field' => 'offer_id', 'condition' => '=', 'value' => $params['offer_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],

            ];
            $offerPriceTotal = $this->offerPriceService->select($offerPriceTotalRequest);
            if ($offerPriceTotal['status'] != 'success') {
                throw new ApiErrorException($offerPriceTotal['message']);
            }

            $totalPrice = collect($offerPriceTotal['data'])->sum(['total_amount']);

            $offerStatusData =
                [
                    "total" => $totalPrice,
                    "updated_by" => fillOnUndefined($params, "user_id")

                ];

            $offerStatusResult = $this->update($params, $offerStatusData);

            if ($offerStatusResult['status'] != 'success') {
                throw new ApiErrorException(lang('Offer Price Total data is not updated.'));
            }

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

        } 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 output($response);

    }


    public function findOffer($params)
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {
            $offerRequest = [
                'criteria' => [
                    //   ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $params['offer_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => [
                    'offerAccommodationMapping.propertyAccommodation',
                    'offerCancellationPolicy', 'offerContactMapping.propertyExecutive.executiveType',
                    'offerFactMapping.propertyFact', 'offerImportantNotes', 'offerPhotoMapping.propertyPhoto',
                    'offerPrice', 'offerRoomMapping.propertyRoom', 'offerAcceptStatus',
                    'offerLanguage', 'createUser', 'property.propertyBrand'],
                'firstRow' => 1
            ];
            $columns = [
                "id",
                "email",
                "property_id",
                "ticket_code",
                "offer_code",
                "title",
                "description",
                "expire_date",
                "language",
                "currency",
                "total",
                "status",
                "payment_type_id",
                "payment_type_mapping_id",
                "status",
                "accept_status",
                "confirm_type",
                "check_in",
                "check_out",
                "created_by"
            ];

            $offerData = $this->offerRepository->findByCriteria($offerRequest, $columns);
            if (!$offerData) {
                throw new ApiErrorException('Offer data not found');
            }

            $offerAccommodationMapping = collect($offerData['offer_accommodation_mapping'])->map(function ($value) {
                return $value['property_accommodation'];
            })->values()->all();

            $offerCancellationPolicy = collect($offerData['offer_cancellation_policy'])->map(function ($value) {
                return $value;
            })->values()->all();

            $offerContactMapping = collect($offerData['offer_contact_mapping'])->map(function ($value) use ($offerData) {
                $response = $value['property_executive'];

                $response['executive_type'] = $response['executive_type']['language_key'];
                return $response;
            })->values()->all();

            $offerFactMapping = collect($offerData['offer_fact_mapping'])->map(function ($value) {
                return $value['property_fact'];
            })->values()->all();

            $offerImportantNotes = $offerData['offer_important_notes'];
            $offerPhotoMapping = collect($offerData['offer_photo_mapping'])
                ->where('is_cover', '=', 0)
                ->map(function ($value) use ($params) {

                    $photoUrlFilePath = Config::get('app.fileSystemDriver') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_1024x768.' . $value['property_photo']['file_ext'];
                    $photoUrlThumbFilePath = Config::get('app.fileSystemDriver') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_200x200.' . $value['property_photo']['file_ext'];

                    if (File::exists($photoUrlFilePath)) {
                        $photoUrlFilePath = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_1024x768.' . $value['property_photo']['file_ext'];
                    } else {
                        $photoUrlFilePath = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_medium.' . $value['property_photo']['file_ext'];
                    }

                    if (File::exists($photoUrlThumbFilePath)) {
                        $photoUrlThumbFilePath = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_200x200.' . $value['property_photo']['file_ext'];
                    } else {
                        $photoUrlThumbFilePath = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_thumbnail.' . $value['property_photo']['file_ext'];
                    }
                    $value['property_photo']['image_url'] = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '.' . $value['property_photo']['file_ext'];
                    $value['property_photo']['thumb_image_url'] = $photoUrlThumbFilePath;
                    $value['property_photo']['medium_image_url'] = $photoUrlFilePath;
                    return $value['property_photo'];
                })->values()->all();


            $offerCoverPhotoMapping = collect($offerData['offer_photo_mapping'])
                ->where('is_cover', '=', 1)
                ->map(function ($value) use ($params) {

                    $photoUrlFilePath = Config::get('app.fileSystemDriver') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_1024x768.' . $value['property_photo']['file_ext'];
                    $photoUrlThumbFilePath = Config::get('app.fileSystemDriver') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_200x200.' . $value['property_photo']['file_ext'];

                    if (File::exists($photoUrlFilePath)) {
                        $photoUrlFilePath = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_1024x768.' . $value['property_photo']['file_ext'];
                    } else {
                        $photoUrlFilePath = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_medium.' . $value['property_photo']['file_ext'];
                    }

                    if (File::exists($photoUrlThumbFilePath)) {
                        $photoUrlThumbFilePath = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_200x200.' . $value['property_photo']['file_ext'];
                    } else {
                        $photoUrlThumbFilePath = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '_thumbnail.' . $value['property_photo']['file_ext'];
                    }
                    $value['property_photo']['image_url'] = Config::get('app.imageUrl') . '/property-photos/' . $params['property_id'] . '/' . $value['property_photo']['photo_name'] . '.' . $value['property_photo']['file_ext'];
                    $value['property_photo']['thumb_image_url'] = $photoUrlThumbFilePath;
                    $value['property_photo']['medium_image_url'] = $photoUrlFilePath;
                    return $value['property_photo'];
                })->values()->all();


            $offerPrice = $offerData['offer_price'];
            $offerRoomMapping = collect($offerData['offer_room_mapping'])->map(function ($value) {
                return $value['property_room'];
            })->values()->all();

            $responseOfferData = [

                "id" => $offerData['id'],
                "email" => $offerData['email'],
                "property_id" => $offerData['property_id'],
                "ticket_code" => $offerData['ticket_code'],
                "offer_code" => $offerData['offer_code'],
                "title" => $offerData['title'],
                "description" => $offerData['description'],
                "expire_date" => $offerData['expire_date'],
                "check_in" => $offerData['check_in'],
                "check_out" => $offerData['check_out'],
                "language" => $offerData['language'],
                "currency" => $offerData['currency'],
                "total" => $offerData['total'],
                "status" => $offerData['status'],
                "payment_type_id" => $offerData['payment_type_id'],
                "payment_type_mapping_id" => $offerData['payment_type_mapping_id'],
                "accept_status" => $offerData['accept_status'],
                "confirm_type" => $offerData['confirm_type'],
                'offer_accommodation_mapping' => $offerAccommodationMapping,
                'offer_has_cancellation_policy' => count($offerCancellationPolicy) > 0 ? true : false,
                'offer_cancellation_policy' => $offerCancellationPolicy,
                'offer_contact_mapping' => $offerContactMapping,
                'offer_fact_mapping' => $offerFactMapping,
                'offer_important_notes' => $offerImportantNotes,
                'offer_photo_mapping' => $offerPhotoMapping,
                'offer_cover_photos' => $offerCoverPhotoMapping,
                'offer_price' => $offerPrice,
                'offer_room_mapping' => $offerRoomMapping,
                'offer_language' => $offerData['offer_language'],
                'offer_accept_status' => $offerData['offer_accept_status'],
                'create_user' => $offerData['create_user'],
                'property' => $offerData['property'],
                'property_brand' => $offerData['property']['property_brand'],
            ];

            $response = [
                'status' => true,
                'data' => $responseOfferData,
            ];

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

        return output($response);

    }

    public function editFormCheckValues($params)
    {

        $responseData = $params;
        $offer = fillOnUndefined($params, 'get_offer', []);

        $offerContactMapping = collect($offer['offer_contact_mapping'])->keyBy('id')->keys()->all();
        $offerPhotoMapping = collect($offer['offer_photo_mapping'])->keyBy('id')->keys()->all();
        $offerCoverPhotoMapping = collect($offer['offer_cover_photos'])->keyBy('id')->keys()->all();
        $offerRoomMapping = collect($offer['offer_room_mapping'])->keyBy('id')->keys()->all();

        $responseData['executives'] = collect($params['executives'])->map(function ($value) use ($offerContactMapping) {
            $value['is_selected'] = array_search($value['id'], $offerContactMapping) > -1 ? true : false;
            return $value;
        })->values()->all();

        $responseData['photos'] = collect($params['photos'])->map(function ($value) use ($offerPhotoMapping, $offerCoverPhotoMapping) {
            $value['is_selected'] = array_search($value['id'], $offerPhotoMapping) > -1 ? true : false;
            $value['is_cover'] = array_search($value['id'], $offerCoverPhotoMapping) > -1 ? true : false;

            return $value;
        })->values()->all();

        $responseData['property_rooms'] = collect($params['property_rooms'])->map(function ($value) use ($offerRoomMapping) {
            $value['is_selected'] = array_search($value['id'], $offerRoomMapping) > -1 ? true : false;
            return $value;
        })->values()->all();
        unset($offer['offer_accommodation_mapping']);
        unset($offer['offer_contact_mapping']);
        unset($offer['offer_fact_mapping']);
        unset($offer['offer_photo_mapping']);
        unset($offer['offer_cover_photos']);
        unset($offer['offer_room_mapping']);
        unset($offer['offer_price']);
        $responseData['get_offer'] = $offer;
        return $responseData;
    }

    public function updateOffer($param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            DB::beginTransaction();

            $checkOfferApprovedParam = [
                'offer_id' => $param['offer_id']
            ];
            $checkOfferApprovedStatus = $this->checkOfferApprovedStatus($checkOfferApprovedParam);
            if ($checkOfferApprovedStatus['status'] != 'success') {
                throw new ApiErrorException($checkOfferApprovedStatus['message']);
            }

            $offerId = fillOnUndefined($param, "offer_id");
            $offerData = [
                "title" => fillOnUndefined($param, "title"),
                "email" => fillOnUndefined($param, "email"),
                "expire_date" => fillOnUndefined($param, "expire_date"),
                "language" => fillOnUndefined($param, "language"),
                "currency" => fillOnUndefined($param, "currency"),
                "payment_type_id" => fillOnUndefined($param, "payment_type_id"),
                "payment_type_mapping_id" => fillOnUndefined($param, "payment_type_mapping_id"),
                "updated_by" => fillOnUndefined($param, "user_id"),
            ];

            if ($checkOfferApprovedStatus['data']['confirm_type'] != $param['confirm_type']) {
                if ($checkOfferApprovedStatus['data']['accept_status'] == 3) {
                    $offerData['confirm_type'] = fillOnUndefined($param, "confirm_type");
                } else {
                    throw new ApiErrorException('Offer information cannot be updated due to approval phase.');
                }
            }

            if ($checkOfferApprovedStatus['data']['payment_type_mapping_id'] != $param['payment_type_mapping_id']) {
                if ($checkOfferApprovedStatus['data']['accept_status'] == 3) {
                    $offerData['payment_type_mapping_id'] = fillOnUndefined($param, "payment_type_mapping_id");
                } else {
                    throw new ApiErrorException('Offer information cannot be updated due to approval phase.');
                }
            }

            $validationResult = $this->offerUpdateValidator->validate($offerData);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $offerCreateResult = $this->update($offerId, $offerData);

            if ($offerCreateResult['status'] != 'success') {
                throw new ApiErrorException(lang('Offer data is not updated.'));
            }
            $offerData = $offerCreateResult["data"];


            $offerData = [
                'offer_id' => $offerData['id'],
                'user_id' => fillOnUndefined($param, "user_id"),
                'fact_mapping' => fillOnUndefined($param, 'fact_mapping', []),
                'contact_mapping' => fillOnUndefined($param, 'contact_mapping', []),
                'room_mapping' => fillOnUndefined($param, 'room_mapping', []),
                'important_notes' => fillOnUndefined($param, 'important_notes', []),
                'photo_mapping' => fillOnUndefined($param, 'photo_mapping', []),
                'cover_photos' => fillOnUndefined($param, 'cover_photos', []),
                'cancellation_policy' => fillOnUndefined($param, 'cancellation_policy', []),
                'has_cancellation_policy' => fillOnUndefined($param, 'has_cancellation_policy', false),
                'accommodation_mapping' => fillOnUndefined($param, 'accommodation_mapping', []),
                'hotel_features_mapping' => fillOnUndefined($param, 'hotel_features_mapping', []),
            ];

            $getOffer = $this->findOffer($param);

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

            $offer = $getOffer['data'];


            $offerFactMapping = collect($offer['offer_fact_mapping'])->keyBy('id')->keys()->all();
            $offerContactMapping = collect($offer['offer_contact_mapping'])->keyBy('id')->keys()->all();
            $offerPhotoMapping = collect($offer['offer_photo_mapping'])->keyBy('id')->keys()->all();
            $offerCoverPhotoMapping = collect($offer['offer_cover_photos'])->keyBy('id')->keys()->all();
            $offerRoomMapping = collect($offer['offer_room_mapping'])->keyBy('id')->keys()->all();
            $offerAccommodationMapping = collect($offer['offer_accommodation_mapping'])->keyBy('id')->keys()->all();
            $offerCancellationPolicy = collect($offer['offer_cancellation_policy'])->keyBy('id')->keys()->all();
            $offerImportantNotes = collect($offer['offer_important_notes'])->keyBy('id')->keys()->all();


            $addOfferFactResponse = $this->offerFactMappingService->updateOfferFacts($offerData, $offerFactMapping);
            if ($addOfferFactResponse['status'] != 'success') {
                throw new ApiErrorException($addOfferFactResponse['message']);
            }

            $offerContactResponse = $this->offerContactMappingService->updateContactMapping($offerData, $offerContactMapping);
            if ($offerContactResponse['status'] != 'success') {
                throw new ApiErrorException($offerContactResponse['message']);
            }

            $offerPhotoMapping = $this->offerPhotoMappingService->updatePhotoMapping($offerData, $offerPhotoMapping);
            if ($offerPhotoMapping['status'] != 'success') {
                throw new ApiErrorException($offerPhotoMapping['message']);
            }

            $offerCoverPhotoMapping = $this->offerPhotoMappingService->updateCoverPhotoMapping($offerData, $offerCoverPhotoMapping);
            if ($offerCoverPhotoMapping['status'] != 'success') {
                throw new ApiErrorException($offerCoverPhotoMapping['message']);
            }

            $offerRoomResponse = $this->offerRoomMappingService->updateRoomMapping($offerData, $offerRoomMapping);
            if ($offerRoomResponse['status'] != 'success') {
                throw new ApiErrorException($offerRoomResponse['message']);
            }

            $offerAccommodationResponse = $this->offerAccommodationMappingService->updateAccommodationMapping($offerData, $offerAccommodationMapping);
            if ($offerAccommodationResponse['status'] != 'success') {
                throw new ApiErrorException($offerAccommodationResponse['message']);
            }

            $offerImportantNotesResponse = $this->offerImportantNotesService->insertImportantNotes($offerData, $offerImportantNotes);
            if ($offerImportantNotesResponse['status'] != 'success') {
                throw new ApiErrorException($offerImportantNotesResponse['message']);
            }

            $offerCancellationPolicy = $this->offerCancellationPolicyService->insertCancellationPolicy($offerData, $offerCancellationPolicy);
            if ($offerCancellationPolicy['status'] != 'success') {
                throw new ApiErrorException($offerCancellationPolicy['message']);
            }

            $deleteThisPrices = [
                'offer_id' => $offer['id'],
                'property_room_id' => fillOnUndefined($offerRoomResponse, 'data', []),
                'property_accommodation_id' => fillOnUndefined($offerAccommodationResponse, 'data', []),

            ];

            $deleteThisOfferPrices = $this->offerPriceService->deleteThisOfferPrices($deleteThisPrices);
            if ($deleteThisOfferPrices['status'] != 'success') {
                throw new ApiErrorException($deleteThisOfferPrices['message']);
            }


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

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

        return output($response);
    }

    public function updateStatus($param = [])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $validationResult = $this->offerStatusValidator->validate($param);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $offerId = fillOnUndefined($param, "offer_id");

            $checkOfferApprovedParam = [
                'offer_id' => $offerId
            ];
            $checkOfferApprovedStatus = $this->checkOfferApprovedStatus($checkOfferApprovedParam);
            if ($checkOfferApprovedStatus['status'] != 'success') {
                throw new ApiErrorException($checkOfferApprovedStatus['message']);
            }

            $offerStatusData =
                [
                    "property_id" => fillOnUndefined($param, "property_id"),
                    "status" => fillOnUndefined($param, "status"),
                    "updated_by" => fillOnUndefined($param, "user_id")

                ];
            $offerStatusResult = $this->update($offerId, $offerStatusData);

            if ($offerStatusResult['status'] != 'success') {
                throw new ApiErrorException(lang('Offer Status data is not updated.'));
            }

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

        } 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 output($response);

    }

    public function updateAcceptStatus($param)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $offerId = fillOnUndefined($param, "offer_id");
            $offerCode = fillOnUndefined($param, "offer_code");
            $acceptStatus = fillOnUndefined($param, "accept_status", 1);

            $checkOfferApprovedParam = [
                'offer_id' => $offerId
            ];
            $checkOfferApprovedStatus = $this->checkOfferApprovedStatus($checkOfferApprovedParam);

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

            $offerRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $offerId],
                    ['field' => 'offer_code', 'condition' => '=', 'value' => $offerCode]
                ],
                'firstRow' => 1
            ];

            $offerData = $this->offerRepository->findByCriteria($offerRequest);
            if (!$offerData) {
                throw new ApiErrorException('Offer data not found');
            }

            $offerAcceptStatusData = [
                "accept_status" => $acceptStatus,
                "updated_at" => Carbon::now()->timestamp
            ];

            $offerAcceptStatusResult = $this->update($offerData['id'], $offerAcceptStatusData);

            if ($offerAcceptStatusResult['status'] != 'success') {
                throw new ApiErrorException(lang('Offer Accept Status data is not updated.'));
            }

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


        } 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 output($response);
    }

    public function checkOfferApprovedStatus($param)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $offerRequest = [
                'criteria' => [
                    //   ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => fillOnUndefined($param, "offer_id")],
                ],
                'firstRow' => 1
            ];

            $offerData = $this->offerRepository->findByCriteria($offerRequest);
            if (!$offerData) {
                throw new ApiErrorException('Update failed. Offer data not found');
            }

            if (!in_array($offerData['accept_status'], [1, 2, 3])) {
                throw new ApiErrorException('Update failed. Offer update is locked.');
            }

            $response = [
                'status' => true,
                'data' => $offerData,
            ];

        } 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 output($response);
    }

    private function generateTicket($length = 6)
    {
        $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        $checkTicketCriteria = [
            'criteria' => [
                ['field' => 'ticket_code', 'condition' => '=', 'value' => $randomString],
            ],
            'firstRow' => 1
        ];
        $checkTicket = $this->offerRepository->findByCriteria($checkTicketCriteria);
        if ($checkTicket) {
            $this->generateTicket($length);
        }
        return $randomString;
    }

    public function checkPropertyOfferPermissionAccess($param)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $offerRequest = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => fillOnUndefined($param, "offer_id")],
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($param, "property_id")],
                ],
                'firstRow' => 1
            ];

            $offerData = $this->offerRepository->findByCriteria($offerRequest,
                [
                    'id', 'property_id', 'offer_code', 'status', 'confirm_type', 'accept_status',
                    'payment_type_mapping_id', 'title', 'ticket_code', 'offer_code', 'email', 'currency', 'total',
                    'language', 'created_by'
                ]
            );

            if (!$offerData) {
                throw new ApiErrorException('Offer permission error');
            }
            $response = [
                'status' => true,
                'data' => $offerData,
            ];

        } 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 output($response);
    }


}
