<?php

namespace App\Classes\Modules\Receipts\ControllersLogic;

use App\Classes\General\Abstracts\AbstractControllerLogic;

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\Http\Resources\ReceiptResource;
use App\Http\Resources\ReceiptDetailResource;

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

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

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

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

class CreateReceiptLogic extends AbstractControllerLogic
{


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

    
    /** @var GeneratesReceiptBillNo */
    private $generatesReceiptBillNo;

    /** @var CanCreateReceipt */
    private $canCreateReceipt;
    
    private $fetchesCurrency;
   
    private $rateCalculatesCurrency;
    
    private $fetchesCompany;

    private $createsReceipt;
    
    private $canCreateReceiptDetail;
    
    private $createsReceiptDetail;
    
    private $fetchesTransaction;

    /**
     * CreateWalletLogic constructor.
     * @param GeneratesReceiptBillNo $generatesReceiptBillNo
     * @param CanCreateReceipt $canCreateReceipt
     * @param FetchesCurrency $fetchesCurrency
     * @param RateCalculatesCurrency $rateCalculatesCurrency
     * @param FetchesCompany $fetchesCompany
     * @param CreatesReceipt $createsReceipt
     * @param CanCreateReceiptDetail $canCreateReceiptDetail
     * @param CreatesReceiptDetail $createsReceiptDetail
     * @param FetchesTransaction $fetchesTransaction
     */
    public function __construct(
            GeneratesReceiptBillNo $generatesReceiptBillNo, CanCreateReceipt $canCreateReceipt,
            FetchesCurrency $fetchesCurrency,RateCalculatesCurrency $rateCalculatesCurrency, FetchesCompany $fetchesCompany,
            CreatesReceipt $createsReceipt,
            CanCreateReceiptDetail $canCreateReceiptDetail, CreatesReceiptDetail $createsReceiptDetail,
            FetchesTransaction $fetchesTransaction
    ){
        $this->generatesReceiptBillNo = $generatesReceiptBillNo;
        $this->canCreateReceipt = $canCreateReceipt;
        $this->fetchesCurrency = $fetchesCurrency;
        $this->rateCalculatesCurrency = $rateCalculatesCurrency;
        $this->fetchesCompany = $fetchesCompany;
        $this->createsReceipt =$createsReceipt;
        $this->canCreateReceiptDetail =$canCreateReceiptDetail;
        $this->createsReceiptDetail = $createsReceiptDetail;
        $this->fetchesTransaction = $fetchesTransaction;
    }

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

            DB::beginTransaction();
            $json_array = json_decode($request->getContent(), true);
            $company =  $this->fetchesCompany->execute(['id' => $json_array['company_id']]);
            
            $conversion_currency = $this->fetchesCurrency->execute(['id' => $json_array['currency_id']]);
            $convertable_currency = $this->fetchesCurrency->execute(['id' => 1]);//MYR
            $convert_amount = $this->rateCalculatesCurrency->execute($conversion_currency, $convertable_currency, $json_array['amount']);
            $convert_rate = $this->rateCalculatesCurrency->execute_rate($conversion_currency, $convertable_currency);
            
            $object = new ReceiptObject(
                $this->generatesReceiptBillNo->execute(),$json_array['trans_type1'],$json_array['trans_type2'],
                number_format( (float) $convert_amount, 5, '.', ''), 1 , number_format( (float) $json_array['amount'], 5, '.', ''),
                $json_array['currency_id'],number_format( (float) $convert_rate, 5, '.', ''),
                $json_array['dt_transaction'],1,$request->route('id'),
                $company->id
            );
            
            
            $this->canCreateReceipt->passes($object);

            $receipt = $this->createsReceipt->execute($object);
            
            $receipt_array = new ReceiptResource($receipt);
            $receipt_detail_array = array();
           
            foreach ($json_array['receipt_detail'] as $key => $value) {
                
                $transaction_inv = $this->fetchesTransaction->execute(['id' => $value['transaction_id']]);
                
                $object_detail = new ReceiptDetailObject(
                    $json_array['trans_type1'],$json_array['trans_type2'],
                    $transaction_inv->id,$receipt->id,
                    number_format( (float) $convert_amount, 5, '.', ''), number_format( (float) $json_array['amount'], 5, '.', '')
                );
                $this->canCreateReceiptDetail->passes($object_detail);
                $transaction_detail = $this->createsReceiptDetail->execute($object_detail);
                //array_push($stack, "apple", "raspberry");
                $receipt_detail_resource= new ReceiptDetailResource($transaction_detail);
                $receipt_detail_array[]= $receipt_detail_resource->toArray($request);
                 
            }
            
            //$transaction_array['transaction_detail']= $transaction_detail_array;
            //print_r($transaction_detail_array);
            //dd($transaction_detail_array);
            DB::commit();

            return $this->resourceResponse($receipt_array);
            //return $this->resourceResponse($json_array);

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

    }
}