<?php

namespace App\Classes\Modules\Transactions\ControllersLogic;


use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Standards\Rules\CanCreateTransaction;
use App\Classes\Modules\Transactions\Standards\Rules\CanCreateTransactionDetail;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Http\Resources\TransactionResource;
use App\Http\Resources\TransactionDetailResource;

use App\Classes\Modules\Receipts\Standards\Rules\CanCreateReceipt;
use App\Classes\Modules\Receipts\Standards\Rules\CanCreateReceiptDetail;
use App\Classes\Modules\Receipts\DataTransferObjects\ReceiptObject;
use App\Classes\Modules\Receipts\DataTransferObjects\ReceiptDetailObject;
use App\Classes\Modules\Receipts\Services\CreatesReceipt;
use App\Classes\Modules\Receipts\Services\CreatesReceiptDetail;
use App\Classes\Modules\Receipts\Services\GeneratesReceiptBillNo;

use App\Classes\Modules\Currencies\Services\FetchesCurrency;
use App\Classes\Modules\Currencies\Services\RateCalculatesCurrency;

use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\FetchesTransactionDetail;

use App\Classes\Modules\Companies\Services\FetchesCompany;

use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class CreateMakePaymentPOTransactionLogic extends AbstractControllerLogic
{


    /**
     * @return array
     */
    protected function notification():array {
        return [
            'title' => 'Created Transaction',
            'message' => 'You have successfully created a transaction'
        ];
    }

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

    /** @var CanCreateTransaction */
    private $canCreateTransaction;
    
    private $fetchesCurrency;
   
    private $rateCalculatesCurrency;
    
    private $fetchesCompany;

    private $createsTransaction;
    
    private $canCreateTransactionDetail;
    
    private $createsTransactionDetail;
    
    private $fetchesTransaction;
    
    private $fetchesTransactionDetail;
    
    private $generatesReceiptBillNo;

    /** @var CanCreateReceipt */
    private $canCreateReceipt;
    
    private $createsReceipt;
    
    private $canCreateReceiptDetail;
    
    private $createsReceiptDetail;

    /**
     * CreateWalletLogic constructor.
     * @param GeneratesTransactionBillNumber $generatesTransactionBillNo
     * @param CanCreateTransaction $canCreateTransaction
     * @param FetchesCurrency $fetchesCurrency
     * @param RateCalculatesCurrency $rateCalculatesCurrency
     * @param FetchesCompany $fetchesCompany
     * @param CreatesTransaction $createsTransaction
     * @param CanCreateTransactionDetail $canCreateTransactionDetail
     * @param CreatesTransactionDetail $createsTransactionDetail
     * @param FetchesTransaction $fetchesTransaction
     * @param FetchesTransactionDetail $fetchesTransactionDetail
     * @param GeneratesReceiptBillNo $generatesReceiptBillNo
     * @param CanCreateReceipt $canCreateReceipt
     * @param CreatesReceipt $createsReceipt
     * @param CanCreateReceiptDetail $canCreateReceiptDetail
     * @param CreatesReceiptDetail $createsReceiptDetail
     */
    public function __construct(
        GeneratesTransactionBillNumber $generatesTransactionBillNo, CanCreateTransaction $canCreateTransaction,
        FetchesCurrency $fetchesCurrency, RateCalculatesCurrency $rateCalculatesCurrency, FetchesCompany $fetchesCompany,
        CreatesTransaction $createsTransaction,
        CanCreateTransactionDetail $canCreateTransactionDetail, CreatesTransactionDetail $createsTransactionDetail,
        FetchesTransaction $fetchesTransaction , FetchesTransactionDetail $fetchesTransactionDetail,
        GeneratesReceiptBillNo $generatesReceiptBillNo, CanCreateReceipt $canCreateReceipt,
        CreatesReceipt $createsReceipt,
        CanCreateReceiptDetail $canCreateReceiptDetail, CreatesReceiptDetail $createsReceiptDetail
    ){
        $this->generatesTransactionBillNo = $generatesTransactionBillNo;
        $this->canCreateTransaction = $canCreateTransaction;
        $this->fetchesCurrency = $fetchesCurrency;
        $this->rateCalculatesCurrency = $rateCalculatesCurrency;
        $this->fetchesCompany = $fetchesCompany;
        $this->createsTransaction =$createsTransaction;
        $this->canCreateTransactionDetail =$canCreateTransactionDetail;
        $this->createsTransactionDetail = $createsTransactionDetail;
        $this->fetchesTransaction = $fetchesTransaction;
        $this->fetchesTransactionDetail = $fetchesTransactionDetail;
        
        $this->generatesReceiptBillNo = $generatesReceiptBillNo;
        $this->canCreateReceipt = $canCreateReceipt;
        $this->createsReceipt =$createsReceipt;
        $this->canCreateReceiptDetail =$canCreateReceiptDetail;
        $this->createsReceiptDetail = $createsReceiptDetail;
        
    }

    /**
     * @param Request $request
     * @return JsonResponse
     * @throws ErrorException
     */
    public function logic(Request $request) : JsonResponse
    {
        try {

            DB::beginTransaction();
            $json_array = json_decode($request->getContent(), true);
            
            $po_transaction = $this->fetchesTransaction->execute(['id' => $json_array['ref_po']]);
            
            $object = new TransactionObject(
                $this->generatesTransactionBillNo->execute(),$po_transaction->trans_type1,'INV',
                $po_transaction->amount, $po_transaction->currency_id , $po_transaction->original_amount,
                $po_transaction->original_currency_id, $po_transaction->currency_rate ,
                $po_transaction->dt_transaction,1,$po_transaction->booking_id,
                $po_transaction->company_id
            );
            
            $this->canCreateTransaction->passes($object);
            $transaction = $this->createsTransaction->execute($object);
            $transaction_array = new TransactionResource($transaction);
            
            $transaction_detail = $this->fetchesTransactionDetail->getRepository()->where('transaction_id', $json_array['ref_po'])->get();
            foreach ($transaction_detail as $key => $value) {
                
                $object_detail = new TransactionDetailObject(
                    $transaction->trans_type1,$transaction->trans_type2,
                    $transaction->id,$value->product_code,$value->product_name,
                    $value->qty,$value->price, $value->amount
                );
                $this->canCreateTransactionDetail->passes($object_detail);
                $transaction_detail = $this->createsTransactionDetail->execute($object_detail);
                //array_push($stack, "apple", "raspberry");
                $transaction_detail_resource= new TransactionDetailResource($transaction_detail);
                $transaction_detail_array[]= $transaction_detail_resource->toArray($request);
            }
            
            
            $object = new ReceiptObject(
                $this->generatesReceiptBillNo->execute(),$transaction->trans_type1,"RECPT",
                $po_transaction->amount, $po_transaction->currency_id , $po_transaction->original_amount,
                $po_transaction->original_currency_id, $po_transaction->currency_rate ,
                $po_transaction->dt_transaction,1,$po_transaction->booking_id,
                $po_transaction->company_id
            );
            
            
            $this->canCreateReceipt->passes($object);

            $receipt = $this->createsReceipt->execute($object);
            
                
            $object_detail = new ReceiptDetailObject(
                $transaction->trans_type1,"RECPT",
                $transaction->id,$receipt->id,
                $transaction->amount, $transaction->amount
            );
            $this->canCreateReceiptDetail->passes($object_detail);
            $this->createsReceiptDetail->execute($object_detail);
                           
            
            DB::commit();

            return $this->resourceResponse($transaction_array);
            

        } catch (\Exception $exception) {
            throw new ErrorException($exception->getMessage(), $exception->getCode());
        }

    }
}