<?php

namespace App\Http\Controllers;

use App\Classes\Accounting\Accounting;
use App\Classes\EditLogHistory;
use App\Models\Client;
use App\Models\Employee;
use Exception;
use Carbon\Carbon;
use App\Models\Pop;
use App\Models\User;
use App\Models\Reseller;
use App\Models\Permission;
use App\Models\User_details;
use Illuminate\Http\Request;
use App\Models\UserAccounting;
use App\Models\user_has_reseller;
use Database\Seeders\UserHasRole;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Role;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Artisan;
use App\Models\User_has_reseller as ModelsUser_has_reseller;
use Brian2694\Toastr\Toastr as ToastrToastr;
use Illuminate\Support\Facades\Auth;

class UserController extends Controller
{

    public function __construct()
    {
        $this->middleware('permission:user_index|user-registration|user_edit', ['only' => ['index', 'show', 'edit']]);
        $this->middleware('permission:user-registration', ['only' => ['create']]);
        $this->middleware('permission:user_edit', ['only' => ['edit']]);
    }

    public function index()
    {
        $user = auth()->user();
        if ($user->hasRole(['Administer Sub Reseller'])) {
            $userlist = User::with('userdetails', 'role')->whereHas('roles', function ($q) {
                $q->where('name', 'Sub Reseller');
            });
        } else {

            $userlist = User::with('userdetails', 'role');
        }

        if ($user->getPermissionsViaRoles('user_index') != true) {
            return redirect()->route('dashboard');
        }

        if ($user->hasRole(['Sub Reseller'])) {
            $userlist->where('id', $user->id);
        }

        if ($user->hasRole(['Reseller Admin', 'Reseller'])) {
            $resellerlist =  DB::table('reseller_user')->where('user_id', $user->id)->pluck('reseller_id')->toArray();
            $ulist = DB::table('reseller_user')->whereIn('reseller_id', $resellerlist)->pluck('user_id')->toArray();
            $userlist->whereIn('id', $ulist);
        }

        // dd($userlist->get());



        if ($user->id == 1) {
            $userlist = $userlist->get();
        } else {

            $userlist = $userlist->where('id', '!=', 1)
                ->where('email', '!=', "account@bkash.com")
                ->where('email', '!=', "user@bkash.com")
                ->where('email', '!=', "Bkash-Online@demo.com")
                ->where('email', '!=', "Nagad-Online@demo.com")
                ->get();
        }
        //This for chcke who edit
        $user_with_has = [];
        foreach ($userlist as $user) {
            $user_with_has[$user->id] = $user->name;
        }

        // dd($user_with_has);
        return view('user.index', [
            'users' => $userlist->where('email', '!=', 'admin@billingfix.xyz'),
            'all_user' => $user_with_has,
            'page_title' => 'All User List'
        ]);
    }


    public function create(User $user)
    {

        if (!auth()->user()->hasPermissionTo('assign-permission')) {
            if ($user->id != auth()->user()->id) {
                abort(403);
            }
        }

        if (Auth::user()->email == 'admin@gmail.com') {
            $roles = Role::where('name', '!=', 'Admin')->where('name', '!=', 'SoftwareAdmin')->get();
        } else {
            $roles = Role::where('name', '!=', 'SoftwareAdmin')->get();
        }

        if (Auth::user()->hasRole(['Administer Sub Reseller'])) {
            $roles = Role::where('name', '=', 'Sub Reseller')->get();
        }


        if ($user->getPermissionsViaRoles('user-registration')) {
            return view('user.create', [
                'page_title' => 'Create new User',
                'roles' => $roles,
                'resellers' => Reseller::get(),
            ]);
        } else {
            return redirect()->route('dashboard');
        }
        // $roles = Role::pluck('name','name')->all();

    }


