<?php

namespace App\Classes\Modules\Vouchers\Processors;


use App\Classes\Modules\Vouchers\Services\Voucherify\FetchesVoucherifyVoucher;
use App\Classes\Modules\Vouchers\Services\Voucherify\ValidatesVoucherifyVoucher;
use App\Classes\Modules\Vouchers\Services\CreatesVoucher;
use App\Classes\Modules\Vouchers\Services\FetchesVoucher;
use App\Classes\Modules\Rewards\Services\CreatesUserReward;
use App\Classes\Modules\Vouchers\DataTransferObjects\VoucherObject;
use App\Classes\Modules\Vouchers\DataTransferObjects\ValidateVoucherifyVoucherObject;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;


class CreateVoucherProcessor
{
    /** @var FetchesVoucherifyVoucher */
    private $fetchesVoucherifyVoucher;

    /** @var ValidatesVoucherifyVoucher */
    private $validatesVoucherifyVoucher;

    /** @var CreatesVoucher */
    private $createsVoucher;

    /** @var CreatesUserReward */
    private $createsUserReward;

    /** @var FetchesVoucher */
    private $fetchesVoucher;

    /**
     * CreateVoucherProcessor constructor.
     * @param FetchesVoucherifyVoucher $fetchesVoucherifyVoucher
     * @param ValidatesVoucherifyVoucher $validatesVoucherifyVoucher
     * @param CreatesVoucher $createsVoucher
     * @param CreatesUserReward $createsUserReward
     * @param FetchesVoucher $fetchesVoucher
     */
    public function __construct(FetchesVoucherifyVoucher $fetchesVoucherifyVoucher, CreatesVoucher $createsVoucher, CreatesUserReward $createsUserReward, FetchesVoucher $fetchesVoucher, ValidatesVoucherifyVoucher $validatesVoucherifyVoucher)
    {
        $this->fetchesVoucherifyVoucher = $fetchesVoucherifyVoucher;
        $this->createsVoucher = $createsVoucher;
        $this->createsUserReward = $createsUserReward;
        $this->fetchesVoucher = $fetchesVoucher;
        $this->validatesVoucherifyVoucher = $validatesVoucherifyVoucher;
    }


    /**
     * @param ?User $userParam
     * @param string $voucherCodeInput
     * @return array
     * @throws \App\Classes\Exceptions\AccessForbiddenException
     * @throws \App\Classes\Exceptions\MalformedRequestException
     * @throws \App\Classes\Exceptions\RequestValidationException
     */
    public function execute(?User $userParam, string $voucherCodeInput) {
        try{
            $result = null;
            $user = Auth::user(); /** @var User $user */
            if($user && isset($user->type) && in_array($user->type, RoleTypes::ADMIN_ROLES) && $userParam){
                $user = User::where('id', $userParam->id)->first();
            }
            else{
                $user = $userParam ? $userParam : $user;
            }

            //Voucherify - Validates Voucher
            $ValidateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject(0, $voucherCodeInput, 0.00, $user);
            $voucherifyVoucherValidated = $this->validatesVoucherifyVoucher->execute($ValidateVoucherifyVoucherObject);

            if(isset($voucherifyVoucherValidated->reason)){
                $result = [];
                $result['reason'] = $voucherifyVoucherValidated->reason;
            }
            else if($voucherifyVoucherValidated){
                $voucher = $this->recordVoucherInfo($user, $voucherCodeInput);
                $voucherCount = $user->rewards->where('voucher_id', $voucher->id)->count();
                if($voucherCount == 0){
                    $result = $this->createsUserReward->execute(null, $user, $voucher->id);
                }
                else{
                    $result['reason'] = 'Voucher already added';
                }
            }

            return $result;
        } catch (\Exception $e) {
            Log::error($e);
        }
    }

    private function recordVoucherInfo(User $user, string $voucherCodeInput){
           //Voucherify - Get Voucher
           $voucherifyVoucherFetched = $this->fetchesVoucherifyVoucher->execute($user, $voucherCodeInput);

           $voucherName = $voucherifyVoucherFetched->campaign;
           $voucherType = $voucherifyVoucherFetched->discount->type;
           $voucherValue = isset($voucherifyVoucherFetched->discount->amount_off) ? $voucherifyVoucherFetched->discount->amount_off : $voucherifyVoucherFetched->discount->percent_off;
           $voucherCode = $voucherifyVoucherFetched->code;
           $voucherStartDate = $voucherifyVoucherFetched->start_date;
           $voucherEndDate = $voucherifyVoucherFetched->expiration_date;

           $voucherObject= new VoucherObject($voucherCode, isset($voucherName) ? $voucherName : "Voucherify Voucher Added Manually", $voucherType, $voucherValue, $voucherStartDate, $voucherEndDate);
           $voucher = $this->createsVoucher->execute($voucherObject);
           if(!$voucher) $voucher = $this->fetchesVoucher->execute(['code' => $voucherCodeInput]);
        return $voucher;
    }
}
