<?php

namespace App\Http\Controllers;

use App\Http\Component\AppController;
use App\Http\Services\CouponService;
use App\Models\AdminNotification;
use App\Models\Investment;
use App\Models\Plan;
use App\Models\Transaction;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Services\WalletServices;
use App\Models\Team;
use Illuminate\Support\Facades\Validator;

class ProductController extends AppController
{
    private $wallet;
    private $activeTemplate;
    private $coupon;

    public function __construct(
        WalletServices $wallet,
        CouponService $coupon
    )
    {
        $this->activeTemplate = activeTemplate();
        $this->wallet = $wallet;
        $this->coupon = $coupon;
    }


    function plan(){

        $pageTitle = 'Orders';
        $user = Auth::user();
		$currency = config('settings')->cur_text;
		
        $userBalance = $this->wallet->getBalanceRaw($user, $currency);
		
        if($userBalance instanceOf \Exception) {
            $notify[] = ['error', $userBalance->getMessage()];
            return back()->withNotify($notify);
        }

        $plans = Plan::where('platform', config('settings')->active_template)->where(['status' => 1])->orderBy('min_amount')->get();
        $totalBuy = Investment::where(['user_id' => $user->id])->count();
        $userCount = User::count();

        $emptyMessage = 'Data Not Found';
        return view($this->activeTemplate. 'user.plans', compact(
            'pageTitle',
            'user',
            'currency',
            'plans',
            'totalBuy',
            'userCount',
            'userBalance'
        ));

    }

