<?php

namespace App\Classes\Modules\Rules\Standards\Rules;

use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Bookings\Services\FetchesBooking;
use App\Classes\Modules\Companies\Services\FetchesCompanyPaymentAttemptLimit;
use App\Classes\Modules\Transactions\Services\CalculatesTransactionExpiryDateTime;
use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding;
use App\Classes\Modules\Bookings\Services\CalculatesBookingPaidAmount;
use App\Classes\Modules\Billplzs\Services\DeletesBillplzBill;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

class CanPassOrderDurationLimitRule extends AbstractRule
{

    /** @var FetchesBooking */
    private $fetchesBooking;

    /** @var FetchesCompanyPaymentAttemptLimit */
    private $fetchesCompanyPaymentAttemptLimit;

    /** @var CalculatesTransactionExpiryDateTime */
    private $calculatesTransactionExpiryDateTime;

    /** @var DeletesBillplzBill */
    private $deletesBillplzBill;

    /** @var FetchesTransaction */
    private $fetchesTransaction;

    /** @var CalculatesBookingOutstanding */
    private $calculatesBookingOutstanding;

    /** @var CalculatesBookingPaidAmount */
    private $calculatesBookingPaidAmount;

    /**
     * CanPassOrderDurationLimitRule constructor.
     * @param FetchesBooking $fetchesBooking
     * @param FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit
     * @param CalculatesTransactionExpiryDateTime $calculatesTransactionExpiryDateTime
     * @param DeletesBillplzBill $deletesBillplzBill
     * @param FetchesTransaction $fetchesTransaction
     * @param CalculatesBookingOutstanding $calculatesBookingOutstanding
     * @param CalculatesBookingPaidAmount $calculatesBookingPaidAmount
     */
    public function __construct(FetchesBooking $fetchesBooking, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, CalculatesTransactionExpiryDateTime $calculatesTransactionExpiryDateTime, DeletesBillplzBill $deletesBillplzBill, FetchesTransaction $fetchesTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CalculatesBookingPaidAmount $calculatesBookingPaidAmount)
    {
        $this->fetchesBooking = $fetchesBooking;
        $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit;
        $this->calculatesTransactionExpiryDateTime = $calculatesTransactionExpiryDateTime;
        $this->deletesBillplzBill = $deletesBillplzBill;
        $this->fetchesTransaction = $fetchesTransaction;
        $this->calculatesBookingOutstanding = $calculatesBookingOutstanding;
        $this->calculatesBookingPaidAmount = $calculatesBookingPaidAmount;
    }

    /**
     * @return bool
     */
    protected function authorized($object): bool
    {
        return true;

    }

    /**
     * @return bool
     */
    protected function validators($object): bool
    {
        return true;

    }


    /**
     * @return bool
     */
    protected function criteria($object): bool
    {
        //Check if order is still valid (within duration limit, reused PAYMENT_ATTEMPT_DURATION_LIMIT)
        $expiresOn = $this->calculatesTransactionExpiryDateTime->execute($object->bookingId);
        $isExpired = Carbon::now()->greaterThan($expiresOn);

        // if($isExpired) {
        //     $booking = $this->fetchesBooking->execute(['id' => $object->bookingId]);
        //     $amountOutstanding = $this->calculatesBookingOutstanding->execute($booking);
        //     $amountPaid = $this->calculatesBookingPaidAmount->execute($booking);
        //     if($amountPaid > 0.01 && $amountOutstanding > 0){
        //         Log::info("Transfer already expired but has paid amount: {$amountPaid} and outstanding amount: {$amountOutstanding}, Booking ID: {$object->bookingId}");
        //         $isExpired = false;
        //     }
        // }

        if($isExpired){
            if (isset($object->paymentReference) && $object->paymentReference){
                $transaction = $this->fetchesTransaction->execute(['payment_reference' => $object->paymentReference]);
                if($transaction->status === ApprovalStatus::PENDING_SUBMISSION && $transaction->payment_method == PaymentMethodType::PAYMENT_GATEWAY){
                    $this->deletesBillplzBill->execute($object->paymentReference);
                }
            }

            throw new CriteriaNotFulfilledException("Transfer has already expired.");
        }
        return true;
    }
}
