<?php


namespace Modules\Affiliate\Repositories;


use App\User;
use Brian2694\Toastr\Facades\Toastr;
use Browser;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Modules\Affiliate\Entities\AffiliateCommission;
use Modules\Affiliate\Entities\AffiliateConfiguration;
use Modules\Affiliate\Entities\AffiliateLink;
use Modules\Affiliate\Entities\AffiliateLinkVisitTrackUser;
use Modules\Affiliate\Entities\AffiliateUserWallet;
use Modules\Affiliate\Entities\ReferralUser;
use Modules\BundleSubscription\Entities\BundleCoursePlan;
use Modules\CourseSetting\Entities\Course;
use Modules\Subscription\Entities\CourseSubscription;
use Request;

class AffiliateRepository
{
    public function all()
    {
        $user = Auth::user();
        if ($user->role_id == 3) {
            return AffiliateLink::with(['owner', 'registerUser', 'payment'])->where('owner_id', Auth::id())->latest()->paginate(10);
        } else {
            return AffiliateLink::with(['owner', 'registerUser', 'payment'])->where('owner_id', Auth::id())->latest()->get();
        }
    }

    public function affiliateUserByCode($code)
    {
        $user = User::where('referral', $code)->first();
        $link =AffiliateLink::where('owner_id', $user?->id)->first();

          if ($user && $link) {
            return ReferralUser::create([
                'user_id' => $user->id,
                'affiliate_link_id' => $link->id,
                'validity_start_date' => now(),
            ]);
        } else {
            return false;
        }

    }

    public function create(array $data)
    {
        $user =Auth::user();
        $type =$data['commission_type']??'';

        $ref =$user->referral;

        if ($type == 'common') {
            $url = $data['url']??'';
            $refUrl= $this->addParameterToUrl($url, 'ref', $ref);
          AffiliateLink::updateOrCreate([
              'affiliate_link' => $refUrl,
          ],[
                'affiliate_link' => $refUrl,
                'owner_id' => $user->id,
                'type' => 'common',
                'url' => $url,
                'ref' => $ref,
            ]);
        }elseif ($type=="course"){
            foreach ((array)$data['course'] as $key => $value) {
                $course =Course::select('id','type','slug')->find($value);
                if ($course){
                    $commission = AffiliateCommission::where('commable_type',Course::class)
                        ->where('commable_id',$course->id)
                        ->first();
                    if (!$commission){
                        Toastr::error(__('affiliate.Commission Not Set For').' '.$course->title,__('common.Error'));
                        continue;
                    }
                    $url = courseDetailsUrl($course->id,$course->type,$course->slug);
                    $refUrl= $this->addParameterToUrl($url, 'ref', $ref);
                    AffiliateLink::updateOrCreate([
                        'affiliate_link' => $refUrl,
                    ],[
                        'affiliate_link' => $refUrl,
                        'owner_id' => $user->id,
                        'type' => 'course',
                        'url' => $url,
                        'ref' => $ref,
                        'topic_id'=>$value
                    ]);
                }
            }
        }elseif ($type=="bundle"){
            foreach ((array)$data['bundle'] as $key => $value) {
                $bundle = BundleCoursePlan::select('id')->find($value);
                if ($bundle){
                    $commission = AffiliateCommission::where('commable_type',BundleCoursePlan::class)
                        ->where('commable_id',$bundle->id)
                        ->first();
                    if (!$commission){
                        Toastr::error(__('affiliate.Commission Not Set For').' '.$bundle->title,__('common.Error'));
                        continue;
                    }

                    $url =route('bundle.show').'?id='.$bundle->id;
                    $refUrl= $this->addParameterToUrl($url, 'ref', $ref);
                    AffiliateLink::updateOrCreate([
                        'affiliate_link' => $refUrl,
                    ],[
                        'affiliate_link' =>  $this->addParameterToUrl($url, 'ref', $ref),
                        'owner_id' => $user->id,
                        'type' => 'bundle',
                        'url' => $url,
                        'ref' => $ref,
                        'topic_id'=>$value
                    ]);
                }
            }
        }elseif ($type=="subscription"){
            foreach ((array)$data['subscription'] as $key => $value) {
                $plan = CourseSubscription::select('id')->find($value);
                if ($plan){
                    $commission = AffiliateCommission::where('commable_type',CourseSubscription::class)
                        ->where('commable_id',$plan->id)
                        ->first();
                    if (!$commission){
                        Toastr::error(__('affiliate.Commission Not Set For').' '.$plan->title,__('common.Error'));
                        continue;
                    }

                    $url =route('courseSubscription').'?plan='.$plan->id;
                    $refUrl= $this->addParameterToUrl($url, 'ref', $ref);
                    AffiliateLink::updateOrCreate([
                        'affiliate_link' => $refUrl,
                    ],[
                        'affiliate_link' =>  $this->addParameterToUrl($url, 'ref', $ref),
                        'owner_id' => $user->id,
                        'type' => 'subscription',
                        'url' => $url,
                        'ref' => $ref,
                        'topic_id'=>$value

                    ]);
                }
            }
        }

    }