    public function planRequest(Request $request){
        // Validate
        $validator = Validator::make($request->all(),[
            'id' => 'required',
            'coupon' => 'nullable|string',
            'pay_with' => 'required|string'
        ]);

        // Failed to validate
        if ($validator->fails()) {
            $errors = $validator->errors()->all();
            $notify[] = ['error', implode(' ', $errors)];
            return $this->handleResponse($request, implode(' ', $errors), 401, $notify);
        }

        $user = auth()->user();

        $findPlan = Plan::where('id', $request->id)->where('status', 1)->first();

        if(!$findPlan){
            $notify[] = ['error', 'Package not available'];
            return $this->handleResponse($request, 'Package not available', 401, $notify);
        }

        $amount = ($request->amount) ? $request->amount : $findPlan->min_amount;

        if($findPlan->min_amount > $amount || $findPlan->max_amount < $amount){
            $notify[] = ['error', 'Amount must be between'.showAmount($findPlan->min_amount).' and '.showAmount($findPlan->max_amount)];
            return redirect()->back()->withNotify($notify);
        }
		
		/* 
		$inv = Investment::where('user_id', $user->id)->where('plan_id', $request->id)->first();

        if($inv){

            $last_time = Carbon::parse($inv->created_at);
            $now = Carbon::now();

            $difference = $last_time->diffInHours($now);
            $hours = 12;

            if($difference <= $hours){
                $next_tobuy = $hours - $difference;
                $notify[] = ['error', "You can only buy this package once every $hours hours. your next time to buy this package are $next_tobuy hours"];
                return $this->handleResponse($request, "You can only buy this package once every $hours hours. your next time to buy this package are $next_tobuy hours", 401, $notify);
            }
        }*/

        $limitBuy = 0;
        $buyLimit = (config('settings')->buy_limit && $findPlan->escape_buy_limit != 1) ? config('settings')->buy_limit : $findPlan->buy_limit;
        $buyLimitType = (config('settings')->buy_limit && $findPlan->escape_buy_limit != 1) ? config('settings')->buy_limit_type : $findPlan->buy_limit_type;
        
        // Check total purchase for request package
        if($buyLimitType) {
            $limitBuy = $findPlan->limit_buy;
            //$totalBuy = (config('settings')->buy_limit && $findPlan->escape_buy_limit != 1) ? Investment::where(['plan_id' => $findPlan->id])->whereDate('created_at', date("Y-m-d"))->count() : Investment::where(['user_id' => $user->id, 'plan_id' => $findPlan->id])->where('created_at', '>=', Carbon::now()->subHours(12))->count();
            $totalBuy = Investment::where(['user_id' => $user->id, 'plan_id' => $findPlan->id])->where('created_at', '>=', Carbon::now()->subHours(24))->count();
        }else {
            $limitBuy = config('settings')->limit_buy;
            //$totalBuy = (config('settings')->buy_limit && $findPlan->escape_buy_limit != 1) ? Investment::where(['plan_id' => $findPlan->id])->count() : Investment::where(['user_id' => $user->id, 'plan_id' => $findPlan->id])->where('created_at', '>=', Carbon::now()->subHours(12))->count();
            $totalBuy = Investment::where(['user_id' => $user->id, 'plan_id' => $findPlan->id])->where('created_at', '>=', Carbon::now()->subHours(24))->count();
        }

        // Verify purchase limit
        if($totalBuy >= $limitBuy && $buyLimit){
            $notify[] = ['error', 'Purchase limit exceed for '.$findPlan->name.', you can buy only '.$limitBuy.' times'];
            return $this->handleResponse($request, 'Purchase limit exceed for '.$findPlan->name.', you can buy only '.$limitBuy.' times', 401, $notify);
        }
		
		$uBalance = 'balance'; 
		if(config('settings')->cur_text != 'NGN'){
			$uBalance = 'usdt_balance'; 
		}

        $userBalance = $user->$uBalance;

        // Debit Balance
        if($findPlan->p_status != 'trial') {
            
            // Check Balance
            if($request->debit_wallet) {
				$walletMethod = 'get'.$request->debit_wallet;
				$userBalance = $this->wallet->$walletMethod($user, $request->pay_with);
			}else{
				$userBalance = $this->wallet->getBalance($user, $request->pay_with);
			}

            // Verify Balance
            if($userBalance instanceOf \Exception) {
                $notify[] = ['error', $userBalance->getMessage()];
                return $this->handleResponse($request, $userBalance->getMessage(), 401, $notify);
            }

            $pay_amount = $amount;

            // Coupon Discount
            $coupon_amount = null;
            $coupon_rate = 0;

            if($request->coupon) {
                // Get Couupon
                $coupon = $this->coupon->verifyCoupon($user, 'invest', $request->coupon, $amount, $findPlan->id);

                // Verify Coupon
                if($coupon instanceOf \Exception) {
                    $notify[] = ['error', $coupon->getMessage()];
                    return $this->handleResponse($request, $coupon->getMessage(), 401, $notify);
                }

                //$pay_amount = $coupon['charge']; We provide discount to income balance
                $coupon_rate = $coupon['discount_rate'];
                $coupon_amount = $coupon['discount'];
            }

            // Exchange Package amount
            if($findPlan->cur_text != $request->pay_with) {
                $exchange_pay_amount = $this->wallet->getExchangeRate($user, $pay_amount, $findPlan->cur_text, $request->pay_with);
                if($exchange_pay_amount instanceOf \Exception) throw new \Exception($exchange_pay_amount->getMessage());
                
                // Set new pay amount
                $pay_amount = $exchange_pay_amount['amount_with_fees'];
            }

            // Low Balance
            if($userBalance < $pay_amount){
                $notify[] = ['error', 'You do not have sufficient balance to pay. Please recharge your wallet'];
                return $this->handleResponseRedirect($request, 'You do not have sufficient balance to pay. Please recharge your wallet', 401, url(route('user.deposit', ['currency' => $request->pay_with])), 'user.deposit', $notify, ['currency' => $request->pay_with]);
            }

            // Debit Balance
            if($request->debit_wallet) {
				$walletMethod = 'debit'.$request->debit_wallet;
				$debitBalance = $this->wallet->$walletMethod($user, $request->pay_with, $pay_amount);
			}else{
				$debitBalance = $this->wallet->debitBalance($user, $request->pay_with, $pay_amount);
			}

            // Exception
            if($debitBalance instanceOf \Exception) {
                $notify[] = ['error',$debitBalance->getMessage()];
                //return $this->handleResponse($request,$debitBalance->getMessage(), 401, $notify);
                return $this->handleResponseRedirect($request, $debitBalance->getMessage(), 401, url(route('user.deposit', ['currency' => $request->pay_with])), 'user.deposit', $notify, ['currency' => $request->pay_with]);
            }
        }
        

        $perAnnuityInterest = 0;
        //$nextReturn = getNextDayWithTime(8, 5);
        //$nextReturn = Carbon::now()->addHours(24);
        $nextReturn = Carbon::now()->endOfDay()->subMinutes(1);
        $intAmount = $findPlan->interest_amount;

        if($findPlan->interest_type == 0){
            $perAnnuityInterest = $intAmount;
        }else{
            $perAnnuityInterest = ($amount * $intAmount) / 100;
        }

        $newInvest = new Investment();
		
		$leftMinutes = 1434;//now()->diffInMinutes($nextReturn);
		
		$nextRun = [];$max = 1; $check = []; $addRate = [];
		$cycle = $findPlan->cycle; $uInRate = $perAnnuityInterest;
		$constant = ceil($leftMinutes/$cycle);
		$interestRate = ceil($uInRate/$cycle);
		$rateHalf = ceil($interestRate/2);
		for($i=1; $i<=$cycle; $i++){
			$min = $max; $max = $constant * $i;

			$minutes = rand($min, $max);
			$nextRun[] = Carbon::now()->addMinutes($minutes)->toDateTimeString();
			
			$rMin = ($interestRate-$rateHalf); 
			$rMax = ceil($interestRate+($rateHalf/1.6)); 
			$inCycle = rand($rMin, $rMax);
			$addRate[] = $eachRate = ($i < $cycle) ? $inCycle:$uInRate;
			$uInRate -= $eachRate;
		}

		$newInvest->run_to 		= $nextRun[0];
		$newInvest->profits 	= json_encode($addRate);
		$newInvest->dates 		= json_encode($nextRun);
		$newInvest->state 		= 0; $newInvest->stop  = ($cycle-1);

		
        $newInvest->trx = getTrx();
        $newInvest->plan_id = $findPlan->id;
        $newInvest->user_id = $user->id;
        $newInvest->currency = $findPlan->cur_text;
        $newInvest->amount = $amount;
        $newInvest->capital_status = $findPlan->capital_back_status;
        $newInvest->interest_type = $findPlan->interest_type;
        $newInvest->interest_amount = $perAnnuityInterest;
        $newInvest->total_return = $findPlan->total_return;
        $newInvest->next_return_date = $nextReturn;
        $newInvest->status = 0;
        $newInvest->save();
		
		$user->invested = $user->invested + $amount;
		$user->save();
		
        //give bonus

        $transaction = new Transaction();
        $transaction->user_id = $user->id;
        $transaction->currency = $newInvest->currency;
        $transaction->amount = $amount;
        $transaction->post_balance = $userBalance;
        $transaction->charge = 0;
        $transaction->type = 'invest';
        $transaction->trx_type = '-';
        $transaction->details = 'Take part in '.$findPlan->name;//." with ".$findPlan->min_amount;
        $transaction->trx =  $newInvest->trx;
        $transaction->pay_with = $request->pay_with;
        $transaction->coupon = $request->coupon;
        $transaction->coupon_rate = $coupon_rate;
        $transaction->status = 1;
        $transaction->save();


        // Referral Commission
        if($findPlan->p_status != 'trial') {
			
			if( config('settings')->commission_type == 'referral' || config('settings')->commission_type == 'both' ){
				$earnWallet = ( config('settings')->active_template == 'gmg' ) ? 0 : 2;

				$creditBonus = referralComission($user, $newInvest->currency, $amount, $earnWallet);
				// Update Invest
				if($creditBonus instanceof Transaction) {
					$newInvest->ref_bonus = $creditBonus->amount;
					$newInvest->save();
				}
			}
        }

        // Coupon Bonus
        if($coupon_amount) give_bonus($user->id, 2, $findPlan->cur_text, $coupon_amount, "Coupon bonus from ".$findPlan->name, 2);

        $adminNotification = new AdminNotification();
        $adminNotification->user_id = $user->id;
        $adminNotification->title = 'New Investment In '.$findPlan->name.' from '.$user->username;
        $adminNotification->click_url = urlPath('admin.users.investment',$user->id);
        $adminNotification->save();

        /*notify($user, 'INVESTMENT', [
            'currency' => $transaction->currency,
            'trx' => $transaction->trx,
            'plan' => $findPlan->name,
            'amount' => $amount,
            'details' => $transaction->details,
            'post_balance' => $userBalance,
            'interest' => $perAnnuityInterest,
            'total_return' => $newInvest->total_return
        ]);*/

        $notify[] = ['success', 'Successfully bought '.$findPlan->name];
        return $this->handleResponseRedirect($request, 'Successfully bought '.$findPlan->name, 200, url(route('user.investment.log')), 'user.investment.log', $notify);

    }

