<?php

namespace App\Http\Controllers;

use App\LoopGroupUser;
use App\LoopGroupUserPaid;
use App\Notifications\LoopUserNotification;
use App\User;
use App\UserWallet;
use Illuminate\Support\Facades\DB;

class LoopUserController extends Controller
{
    /**
     * Send Notification to users to pay thier shares for thier loops
     * 1- Get users subscribed to loops, and thier subscribtion is active
     * 2- Get how many months they have not paid yet
     *
     * @return \Illuminate\Http\Response
     */

    public static function payForLoop(bool $warn= false)
    {
        // This check for the first run only, but after that the cron will handel it
        $warningDay=json_decode(settings('fees'))->warning_day;
        if ((int)date('d') != 1 || $warningDay != (int)date('d')) {
            return 'not now';
        }

        DB::enableQueryLog();

        $query= LoopGroupUser::where('status', 'active')
        ->whereRaw("DATE_ADD(DATE_FORMAT(created_at,'%Y-%m-01'), INTERVAL `period` MONTH) >= CURDATE()")
        ->selectRaw('*')
        ->addSelect(DB::raw("
        DATE_FORMAT(created_at,'%Y-%m-01') AS loop_date,
        MONTH(CURDATE()) AS current_month,
        (SELECT loop_id FROM loop_groups lg WHERE lg.id = loop_group_users.loop_group_id LIMIT 1) AS loop_id,
        (SELECT month FROM loop_group_user_paids lgup WHERE lgup.loop_group_user_id = loop_group_users.id ORDER BY created_at DESC LIMIT 1) AS last_paid_month"));

        if($warn){
            $type= 'warn';
        }else{
            $type= 'pay';
        }

        $query->whereRaw("user_id NOT IN (SELECT notifiable_id FROM notifications WHERE JSON_EXTRACT(`data`, '$.loop_group_id') = loop_group_id AND JSON_EXTRACT(`data`, '$.month') = MONTH(CURDATE()) AND JSON_EXTRACT(`data`, '$.type') = '{$type}' )");

        $users= $query->get();
        // dd(DB::getQueryLog());
        // dd($users->toArray());
        $usersMustPay=[];

        $fees= settings('fees');
        $fees= $fees && json_decode($fees) ? json_decode($fees, true) : [];
        $settingDelayFees= (float) $fees['delay_fees'] ?? 0;

        foreach ($users->toArray() as $user) {

            $payUnPaidShare = self::payUnPaidShare($user, $settingDelayFees);
            $unpaidMonths= $payUnPaidShare['unpaidMonths'];
            // dd($unpaidMonths);

            if ($unpaidMonths == 0) {
                continue;
            }

            if ($warn) {
                $message= sprintf(__('loops.late_for_loop'), $unpaidMonths , $user['loop_date']);
            } else {
                $message= sprintf(__('loops.pay_for_loop'), $user['current_month'] , $user['loop_date']);
            }

            $user= $user + ['type'=> $type, 'message'=> $message, 'month'=> $user['current_month'], 'unpaidMonths'=> $unpaidMonths];

            $usersMustPay[]= $user;
            $userInfo= User::find($user['user_id']);
            $userInfo->notify(new LoopUserNotification($user));
        }
        // dd($usersMustPay);
        return 'Done on '.date('D d F Y');
    }
    /**
     * Send Notification to users to inform them the thier profit ransfered to thier wallett
     * 1- Get users subscribed to loops, and thier subscribtion
     *
     * 2- check the susbcribtion status
     *
     * 2.1- If the status is active, Get how many months they have not paid yet
     * 2.2- get the delay fees of the months,
     *  and add the total of unpaid months plus delay fees into the wallet in negative values
     * 2.3- add records of un-paid months to loop_group_user_paids to mark them as paid
     * 2.3- add shares of un-paid months to UserWallet in negative value
     *
     * 3- Add Profit
     *
     * 3.1- If status is active, add the profit as 'profit= share * period' to the wallet in positive value
     * 3.2- If the status is cancelled, add the profit as `profit= share * paid months`
     *
     * 4- store loop_id, loop_group_user_id in the meta of the wallet
     *
     * 5- send notificatio to the users
     *
     * @return \Illuminate\Http\Response
     */

    public static function transferLoopProfit()
    {
        // This check for the first run only, but after that the cron will handel it
        if ((int)date('d') != 6) {
            return 'not now';
        }

        DB::enableQueryLog();
        $type= 'encashment';
        // Get users deserved to be paid, as thier encashment maonth was the previous month
        $query= LoopGroupUser::selectRaw('*')
        // ->whereRaw("DATE_FORMAT(encashment_month,'%Y-%m-01') = DATE_FORMAT(DATE_SUB( CURDATE(), INTERVAL 1 MONTH),'%Y-%m-01')")
        ->where('get_paid', 0)
        ->whereRaw("DATE_FORMAT(encashment_month,'%Y-%m-01') = DATE_FORMAT(CURDATE(),'%Y-%m-01')")
        ->whereRaw("user_id NOT IN (SELECT notifiable_id FROM notifications WHERE JSON_EXTRACT(`data`, '$.loop_group_id') = loop_group_id AND JSON_EXTRACT(`data`, '$.month') = MONTH(CURDATE()) AND JSON_EXTRACT(`data`, '$.type') = '{$type}' )")
        ->addSelect(DB::raw("
        DATE_FORMAT(created_at,'%Y-%m-01') AS loop_date,
        MONTH(CURDATE()) AS current_month,
        (SELECT loop_id FROM loop_groups lg WHERE lg.id = loop_group_users.loop_group_id LIMIT 1) AS loop_id,
        (SELECT COUNT(id) FROM loop_group_user_paids lgup WHERE lgup.loop_group_user_id = loop_group_users.id LIMIT 1) AS paid_months,
        (SELECT month FROM loop_group_user_paids lgup WHERE lgup.loop_group_user_id = loop_group_users.id ORDER BY created_at DESC LIMIT 1) AS last_paid_month
        "));

        $users= $query->get();
        // dd(DB::getQueryLog());
        // dd($users->toArray());
        $usersGotCashed= [];
        $fees= settings('fees');
        $fees= $fees && json_decode($fees) ? json_decode($fees, true) : [];
        $settingDelayFees= (float) $fees['delay_fees'] ?? 0;

        foreach ($users->toArray() as $user) {

            $months= $user['status'] == 'cancelled' ? $user['paid_months'] : $user['period'];

            if ($months == 0) {
                continue;
            }

            $total = ceil( $user['share'] * $months );
            // dd($total);
            $message= sprintf(__('loops.cash_your_loop'), $total, $user['loop_date']);

            $userInfo= User::find($user['user_id']);
            // dd($user['user_id'], $userInfo->toArray());
            $user= $user + ['type'=> $type, 'message'=> $message, 'month'=> $user['current_month'], 'months'=> $months];

            $usersGotCashed[]= $user;
            $userInfo->notify(new LoopUserNotification($user));

            $walletData= [
                'user_id' => $user['user_id'],
                'amount' => $total,
                'description' => $message,
                'meta'=> [
                    'type'=> $type,
                    'loop_id'=> $user['loop_id'],
                    'loop_group_id'=> $user['loop_group_id'],
                    'loop_group_user_id'=> $user['id'],
                    "share" => $user['share'],
                    "period" => $user['period'],
                    "months" => $months,
                    "total" => $total
                ]
            ];
            // dd($walletData);

            UserWallet::create($walletData);

            // set loop_group_user  as paid
            LoopGroupUser::where('id', $user['id'])->update(['get_paid'=> 1]);

            # Check status
            if ('active' == $user['status']) {
                $payUnPaidShare = self::payUnPaidShare($user, $settingDelayFees);
                $unpaidMonths= $payUnPaidShare['unpaidMonths'];
                // dd($unpaidMonths);
            } else {
                // set store paid months as done paid
                LoopGroupUserPaid::where('loop_group_user_id', $user['id'])->update(['done'=> true]);
            }

        }
        // dd($usersGotCashed);
        return 'Done on '.date('D d F Y');
    }

    /**
     * Pay Share
     */
    public static function payUnPaidShare($user, $settingDelayFees)
    {
        // dd($user);
        $lastMonth= $user['last_paid_month'] ? $user['last_paid_month'] : (date('m', strtotime($user['loop_date'].' -1 month')) );

        $unpaidMonths= $user['current_month'] - $lastMonth;
        // dd($unpaidMonths);
        $userInfo= User::find($user['user_id']);
        // dd($user['user_id'], $userInfo->toArray());
        $totalBalance= $userInfo->wallet->pluck('amount')->sum();
        // dd($totalBalance);

        if ($unpaidMonths == 0 || $totalBalance <= 0) {
            return [
                'unpaidMonths'=> $unpaidMonths,
                'totalBalance'=> $totalBalance,
            ];
        }

        if ($unpaidMonths<0) {
            $unpaidMonths = $unpaidMonths + 12;
        }

        $delayFees= $user['share'] * $settingDelayFees/100;
        $delayFees= ceil($delayFees * ($unpaidMonths - 1) );
        $subtractShare= $delayFees + $user['share'];
        $totalBalance = $totalBalance - $subtractShare;

        // dd($totalBalance, $subtractShare, $unpaidMonths, $lastMonth, $settingDelayFees, $delayFees);

        // 2.3- Add unpaid months
        // Insert unpaid in loop_group_user_paids
        $totalPaid= 0;
        $paidMonth= 0;

        if( $totalBalance >= 0 ){
            $lastPaidMonth= $lastMonth;
            $paidMonths= [];

            for ($i= 0; $i < $unpaidMonths ; $i++) {
                $paidMonth++;
                $lastPaidMonth = $lastPaidMonth + 1;

                if ($lastPaidMonth == 13) {
                    $lastPaidMonth = 1;
                }
                $paidMonths[]= $lastPaidMonth;

                $data= [
                    'loop_group_user_id'=> $user['id'],
                    'month'=> $lastPaidMonth,
                    'done' => true
                ];
                LoopGroupUserPaid::create($data);
                if($i < ($unpaidMonths - 1) ){
                    $totalBalance = $totalBalance - $user['share'];
                    if ($totalBalance < 0 ) {
                        break;
                    }
                    $subtractShare = $subtractShare - $user['share'];
                }
            }

            // dd($totalBalance, $subtractShare);
            // dd( $paidMonth, $unpaidMonths, $paidMonths);
            // Add Shares
            $message= sprintf(__('loops.pay_share_of_loop'), $paidMonth, date('F Y', strtotime($user['loop_date'])) );
            $totalPaid= $subtractShare;
            $walletData= [
                'user_id' => $user['user_id'],
                'amount' => -$totalPaid,
                'description' => $message,
                'meta'=> [
                    'type'=> 'pay_share',
                    'loop_id'=> $user['loop_id'],
                    'loop_group_id'=> $user['loop_group_id'],
                    'loop_group_user_id'=> $user['id'],
                    "share" => $user['share'],
                    "period" => $user['period'],
                    "months" => $paidMonth,
                    "total" => $totalPaid
                ]
            ];
            // dd($walletData);
            UserWallet::create($walletData);

            $user= $user + ['type'=> 'pay_share', 'message'=> $message, 'month'=> $user['current_month'], 'months'=> $paidMonth];

            $userInfo->notify(new LoopUserNotification($user));

            $unpaidMonths -= $paidMonth;
        }
        return [
            'unpaidMonths'=> $unpaidMonths,
            'paidMonth'=> $paidMonth,
            'delayFees'=> $delayFees,
            'totalPaid'=> $totalPaid,
            'totalBalance'=> $totalBalance,
        ];
    }
}
