<?php

namespace App\Classes\Modules\Bookings\Processors;


use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus;
use App\Classes\Modules\Transactions\Services\DeletesTransaction;
use App\Classes\Modules\Documents\Services\DeletesDocument;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionV2Processor;
use Illuminate\Support\Str;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\KVPKey;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Models\Transaction;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;

class RegenerateInvoiceBookingV2Processor
{
    /** @var DeletesTransaction */
    private $deletesTransaction;

    /** @var UpdatesBookingStatus */
    private $updatesBookingStatus;

    /** @var DeletesDocument */
    private $deletesDocument;

    /** @var CreateInvoiceTransactionV2Processor */
    private $createInvoiceTransactionProcessor;

    /**
     * RegenerateInvoiceBookingV2Processor constructor.
     * @param DeletesTransaction $deletesTransaction
     * @param UpdatesBookingStatus $updatesBookingStatus
     * @param DeletesDocument $deletesDocument
     * @param CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor
     */
    public function __construct(
        DeletesTransaction $deletesTransaction,
        UpdatesBookingStatus $updatesBookingStatus,
        DeletesDocument $deletesDocument,
        CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor
    ) {
        $this->deletesTransaction = $deletesTransaction;
        $this->updatesBookingStatus = $updatesBookingStatus;
        $this->deletesDocument = $deletesDocument;
        $this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor;
    }

    public function execute(Booking $booking,
        bool $eInvoiceWithNormalInvoiceTemplate = false,
        bool $eInvoiceWithRefund = false,
        bool $eInvoiceTry = false ////cief todo: 151 - getting ready to get rid of eInvoiceTry as a parameter
    )
    {
        $bookingOriginalStatus = $booking->status;

        // Log::info('E-invoice flags', [
        //     'eInvoiceWithNormalInvoiceTemplate' => $eInvoiceWithNormalInvoiceTemplate,
        //     'eInvoiceWithRefund' => $eInvoiceWithRefund,
        //     'eInvoiceTry' => $eInvoiceTry,
        // ]);

        // if($eInvoiceTry){
        //     if($booking->invoice_status === ApprovalStatus::APPROVED){
        //         // cief todo: must make sure TransactionType::BILL has status Approved (2)
        //         $bookingOriginalStatus = ApprovalStatus::COMPLETED;
        //     }
        // }

        if(!$eInvoiceWithRefund){
            $this->updatesBookingStatus->execute($booking, ApprovalStatus::APPROVED);
        }

        $firstInvoice = $booking->transactions()
            ->whereIn('type', [TransactionType::INVOICE])
            ->withTrashed()
            ->orderBy('created_at', 'asc')
            ->first();

        $latestInvoice = $booking->transactions()
            ->whereIn('type', [TransactionType::INVOICE])
            ->latest()
            ->first();

        // if($eInvoiceTry){
        //     $kvpQuery = $latestInvoice->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE);
        //     if($kvpQuery->exists()){
        //         $this->updateOrCreateKeyValuePair($booking, KVPKey::BOOKING_EINVOICE_ELIGIBLE, '1');
        //     }
        // }

        Log::info('RegenerateInvoiceBookingV2Processor booking: ' . json_encode($booking->marking));

        // get the first bill_no
        if($firstInvoice){
            $firstBillNo = $firstInvoice->bill_no;
            $kvpCopies = null;

            //for NORMAL INVOICE
            if (!Str::startsWith($firstBillNo, 'EINV')) {
                if (strpos($firstBillNo, '-deleted') !== false) {
                    $firstBillNo = substr($firstBillNo, 0, strpos($firstBillNo, '-deleted'));
                }
                // update currentInvoice bill_no to '-deleted-'
                $currentInvoice = $booking->transactions()->where('type', TransactionType::INVOICE)->first();
                if($currentInvoice){
                    $currentInvoice->bill_no = $currentInvoice->bill_no ."-deleted-" . (string)(Carbon::now()->timestamp);
                    $currentInvoice->save();
                }

                $transactionWithSameBillNo = Transaction::where('bill_no', $firstBillNo)->withTrashed()->get();
                if ($transactionWithSameBillNo) {
                    foreach ($transactionWithSameBillNo as $transaction) {
                        $transaction->bill_no = $transaction->bill_no . "-deleted-" . Str::random(10);
                        $transaction->save();
                    }
                }

                $transaction = $booking->transactions()->whereIn('type', [TransactionType::INVOICE, TransactionType::SUPPLIER_DELIVER])->get();
                foreach ($transaction as $key => $row) {
                    $this->deletesTransaction->execute($row);
                }

                if($latestInvoice){
                    $kvpCopies = $latestInvoice->attributesKVP->map(function ($kvp) {
                        return $kvp->replicate();
                    });
                }
            }
            //for E-INVOICE
            else {
                // $transaction = $booking->transactions()->whereIn('type', [TransactionType::SUPPLIER_DELIVER])->get();
                // foreach ($transaction as $key => $row) {
                //     $this->deletesTransaction->execute($row);
                // }
            }

            $document = $booking->documents()->whereIn('document_type', [DocumentType::PURCHASE_ORDER, DocumentType::INVOICE, DocumentType::EINVOICE, DocumentType::DELIVER_ORDER, DocumentType::SUPPLIER_DELIVER_ORDER])->get();
            foreach ($document as $key => $row) {
                $this->deletesDocument->execute($row);
            }

            $this->createInvoiceTransactionProcessor->execute($booking, $firstBillNo, $kvpCopies, [
                'generateEInvoice' => true,
                'generateEInvoiceWithNormalInvoiceTemplate' => $eInvoiceWithNormalInvoiceTemplate,
                'generateEInvoiceRefund' => $eInvoiceWithRefund,
                'bookingOriginalStatus' => $bookingOriginalStatus
            ]);
        }
        else {
            $this->createInvoiceTransactionProcessor->execute($booking, "", null, [
                'generateEInvoice' => false,
                'generateEInvoiceWithNormalInvoiceTemplate' => $eInvoiceWithNormalInvoiceTemplate,
                'generateEInvoiceRefund' => $eInvoiceWithRefund,
                'bookingOriginalStatus' => $bookingOriginalStatus
            ]);
        }
    }

    private function updateOrCreateKeyValuePair($booking, $key, $value)
    {
        $booking->attributesKVP()->updateOrCreate(
            ['key' => $key],
            ['value' => $value]
        );
    }
}