    public function addParameterToUrl($url, $paramName, $paramValue) {
        // Parse the URL and its components
        $urlComponents = parse_url($url);

        // Parse the query string into an associative array
        if (isset($urlComponents['query'])) {
            parse_str($urlComponents['query'], $queryParams);
        } else {
            $queryParams = [];
        }

        // Add the new parameter to the query parameters
        $queryParams[$paramName] = $paramValue;

        // Rebuild the query string
        $urlComponents['query'] = http_build_query($queryParams);

        // Rebuild the URL
        $newUrl = (isset($urlComponents['scheme']) ? $urlComponents['scheme'] . '://' : '') .
            (isset($urlComponents['host']) ? $urlComponents['host'] : '') .
            (isset($urlComponents['port']) ? ':' . $urlComponents['port'] : '') .
            (isset($urlComponents['path']) ? $urlComponents['path'] : '') .
            (isset($urlComponents['query']) ? '?' . $urlComponents['query'] : '') .
            (isset($urlComponents['fragment']) ? '#' . $urlComponents['fragment'] : '');

        return $newUrl;
    }

    public function affiliateUser($userId)
    {
        $record = $this->checkVisitRecord();
        if ($record) {
            return ReferralUser::create([
                'user_id' => $userId,
                'affiliate_link_id' => $record->affiliate_link_id,
                'validity_start_date' => $record->date,
            ]);
        } else {
            return false;
        }

    }

    private function checkVisitRecord()
    {
        $ip = Request::ip();
        $agent = Browser::browserFamily() . '-' . Browser::platformName() . '-' . Browser::deviceModel();
        $row = AffiliateLinkVisitTrackUser::where('ip', $ip)->where('agent', $agent)->latest()->first();
        if ($row) {
            return $row;
        } else {
            return false;
        }
    }

    public function configuration(array $data)
    {
        foreach ($data as $key => $value) {
            if ($key=='balance_add_account_after_days' && empty($value)){
                $value=0;
            }
            AffiliateConfiguration::updateOrCreate(
                ['key' => $key],
                ['value' => $value]
            );
        }

        Cache::forget('affiliate_config_' . SaasDomain());

        $data = [];
        foreach (AffiliateConfiguration::get() as $setting) {
            $data[$setting->key] = $setting->value;
        }
        Cache::rememberForever('affiliate_config_' . SaasDomain(), function () use ($data) {
            return $data;
        });

        return true;
    }

    public function getPaypalAccount()
    {
        return AffiliateUserWallet::select('paypal_account','user_id','amount')->where('user_id' , Auth::id())->first();
    }

    public function addOrUpdatePaypalAccount(array $data)
    {
        return AffiliateUserWallet::updateOrCreate([
                'user_id' => Auth::id(),
            ],[
                'paypal_account' => $data['paypal_account'],
            ] );
    }

    public function getStatistics($user, $startDate = null, $endDate = null)
    {
        $data['current_balance'] = showPrice($user->affiliateWallet?->amount);
        if ($startDate && $endDate) {
            $commissions = $user->affiliateCommissions->whereBetween('date', [$startDate, $endDate]);
            $transactions = $user->affiliateTransaction->whereBetween('confirm_date', [$startDate, $endDate]);
        } else {
            $commissions = $user->affiliateCommissions;
            $transactions = $user->affiliateTransaction;
        }
         $data['total_earning'] = showPrice($commissions->where('status', 1)->sum('amount'));
        $data['pending_earning'] = showPrice($commissions->where('status', 0)->sum('amount'));
        $data['total_withdraw'] = $transactions->where('status', 1)->where('payment_type', '!=', 3)->sum('withdraw_amount');
        $data['pending_withdraw'] = $transactions->where('status', 0)->where('payment_type', '!=', 3)->sum('withdraw_amount');
        $data['total_transfer'] = $transactions->where('status', 1)->where('payment_type', 3)->sum('withdraw_amount');
        $data['pending_transfer'] = $transactions->where('status', 1)->where('payment_type', 3)->sum('withdraw_amount');


        return $data;
    }

}
