<?php

namespace App\Modules\Admin\Subscriptions;

use App\Models\CompanySubscriptionCoupons;
use App\Models\CompanySubscriptionCouponsUsage;
use App\Models\CouponSubscsriptionRate;
use App\Http\Resources\Admin\SubscriptionCoupon as SubscriptionCouponResource;
use App\Http\Resources\Admin\SubscriptionCouponDetails as SubscriptionCouponDetailsResource;
use App\Http\Resources\Admin\SubscriptionCouponUsage as SubscriptionCouponUsageResource;
use App\Models\CompanyCoupons;
use App\Traits\SearchTraits;
use App\Traits\SortingTraits;
use App\Traits\ValidatorTraits;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;

class Coupons
{
    use SortingTraits, SearchTraits, ValidatorTraits;

    public function getActiveCouponData($payload)
    {
        // sorting
        $sortField = $this->sortField($payload, 'id');
        $sortOrder = $this->sortOrder($payload, 'desc');

        // searching
        $couponCodeSearch = $this->searchField($payload->coupon_code);
        $amountSearch = $this->searchField($payload->amount);
        $statusSearch = $payload->is_disabled;
        $currentUsageSearch = $this->searchField($payload->current_usage);
        $maxUsageSearch = $this->searchField($payload->max_usage);

        $dateToday = date('Y-m-d');
        return SubscriptionCouponResource::collection(
            CompanySubscriptionCoupons::select(
                'coupons.id',
                'coupons.coupon_code',
                'coupons.validity_date',
                'coupons.discount as amount',
                'coupons.max_usage',
                'coupons.is_disabled',
                'coupons.type',
                'coupons.range',
                'company_subscription_rates.name as subscription',
                'coupon_subscription_rates.for_all',
                'coupons.created_at')
                ->join('coupon_subscription_rates', 'coupon_subscription_rates.coupon_id', 'coupons.id')
                ->leftJoin('company_subscription_rates', 'company_subscription_rates.id', 'coupon_subscription_rates.company_subscription_rates_id')
                ->where('coupons.validity_date', '>', $dateToday)
                ->whereRaw('coupon_subscription_rates.current_usage < coupons.max_usage')
                ->when(!empty($couponCodeSearch), function ($query) use ($couponCodeSearch) {
                    return $query->where(function ($query) use ($couponCodeSearch) {
                        $query->where('coupons.coupon_code', 'LIKE', $couponCodeSearch . '%');
                    });
                })
                ->when(!empty($maxUsageSearch), function ($query) use ($maxUsageSearch) {
                    return $query->where('coupons.max_usage', 'LIKE', $maxUsageSearch . '%');
                })
                ->when(!empty($statusSearch), function ($query) use ($statusSearch) {
                    return $query->where(function ($query) use ($statusSearch) {
                        $query->whereIn('coupons.is_disabled', $statusSearch);
                    });
                })
                ->orderBy($sortField, $sortOrder)
                ->paginate(20)
        )->response()->setStatusCode(201);
    }

    public function getUsedCouponData($payload)
    {
        // sorting
        $sortField = $this->sortField($payload, 'id');
        $sortOrder = $this->sortOrder($payload, 'desc');

        // searching
        $couponCodeSearch = $this->searchField($payload->coupon_code);
        $amountSearch = $this->searchField($payload->amount);
        $usedBySearch = $this->searchField($payload->used_by);

        return SubscriptionCouponUsageResource::collection(
            CouponSubscsriptionRate::select(
                'coupon_subscription_rates.id',
                'coupon_subscription_rates.current_usage',
                'coupons.id as coupon_id',
                'coupons.coupon_code',
                'coupons.discount',
                'coupons.type',
                'coupons.validity_date',
            )
            ->withCount('company_coupons')
            // ->with('company_coupons')
            ->join('coupons', 'coupons.id', 'coupon_subscription_rates.coupon_id')
            ->where('coupons.validity_date', '>=', now())
            ->orderBy($sortField, $sortOrder)
            ->paginate(20)
        )->response()->setStatusCode(201);
    }

    public function viewDetailedActiveCoupon($payload, $id){
        // sorting
        $sortField = $this->sortField($payload, 'id');
        $sortOrder = $this->sortOrder($payload, 'desc');

        $nameSearch = $this->searchField($payload->name);

        return CompanyCoupons::select(
            'company_coupons.id',
            'companies.name',
            'company_coupons.company_usage',
            'company_coupons.activated_at',
        )
            ->join('companies', 'companies.id', 'company_coupons.company_id')
            ->where('coupon_subscription_rates_id', $id)
            ->when(!empty($nameSearch), function ($query) use ($nameSearch) {
                return $query->where('companies.name', 'LIKE', $nameSearch . '%');
            })
            ->orderBy($sortField, $sortOrder)
            ->paginate(20);
    }