    public function store(Request $request)
    {

        if (!auth()->user()->hasPermissionTo('assign-permission')) {
            if ($user->id != auth()->user()->id) {
                abort(403);
            }
        }

        // dd($request->all());
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|confirmed|min:8',
            'mobile_number' => 'digits:11',
        ]);



        DB::beginTransaction();

        try {
            $user = User::create([
                'name' => $request->name,
                'email' => $request->email,
                'password' => Hash::make($request->password),
                'user_balance_check' => 'no',
                'user_accounting_status' => $request->user_accounting_status,
                'mobile_number' => $request->mobile_number,
                'minimum_recharge_day' => $request->minimum_recharge_day,
            ]);

            $employee = new Employee();
            $employee->name = $user->name;
            $employee->user_id = $user->id;
            $employee->admin_user_id = $user->id;
            $employee->mobile_office = $user->mobile_number;

            if ($request->user_accounting_status == 'yes') {
                $employee->status = 'active';
            } else {
                $employee->status = 'pending';
            }

            $employee->save();
            clearCache('employees');

            $status =  DB::table('user_details')->insert([
                'user_id' => $user->id,
                'company' => $request->company,
                'message' => $request->message,
                'token_admin' => 'no',
                'user_status' => 'active',
                'last_edit_by' => auth()->user()->id,
            ]);

            if ($request->assign_role != null) {

                // assign role
                $user->assignRole($request->input('assign_role'));

                // assign reseller
                if ($request->assign_reseller != null) {
                    $reseller = collect($request->assign_reseller);
                    $user->resellers()->sync($reseller->toArray());
                }


                // assign pop
                if (in_array(11, $request->assign_role)) {
                    if ($request->assign_pop != null) {
                        $pops = collect($request->assign_pop);
                        $user->pops()->sync($pops->toArray());
                    }
                }
            }

            DB::commit();
            Cache::forget('user_list');

            return redirect()->route('user.index')->with('success_message', 'User Created Successfull');
        } catch (Exception $e) {
            dd($e);
            DB::rollback();
            return redirect()->route('user.index')->with('error_message', 'Something is worong');
        }
    }

    public function show($id)
    {
        //
    }

    public function edit(User $user)
    {

        if (!auth()->user()->hasPermissionTo('assign-permission')) {
            if ($user->id != auth()->user()->id) {
                abort(403);
            }
        }



        return view('user.edit', [
            'page_title' => 'Update User Info',
            'r'       => $user
        ]);
    }

    public function update(Request $request, $id)
    {
        // dd($request->all());
        if (Auth::user()->email != 'admin@gmail.com') {

            $this->validate($request, [
                'name' => 'required',
                'email' => 'required|email|unique:users,email,' . $id,
                'mobile_number' => 'digits:11',
            ]);

            DB::beginTransaction();

            try {

                // $user = User::whereId($id)->update([
                //     'name' => $request->name,
                //     'email' => $request->email,
                //     'user_accounting_status' => $request->user_accounting_status,
                //     'mobile_number' => $request->mobile_number
                // ]);

                $type = 'AdminUser';
                $old_info = User::where('id', $id)->first();
                $user = User::find($id);
                $user->name = $request->name;

                if ($user->email != 'rokibulhasan.356@gmail.com') {
                    $user->email = $request->email;
                }

                $user->user_accounting_status = $request->user_accounting_status;
                $user->mobile_number = $request->mobile_number;
                $user->minimum_recharge_day = $request->minimum_recharge_day;

                if ($user->email != 'rokibulhasan.356@gmail.com') {
                    if (auth()->user()->hasPermissionTo('assign-permission')) {
                        if ($request->user_status == 'active') {
                            $user->isActive = 'yes';
                        } else {
                            $user->isActive = 'no';
                        }
                    }
                }

                $user->save();

                DB::table('user_details')
                    ->where('user_id', $id)
                    ->updateOrInsert(
                        [
                            'user_id' => $id,

                        ],
                        [
                            'company' => $request->company,
                            'message' => $request->message,
                            'last_edit_by' => auth()->user()->id,
                        ],

                    );
                if ($user->email != 'rokibulhasan.356@gmail.com') {
                    if (auth()->user()->hasPermissionTo('assign-permission')) {
                        DB::table('user_details')
                            ->where('user_id', $id)
                            ->update(
                                [
                                    'user_status' => $request->user_status
                                ]
                            );
                    }
                }
                $new_info = User::find($user->id);
                (new EditLogHistory)->editLogSave($user, $type, $old_info, $new_info);

                DB::commit();

                Cache::forget('user_list');

                // return redirect()->route('user.index')->with('success_message', 'User Update Successfull');
                Toastr::success('User Update Successfull', 'Success');
                return redirect()->back();
            } catch (Exception $e) {
                dd($e);
                DB::rollback();
                return redirect()->route('user.index')->with('error_message', 'Something is worong');
            }
        } else {

            Toastr::error("You can't change any Information");
            return back();
        }
    }


    public function destroy($id)
    {
        //
    }


    public function passwordReset($email)
    {
        $user = User::where('email', $email)->first();
        return view('user.passwordReset', [
            'page_title' => 'User Password Reset',
            'r'       => $user
        ]);
    }

    public function passwordUpdate(Request $request)
    {
        if (checkSettings('never_change_admin_password') == 'enable' || $request->email == 'rokibulhasan.356@gmail.com') {
            Toastr::error('You can not change admin password');
            return redirect()->back();
        }
        if (Auth::user()->email != 'admin@gmail.com') {

            $user = User::where('email', $request->email)->first();

            $request->validate([
                'password' => 'required|string|confirmed|min:8',
            ]);
            DB::beginTransaction();

            try {
                $type = 'AdminUser';
                $old_info = User::where('id', $user->id)->first()->toArray();
                $old_info['password'] = "old password hidden for security reason";



                $user_detils = User_details::where('user_id', $user->id)->firstOrCreate(
                    [
                        'user_id' => $user->id,
                    ],
                    [
                        'user_id' => $user->id,
                        'last_edit_by' => auth()->user()->id,
                    ]
                );

                $user_detils->last_edit_by = auth()->user()->id;
                $user_detils->save();

                User::whereId($user->id)->update([
                    'password' => Hash::make($request->password)
                ]);

                $new_info = User::find($user->id)->toArray();
                $new_info['password'] = "new password hidden for security reason";

                (new EditLogHistory)->editLogSave($user, $type, $old_info, $new_info);
                DB::commit();

                Cache::forget('user_list');

                Toastr::success('Success! Your Password has been changed!', 'Success');
                return redirect()->back();
            } catch (Exception $e) {

                DB::rollBack();
                Toastr::error("some problem happen");
                return back();
            }
        } else {

            Toastr::error("You can't change admin password");
            return back();
        }
    }


    public function assignReseller($id)
    {
        $user = User::with('resellers')->find($id);



        return view('user.resellerAssign', [
            'page_title' => 'Assign Reseller',
            'user'       => $user,
            'reseller'   => Reseller::all()
        ]);
    }


    public function assignResellerUpdate(Request $request, $id)
    {
        DB::beginTransaction();
        try {

            $user = User::find($id);

            $user_detils = User_details::where('user_id', $user->id)->first();
            $user_detils->last_edit_by = auth()->user()->id;
            $user_detils->save();

            $reseller = collect($request->reseller);
            $user->resellers()->sync($reseller->toArray());

            DB::commit();

            Artisan::call('cache:clear');
            return redirect()->back()->with('success_msessage', 'Assigned Success');
        } catch (Exception $e) {
            DB::rollBack();
            Toastr::error("some problem happen");
            return back();
        }
    }

    public function assignPop($id)
    {
        $user = User::with('pops')->find($id);



        return view('user.popAssign', [
            'page_title' => 'Assign Pop',
            'user'       => $user,
            'pops'   => Pop::popForReseller($user)->get()
        ]);
    }


    public function assignPopUpdate(Request $request, $id)
    {

        // dd($request->all());
        DB::beginTransaction();
        try {
            $user = User::find($id);

            $user_detils = User_details::where('user_id', $user->id)->first();
            $user_detils->last_edit_by = auth()->user()->id;
            $user_detils->save();

            $pops = collect($request->pop);
            $user->pops()->sync($pops->toArray());

            DB::commit();

            Artisan::call('cache:clear');

            return redirect()->back()->with('success_msessage', 'Assigned Success');
        } catch (Exception $e) {
            DB::rollBack();
            Toastr::error("some problem happen");
            return back();
        }
    }


    public function view_user_account_history(Request $request, $id)
    {


        $start = Carbon::parse(now()->startOfMonth())->format('Y-m-d 00:00:00');


        $end = Carbon::parse(today())->format('Y-m-d 23:59:59');
        $accounts = UserAccounting::where('user_id', $id)->whereBetween('created_at', [$start, $end])->orderBy('created_at', 'asc');
        $opening_balance = UserAccounting::where('user_id', $id)->whereRaw("created_at < '$start'")->sum('received_amount');

        // dd($opening_balance);

        return view('user.accountHistory', [
            'page_title' => 'User Accounts Information',
            'accounts'   => $accounts->get(),
            'opening_balance' => $opening_balance,
            'start' => Carbon::now()->startOfMonth(),
            'end' => today(),
            'id' => $id
        ]);
    }

    public function view_user_account_history_search(request $request, $id)
    {
        // dd($request->all());
        $start = Carbon::parse($request->from_date)->format('Y-m-d 00:00:00');
        $end = Carbon::parse($request->to_date)->format('Y-m-d 23:59:59');

        $client = Client::where('userid', $request->userName)->first();
        if ($client != null) {
            $accounts = UserAccounting::where('user_id', $id)->where('client_id', $client->id)->whereBetween('created_at', [$start, $end])->orderBy('created_at', 'asc');
            // dd($accounts->get());
        } else {
            if ($client == null && $request->userName) {
                Toastr::error('No Client Found', 'Error');
                return redirect()->back();
            } else {
                $accounts = UserAccounting::where('user_id', $id)->whereBetween('created_at', [$start, $end])->orderBy('created_at', 'asc');
            }
        }

        $details = UserAccounting::where('user_id', $id)->whereRaw("created_at < '$start'");
        $receive = $details->sum('received_amount');

        $send = $details->sum('paid_amount');

        $opening_balance = $receive - $send;



        return view('user.accountHistory', [
            'page_title' => 'User Accounts Information',
            'accounts'   => $accounts->get(),
            'opening_balance' => $opening_balance,
            'start' => Carbon::parse($request->from_date),
            'end' => Carbon::parse($request->to_date),
            'id' => $id
        ]);
    }

    public function userCustomerSummary($id)
    {
        $user = User::find($id);

        if (Auth::user()->hasRole(['Reseller Admin', 'Reseller', 'Sub Reseller'])) {
            $resellerlist =  DB::table('reseller_user')->where('user_id', $user->id)->pluck('reseller_id')->toArray();
            $ulist = DB::table('reseller_user')->whereIn('reseller_id', $resellerlist)->pluck('user_id')->toArray();
            if (!in_array(Auth::user()->id, $ulist)) {
                Toastr::error('You are not authorized to view this page', 'Error');
                return redirect()->route('user.index');
            }
        }

        $resellers = Reseller::orderBy('id', 'asc')->with('pops', 'reseller_user');

        if ($user->hasRole(['Reseller Admin', 'Reseller', 'Sub Reseller'])) {
            $resellers->whereHas('reseller_user', function ($q) use ($id) {
                return $q->where('user_id', $id);
            });
        }

        $reseller = $resellers->get();

        // $pops = Pop::list();

        // dd($id);
        if ($user->hasRole(['Reseller Admin', 'Reseller'])) {
            $reseller_ids = DB::table('reseller_user')->where('user_id', $id)->pluck('reseller_id')->toArray();
            $pops = Pop::with('reseller')->whereIn('reseller_id', $reseller_ids);
        } elseif ($user->hasRole('Sub Reseller')) {
            $pop_ids = DB::table('pop_user')->where('user_id', $id)->pluck('pop_id')->toArray();
            $pops = Pop::whereIn('id', $pop_ids);
        } else {
            $pops = Pop::with('reseller', 'nas', 'balance');
        }

        $pop_ids = $pops->pluck('id');


        $clientCount = Client::with('clientsinfo')
            ->select('pop_id', 'clients_status', 'client_approval', DB::raw('count(*) as total'))
            ->whereIn('pop_id', $pop_ids)
            ->groupBy('pop_id', 'clients_status', 'client_approval')
            ->get();

        $closeClientCount = Client::onlyTrashed()
            ->select('pop_id', DB::raw('count(*) as total'))
            ->whereIn('pop_id', $pop_ids)
            ->groupBy('pop_id')
            ->get();

        // get all online if system is radius
        if (!checkAPI()) {
            $accounting = new Accounting();
            $all_online_users = $accounting->allOnLineClients();

            $pop_wise_online_counts = Client::select('pop_id', DB::raw('count(*) as total'))
                ->whereIn('userid', $all_online_users)
                ->whereIn('pop_id', $pop_ids)
                ->groupBy('pop_id')
                ->pluck('total', 'pop_id');
        }else{
            $pop_wise_online_counts = null;
        }

        return view('user.userCustomerSummary', [
            'page_title' => 'User Pop Information',
            'pops'   => $pops->get(),
            'clientCount' => $clientCount,
            'closeClientCount' => $closeClientCount,
            'resellers' => $reseller,
            'pop_wise_online_counts' => $pop_wise_online_counts,
        ]);
    }
}
