<?php

namespace App\Classes\Modules\Transactions\Processors;

use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\DeletesTransactionDetails;
use App\Classes\Modules\Transactions\Services\UpdatesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Wallets\Processors\CreditWalletProcessor;

use App\Classes\Modules\Wallets\Services\CreatesWallet;
use App\Classes\Modules\Wallets\Services\GeneratesWalletCode;
use App\Classes\ValueObjects\Constants\CashBack;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Models\Booking;
use App\Models\Transaction;
use Carbon\Carbon;

class CreateCashBackTransactionProcessor
{

    /** @var CreatesTransaction */
    private $createsTransaction;


    /** @var GeneratesTransactionBillNumber */
    private $generatesTransactionBillNumber;


    /** @var CreditWalletProcessor */
    private $creditWalletProcessor;

    /**
     * CreateCashBackTransactionProcessor constructor.
     * @param CreatesTransaction $createsTransaction
     * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
     * @param CreditWalletProcessor $creditWalletProcessor
     */
    public function __construct(CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreditWalletProcessor $creditWalletProcessor)
    {
        $this->createsTransaction = $createsTransaction;
        $this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
        $this->creditWalletProcessor = $creditWalletProcessor;
    }


    /**
     * @param Transaction $transaction
     * @return Transaction|\Illuminate\Database\Eloquent\Model
     * @throws \App\Classes\Exceptions\MalformedRequestException
     */
    public function execute(Transaction $transaction) 
    {
        // leave this disabled until ready to launch to production
        return;
        // ((MYR) * (cash back %)) * (1/conversion rate)
        $current_total_cash_back = Transaction::
            where('type', TransactionType::CASH_BACK)
            ->whereMonth('created_at', Carbon::now()->month)->sum('amount');

        if (
            $current_total_cash_back < CashBack::MAX &&
            $transaction->owner()->first()->transactions()->where('type', TransactionType::PURCHASE_ORDER)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->count() > 0
        ) {

            $cash_back_segemnt = CashBack::SEGMENT;

            foreach ($cash_back_segemnt as $key => $row) {
                if ($row['max_value'] > $transaction->amount && $row['min_value'] <= $transaction->amount) {

                    $method = $this->getRandomWeightedElement($row['weight']);

                    $total = $transaction->amount * $row['percent'][$method];

                    $billNumber = $this->generatesTransactionBillNumber->execute('CBACK-');

                    $object = new TransactionObject(
                        $billNumber, 
                        TransactionType::CASH_BACK, 
                        $transaction->issuer, 
                        1,
                        1, 
                        PaymentMethodType::WALLET,
                        $total, 
                        $total, 
                        $transaction->currency_id, 
                        $transaction->currency_id,
                        1, 
                        0, 
                        0,
                        null,
                        ApprovalStatus::APPROVED,
                        null,
                        'cash back ' . $transaction->bill_no
                    );

                    $cash_back_transaction = $this->createsTransaction->execute($transaction, $object);

                    $company = $transaction->owner()->first()->company;
                    $credit = $this->creditWalletProcessor->execute($company, $transaction->type, $cash_back_transaction->amount, 'cash back ' . $transaction->bill_no);
                }
            }
        }
        return $transaction;
    }

     public function getRandomWeightedElement(array $weightedValues) {
        $rand = mt_rand(1, (int) array_sum($weightedValues));
        foreach ($weightedValues as $key => $value) {
            $rand -= $value;
            if ($rand <= 0) {
                return $key;
            }
        }
    }

}