    public function getExpiredCouponData($payload)
    {
        // sorting
        $sortField = $this->sortField($payload, 'id');
        $sortOrder = $this->sortOrder($payload, 'desc');

        // searching
        $couponCodeSearch = $this->searchField($payload->coupon_code);
        $amountSearch = $this->searchField($payload->amount);
        $statusSearch = $payload->is_disabled;

        $dateToday = date('Y-m-d');
        return SubscriptionCouponResource::collection(
            CompanySubscriptionCoupons::select(
                'coupons.id',
                'coupons.coupon_code',
                'coupons.validity_date',
                'coupons.discount',
                'coupons.max_usage',
                'coupons.is_disabled',
                'company_subscription_rates.name as subscription',
                'coupons.created_at')
                ->join('coupon_subscription_rates', 'coupon_subscription_rates.coupon_id', 'coupons.id')
                ->join('company_subscription_rates', 'company_subscription_rates.id', 'coupon_subscription_rates.company_subscription_rates_id')
                ->where('coupons.validity_date', '<=', $dateToday)
                ->when(!empty($couponCodeSearch), function ($query) use ($couponCodeSearch) {
                    return $query->where(function ($query) use ($couponCodeSearch) {
                        $query->where('coupons.coupon_code', 'LIKE', $couponCodeSearch . '%');
                    });
                })
                // ->when(!empty($amountSearch), function ($query) use ($amountSearch) {
                //     return $query->where(function ($query) use ($amountSearch) {
                //         $query->where('coupons.amount', 'LIKE', $amountSearch . '%')
                //             ->orWhere('coupons.monthly_percentage', 'LIKE', $amountSearch . '%')
                //             ->orWhere('coupons.yearly_percentage', 'LIKE', $amountSearch . '%');
                //     });
                // })
                // ->when(!empty($statusSearch), function ($query) use ($statusSearch) {
                //     return $query->where(function ($query) use ($statusSearch) {
                //         $query->whereIn('coupons.is_disabled', $statusSearch);
                //     });
                // })
                ->orderBy($sortField, $sortOrder)
                ->paginate(20)
        )->response()->setStatusCode(201);
    }

    public function getDetails($id)
    {
        return SubscriptionCouponDetailsResource::collection(
            CompanySubscriptionCoupons::select(
                'coupons.id',
                'coupons.coupon_code',
                'coupons.validity_date',
                'coupons.discount',
                'coupons.max_usage',
                'coupons.is_disabled',
                'coupons.type',
                'coupons.range',
                'coupons.created_at',
                'company_subscription_rates.name as subscription',
                'company_subscription_rates.id as subscription_rate_id',
                'coupon_subscription_rates.for_all',
            )
                ->join('coupon_subscription_rates', 'coupon_subscription_rates.coupon_id', 'coupons.id')
                ->leftJoin('company_subscription_rates', 'company_subscription_rates.id', 'coupon_subscription_rates.company_subscription_rates_id')
                ->where('coupons.id', $id)
                ->limit(1)->get()
        )->response()->setStatusCode(201);
    }

    public function getConsumedCouponData($payload){
         // sorting
        $sortField = $this->sortField($payload, 'id');
        $sortOrder = $this->sortOrder($payload, 'desc');
        $nameSearch = $this->searchField($payload->name);

        return SubscriptionCouponUsageResource::collection(
            CompanyCoupons::select(
                'company_coupons.id',
                'coupons.coupon_code',
                'coupons.discount',
                'coupons.type',
                'companies.name as company_name',
                'company_coupons.company_usage',
                'company_coupons.activated_at',
            )
            ->join('companies', 'companies.id', 'company_coupons.company_id')
            ->join('coupon_subscription_rates', 'coupon_subscription_rates.id', 'company_coupons.coupon_subscription_rates_id')
            ->join('coupons', 'coupons.id', 'coupon_subscription_rates.coupon_id')
            ->whereRaw('company_coupons.range = company_coupons.company_usage')
            ->when(!empty($nameSearch), function ($query) use ($nameSearch) {
                return $query->where('companies.name', 'LIKE', $nameSearch . '%');
            })
                ->orderBy($sortField, $sortOrder)
                ->paginate(20)
        )->response()->setStatusCode(201);
    }