    public function investNow($id = null){
        // Find Plan
        $plan = Plan::where(['identifier' => $id, 'status' => 1])->first();
		
        $user = auth()->user();

        // Verify
        if(empty($plan)) {
            $notify[] = ['error', 'Product not found'];
            return back()->withNotify($notify);
        }
        $userBalance = $this->wallet->getBalanceRaw($user, config('settings')->cur_text);
		
        if($userBalance instanceOf \Exception) {
            $notify[] = ['error', $userBalance->getMessage()];
            return back()->withNotify($notify);
        }

        $buyLimitType = (config('settings')->buy_limit && $plan->escape_buy_limit != 1) ? config('settings')->buy_limit_type : $plan->buy_limit_type;

        // Count Plan Purchase
        if($buyLimitType) {
            //$boughtCount = (config('settings')->buy_limit && $plan->escape_buy_limit != 1) ? Investment::where(['plan_id' => $plan->id])->where('created_at', '>=', Carbon::now()->subHours(12))->count() : Investment::where(['user_id' => $user->id, 'plan_id' => $plan->id])->whereDate('created_at', date("Y-m-d"))->count();
            $boughtCount = Investment::where(['user_id' => $user->id, 'plan_id' => $plan->id])->where('created_at', '>=', Carbon::now()->subHours(24))->count();
        }else {
            //$boughtCount = (config('settings')->buy_limit && $plan->escape_buy_limit != 1) ? Investment::where(['plan_id' => $plan->id])->count() : Investment::where(['user_id' => $user->id, 'plan_id' => $plan->id])->where('created_at', '>=', Carbon::now()->subHours(12))->count();
            $boughtCount = Investment::where(['user_id' => $user->id, 'plan_id' => $plan->id])->where('created_at', '>=', Carbon::now()->subHours(24))->count();
        }

        $pageTitle = $plan->name;
        
        return view($this->activeTemplate.'user.view_plan', compact('pageTitle', 'plan', 'userBalance', 'boughtCount'));
    }

}
