<?php

namespace App\Classes\Modules\Bookings\ControllersLogic;

use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Bookings\Services\DeleteMultipleTransaction;
use App\Classes\Modules\Bookings\Standards\Rules\CanMergeBooking;

use App\Classes\Modules\Bookings\DataTransferObjects\BookingMergeObject;
use App\Classes\Modules\Bookings\Services\GetBookings;
use App\Classes\Modules\Bookings\Services\UpdatesBookingTransaction;
use App\Classes\Modules\Bookings\Services\DeleteMultipleBooking;

use App\Classes\Modules\Transactions\Services\FetchesTransactionDetail;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class MergeBookingLogic extends AbstractControllerLogic
{

    /**
     * @return array
     */
    protected function notification():array {
        return [
            'title' => 'Merge Booking',
            'message' => 'You have successfully merged Booking'
        ];
    }

    /** @var CanMergeBooking */
    private $canMergeBooking;

    /** @var GetBookings */
    private $getBookings;

    /** @var FetchesTransactionDetail */
    private $fetchesTransactionDetail;

    /** @var UpdatesBookingTransaction */
    private $updatesBookingTransaction;

    /** @var DeleteMultipleBooking */
    private $deletesMultipleBooking;

    /** @var DeleteMultipleTransaction */
    private $deletesMultipleTransaction;

    /**
     * MergeBookingLogic constructor.
     * @param CanMergeBooking $canMergeBooking
     * @param GetBookings $getBookings
     * @param FetchesTransactionDetail $fetchesTransactionDetail
     * @param UpdatesBookingTransaction $updatesBookingTransaction
     * @param DeleteMultipleBooking $deletesMultipleBooking
     * @param DeleteMultipleTransaction $deletesMultipleTransaction
     */
    public function __construct(CanMergeBooking $canMergeBooking, GetBookings $getBookings, FetchesTransactionDetail $fetchesTransactionDetail, UpdatesBookingTransaction $updatesBookingTransaction, DeleteMultipleBooking $deletesMultipleBooking, DeleteMultipleTransaction $deletesMultipleTransaction)
    {
        $this->canMergeBooking = $canMergeBooking;
        $this->getBookings = $getBookings;
        $this->updatesBookingTransaction = $updatesBookingTransaction;
        $this->deletesMultipleBooking = $deletesMultipleBooking;
        $this->deletesMultipleTransaction = $deletesMultipleTransaction;
        $this->fetchesTransactionDetail = $fetchesTransactionDetail;
    }


    /**
     * @param Request $request
     * @return JsonResponse
     * @throws \App\Classes\Exceptions\AccessForbiddenException
     * @throws \App\Classes\Exceptions\MalformedRequestException
     * @throws \App\Classes\Exceptions\RequestValidationException
     */
    public function logic(Request $request) : JsonResponse
    {
        $transaction_amount = null;
        $transaction_original_amount = null;

        $booking_ids_to_merge = [];
        $booking_update_values = [];

        $transaction_ids_to_merge = [];
        $transaction_update_values = [];
        $transaction_po_delete = [];

        $transaction_details_ids = [];
        $transaction_details_values = [];

        $booking_object = new BookingMergeObject($request->get('id'),$request->get('booking_ids'));

        $this->canMergeBooking->passes($booking_object);

        $booking_main = $this->getBookings->handler(['id'=> $booking_object->getId()])[0];
        $bookings_to_merge = $this->getBookings->handler(['id_in'=> $booking_object->getBookingIds()]);

        $booking_amount = $booking_main->fix_amount;
        $booking_main_transaction = $booking_main->transactions()->first();

        $transaction_amount = $booking_main_transaction->amount;
        $transaction_original_amount = $booking_main_transaction->original_amount;

        foreach($bookings_to_merge as $booking)
        {
            $booking_amount += $booking->fix_amount;
            $bookings_to_merge_transaction = $booking->transactions()->first();

            $transaction_update_values['booking_id']=$booking_main->id;
            $transaction_amount += $bookings_to_merge_transaction->amount;
            $transaction_original_amount += $bookings_to_merge_transaction->original_amount;
            $transaction_ids_to_merge[]=$bookings_to_merge_transaction->id;

            if($bookings_to_merge_transaction->type==7) {
                $transaction_po_delete[] = $bookings_to_merge_transaction->id;
            }

            $booking_ids_to_merge[]=$booking->id;

            foreach($bookings_to_merge_transaction->transactionDetails()->get() as $transaction_detail){
                $transaction_details_ids[] = $transaction_detail->id;
                $transaction_details_values['transaction_id'] = $booking_main_transaction->id;

            }
        }

        $booking_update_values['fix_amount']=$booking_amount;

        //Update all transactions
        $this->updatesBookingTransaction->execute(
            $booking_main->id,$booking_update_values,
            $transaction_ids_to_merge, $transaction_update_values,
            $transaction_details_ids, $transaction_details_values
        );

        //Soft delete merged booking
        $this->deletesMultipleBooking->execute($booking_ids_to_merge);

        //Soft delete merged transaction with status 7 (purchase order)
        if(count($transaction_po_delete)>0) {
            $this->deletesMultipleTransaction->execute($transaction_po_delete);
        }

        return $this->response();
    }
}