    public function storeData($payload)
    {
        $yesterday = date('Y-m-d', strtotime(now() . '-1 day'));
        // Validate Query Param
        $rules = array(
            'validity_date' => 'required|date|after:' . $yesterday,
            'max_usage' => 'required',
            'discount' => 'required',
            'applicableForAll' => 'required|in:true,false',
            'range' => 'required|min:1|max:12',
        );
        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $subscription = $payload->subscription;
        $forAll = $payload->applicableForAll == 'true'? true: false;

        if(!$forAll){
            if(!$subscription){
                return response()->json([
                    'errors' => 'Please choose the applicable subscription rate.',
                ])->setStatusCode(201); 
            }
        }

        $validity_date = $payload->validity_date;
        $maxUsage = $payload->max_usage;
        $amount = $payload->discount;
        $type = $payload->usePercentage? 'percentage': 'fixed';
        $range = $payload->range;
        $dateToday = date('Y-m-d');

        DB::beginTransaction();

        // preparing user data to be saved on database
        $coupon_code = strtoupper(Str::random(8));
        $subscriptionCouponData = array(
            'coupon_code' => $coupon_code,
            'validity_date' => date('Y-m-d', strtotime($validity_date)),
            'max_usage' => $maxUsage,
            'discount' => $amount,
            'type' => $type,
            'range' => $range,
            'created_at' => $dateToday,
        );

        // save subscription coupon data to subscription_coupons table
        $subscriptionCouponTransaction = CompanySubscriptionCoupons::create($subscriptionCouponData);

        $couponSubscsriptionRateData = array(
            'coupon_id' => $subscriptionCouponTransaction->id,
            'company_subscription_rates_id' => $forAll? 0 : $subscription, // 0 means available for all
            'current_usage' => 0,
            'for_all' => $forAll,
        );

        $couponSubscsriptionRateTransction = CouponSubscsriptionRate::create($couponSubscsriptionRateData);

        if(!$couponSubscsriptionRateTransction || !$subscriptionCouponTransaction){
            DB::rollback();
            return response()->json([
                'errors' => 'Something went wrong.',
            ])->setStatusCode(201);
        }else{  
            DB::commit();
            return response()->json([
                'success' => 'Data added successfully.',
                'coupon_code' => $coupon_code,
            ])->setStatusCode(201);
        }
        
    }

    public function updateData($payload, $id)
    {
        $yesterday = date('Y-m-d', strtotime(now() . '-1 day'));

        $rules = array(
            'validity_date' => 'required|date|after:' . $yesterday,
            'max_usage' => 'required',
            'discount' => 'required',
            'applicableForAll' => 'required|in:true,false',
            'range' => 'required|min:1|max:12',
        );
        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $subscription = $payload->subscription;
        $forAll = $payload->applicableForAll == 'true'? true : false;
        if(!$forAll){
            if(!$subscription){
                return response()->json([
                    'errors' => 'Please choose the applicable subscription rate.',
                    'forAll' => $forAll,
                    'subscription' => $subscription,
                ])->setStatusCode(201); 
            }
        }

        $validityDate = $payload->validity_date;
        $maxUsage = $payload->max_usage;
        $discount = $payload->discount;
        $type = $payload->use_percentage? 'percentage': 'fixed';
        $subscription = $payload->subscription;
        $range = $payload->range;

        DB::beginTransaction();

        // preparing user data to be saved on database
        $subscriptionCouponData = array(
            'validity_date' => date('Y-m-d', strtotime($validityDate)),
            'max_usage' => $maxUsage,
            'discount' => $discount,
            'range' => $range,
            'type' => $type,
        );
        // update subscription rate data to subscription_rates table
        $subscriptionCouponTransaction = CompanySubscriptionCoupons::where('id', $id)->update($subscriptionCouponData);

        $couponSubscsriptionRateData = array(
            'company_subscription_rates_id' => $forAll? 0 : $subscription, // 0 means available for all
            'for_all' => $forAll,
        );

        $couponSubscsriptionRateTransction = CouponSubscsriptionRate::where('coupon_id', $id)->update($couponSubscsriptionRateData);

        if(!$couponSubscsriptionRateTransction || !$subscriptionCouponTransaction){
            DB::rollback();
            return response()->json([
                'error' => 'Something went wrong.',
            ])->setStatusCode(201);
        }else{  
            DB::commit();
            return response()->json([
                'success' => 'Data updated successfully.',
            ])->setStatusCode(201);
        }
    }

    public function enableDisableData($payload, $id)
    {
        $isDisabled = $payload->is_disabled;
        $subscriptionCouponData = array(
            'is_disabled' => $isDisabled,
        );
        CompanySubscriptionCoupons::whereId($id)->update($subscriptionCouponData);

        return response()->json(['success' => 'Data updated successfully.'])->setStatusCode(201);
    }
}
