<?php

namespace App\Modules\Company\Subscription\Discount;

use App\Models\CompanySubscriptionCoupons;
use App\Models\CompanySubscriptionCouponsUsage;
use App\Models\CompanyCoupons;
use App\Models\CouponSubscsriptionRate;
use App\Traits\ValidatorTraits;
use App\Traits\UserTraits;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class Coupon
{
    use ValidatorTraits, UserTraits;

    public function getCouponDiscount($payload)
    {

        $rules = array(
            'couponCode' => 'required|max:50',
            'subscriptionRateID' => 'required',
        );

        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $couponCode = $payload->couponCode;
        $subscriptionRateID = $payload->subscriptionRateID;
        $discountTransaction = $this->fetchCouponDetails($couponCode);

        if (!$discountTransaction) {
            return response()->json(['error' => 'Coupon code does not exist.']);
        }

        //how many company can use
        if ($discountTransaction->current_usage >= $discountTransaction->max_usage) {
            return response()->json(['error' => 'Coupon code has already used its maximum usage.']);
        }

        $companyID = $this->getCurrentUser()->company_id;
        $companyUsage = $this->checkCompanyUsage($companyID);

        //how many times the company can use the coupon
        if($companyUsage && $companyUsage->coupon_subscription_rates_id == $discountTransaction->coupon_subscription_rates_id){
            if($companyUsage->company_usage >= $companyUsage->range){
                return response()->json(['error' => 'You have already exceeded the maximum monthly range of the coupon.']);
            }
        }

        if ($discountTransaction->validity_date <= Carbon::now()) {
            return response()->json(['error' => 'Coupon code has already expired.']);
        }

        if ($discountTransaction->is_disabled) {
            return response()->json(['error' => 'Coupon code is currently disabled.']);
        }

        if($discountTransaction->for_all == false){
            if($discountTransaction->company_subscription_rates_id != $subscriptionRateID){
                return response()->json(['error' => 'Coupon code is not applicable on the choosen subscription rate.']);
            }  
        }
         

        return $discountTransaction;
    }

    public function fetchCouponDetails($couponCode){
        return CompanySubscriptionCoupons::select(
            'coupon_subscription_rates.id as coupon_subscription_rates_id',
            'coupon_subscription_rates.company_subscription_rates_id',
            'coupon_subscription_rates.current_usage',
            'coupon_subscription_rates.for_all',
            'coupons.*',
        )
            ->join('coupon_subscription_rates', 'coupon_subscription_rates.coupon_id', 'coupons.id')
            ->where('coupons.coupon_code', $couponCode)
            ->first();
    }

    public function fetchCouponDetailsUsingID($couponID)
    {
        return CompanySubscriptionCoupons::select(
            'coupon_subscription_rates.id as coupon_subscription_rates_id',
            'coupons.*',
        )
            ->join('coupon_subscription_rates', 'coupon_subscription_rates.coupon_id', 'coupons.id')
            ->where('coupons.id', $couponID)
            ->where('coupons.validity_date', '>=', Carbon::now()->format('Y-m-d'))
            ->first();
    }

    public function addUsageOnCouponDiscount($usageData)
    {
        $usageData = (object) $usageData;

        $couponID = $usageData->couponID;
        $companyID = $usageData->companyID;

        $couponData = $this->fetchCouponDetailsUsingID($couponID);
        $hasCurrentCoupon = $this->checkCompanyUsage($companyID);

        // invalidate coupon discount
        if(!$couponData){
            return true;
        }

        //has current coupon
        if($hasCurrentCoupon){
            if($couponData->id == $hasCurrentCoupon->coupon_id){
                $companyCouponData = [
                    'company_usage' => DB::raw('company_usage + 1'),
                ];
                $this->updateCompanyCoupon($hasCurrentCoupon->id, $companyCouponData); //add company usage
                
            }else{
                $this->disabledCurrentCompanyCoupon($companyID);
                //create new data for new coupon
                $companyCouponData = array(
                    'company_id' => $companyID,
                    'coupon_subscription_rates_id' => $couponData->coupon_subscription_rates_id,
                    'is_active' => true,
                    'company_usage' => 1,
                    'range' => $couponData->range,
                    'activated_at' =>  Carbon::now(),
                );
                $this->createCompanyCoupon($companyCouponData);
                $this->addCountOnUsage($couponData->coupon_subscription_rates_id);
            }

        //fresh coupon
        }else{
            $companyCouponData = array(
                'company_id' => $companyID,
                'coupon_subscription_rates_id' => $couponData->coupon_subscription_rates_id,
                'is_active' => true,
                'company_usage' => 1,
                'range' => $couponData->range,
                'activated_at' =>  Carbon::now(),
            );
            $this->createCompanyCoupon($companyCouponData);
            $this->addCountOnUsage($couponData->coupon_subscription_rates_id);
        }

        return [
            'couponData' => $couponData,
            'hasCurrentCoupon' => $hasCurrentCoupon,
            'companyCouponData' => $companyCouponData,
            'companyID' => $companyID,
        ];
    }

    public function checkCompanyUsage($companyID){
        return CompanyCoupons::select(
            'coupon_subscription_rates.coupon_id',
            'company_coupons.*',
        )
        ->join('coupon_subscription_rates', 'coupon_subscription_rates.id', 'company_coupons.coupon_subscription_rates_id')
        ->where('company_coupons.company_id', $companyID)
        ->where('company_coupons.is_active', true)
        ->first();
    }

    public function createCompanyCoupon($data){
        return CompanyCoupons::create($data);
    }


    public function disabledCurrentCompanyCoupon($companyID){
        return CompanyCoupons::where('company_id', $companyID)
            ->where('is_active', true)
            ->update([
                'is_active' => false
            ]);
    }

    public function updateCompanyCoupon($id, $data){
        return CompanyCoupons::where('id', $id)->update($data);
    }

    public function addCountOnUsage($couponSubscriptionID){
        CouponSubscsriptionRate::where('id', $couponSubscriptionID)
        ->update([
            'current_usage' => DB::raw('current_usage + 1'),
        ]);
    }

    public function getActiveCoupon($companyID){
        return CompanyCoupons::select(
            'coupons.*',
            'company_coupons.company_id',
            'company_coupons.range',
            'company_coupons.company_usage',
        )
        ->join('coupon_subscription_rates', 'coupon_subscription_rates.id', 'company_coupons.coupon_subscription_rates_id')
        ->join('coupons', 'coupons.id', 'coupon_subscription_rates.coupon_id')
        ->where('company_coupons.company_id', $companyID)
        ->whereRaw('company_coupons.range > company_coupons.company_usage')
        ->where('is_active', true)
        ->first();
    }       

}
