<?php

namespace App\Http\Controllers;

use App\Classes\EditLogHistory;
use App\Classes\SMS\ResellerAccountRechargeSms;
use Exception;
use App\Models\Balance;
use App\Models\Client;
use App\Models\Packages;
use App\Models\Pop;
use App\Models\Reseller;
use App\Models\ResellerCommissionReference;
use App\Models\ResellerRechargeReport;
use App\Models\ResellerUser;
use App\Models\UserAccounting;
use Illuminate\Http\Request;
use Database\Seeders\UserHasRole;
use Illuminate\Support\Facades\DB;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;

class ResellerController extends Controller
{


    public function __construct()
    {
        $this->middleware('permission:reseller_index|reseller_create|reseller_edit|reseller_destroy|specific_management_services', ['only' => ['index', 'show']]);
        $this->middleware('permission:reseller_create', ['only' => ['create', 'store']]);
        $this->middleware('permission:reseller_edit|manager-accounts-edit', ['only' => ['edit', 'update']]);
        $this->middleware('permission:reseller_destroy', ['only' => ['destroy']]);
        $this->middleware('permission:reseller-recharge', ['only' => ['resellerRecharge', 'resellerRechargeUpdate']]);
        $this->middleware('permission:package-permission|specific_management_services', ['only' => ['permission', 'permissionUpdate']]);
    }


    public function index()
    {
        $resellers = Reseller::resellerList();
        //$resellers = $t->with('')
        $resellersCount = $resellers->count();

        $due = ResellerRechargeReport::selectRaw('sum(amount) as tamount,sum(paid_amount) as tpaid,reseller_id')
            ->groupBy('reseller_id')
            ->get();

        $check_res_user = ResellerUser::where('user_id', auth()->user()->id)->pluck('reseller_id')->toArray();
        $managers = Reseller::with('commission')->whereIn('id', $check_res_user)->get();
        $accounts = ResellerCommissionReference::selectRaw('sum(received_amount) as ramount, sum(paid_amount) as pamount,reseller_id')->groupBy('reseller_id')->get();

        return view('reseller.index', [
            'resellers' => $resellers->paginate(5000),
            //'rechargeList' => $rechargeList,
            'page_title' => 'Manager List',
            'paid_amount' => false,
            'due' => $due,
            'managers'       => $managers,
            'accounts'      => $accounts,
            'resellersCount' => $resellersCount
        ]);
    }


    public function create()
    {
        return view('reseller.create', [
            'page_title' => 'Add New Reseller',
            'packages'  => Packages::all()
        ]);
    }

    public function store(Request $request)
    {

        $this->validate(
            $request,
            [
                'name' => 'required',
                'reseller_type' => 'required',
                'address' => 'required',
                'contact' => 'required',
                'billable' => 'required',
                'img_url' => 'image|mimes:jpeg,png,jpg,gif|min:20|max:5120',
            ],
        );

        $payment = json_encode([
            'bkash_charges' => $request->bkash_charges,
            'rocket_charges' => $request->rocket_charges,
            'nagad_charges' => $request->nagad_charges,
            'upay_charges' => $request->upay_charges,
            'ucash_charges' => $request->ucash_charges,
        ]);

        if (
            $request->reseller_type == 'own' && ($request->commission_percentage == null || $request->commission_percentage <= 0) && auth()->user()->can('set-manager-commission')
            && checkSettings('manager-commission-percentage') === 'enable'
        ) {
            Toastr::error('For Own type, Manager Miscellaneous Expense must be greater than 0.', 'Error');
            return redirect()->back()->withInput();
        }

        DB::beginTransaction();
        try {

            $reseller = Reseller::create([
                'name'          => $request->name,
                'reseller_type' => $request->reseller_type,
                'address'       => $request->address,
                'contact'       => $request->contact,
                'remark'        => $request->remark,
                'status'        => $request->status ?? 'active',
                'billable'      => $request->billable,
                'payment_charges' => $payment,
                'commission_percentage' => $request->commission_percentage ?? 0,
                'bank_name' => $request->bank_name ?? '',
                'branch_name' => $request->branch_name ?? '',
                'routing_number' => $request->routing_number ?? '',
                'bank_account_no' => $request->bank_account_no ?? '',
                'account_name' => $request->account_name ?? '',
                'created_by' => auth()->user()->id,
                'manager_unique_code' => 'manager'.rand(100000, 999999),
            ]);

            Balance::create([
                'type' => "reseller",
                'type_id' => $reseller->id,
                'amount'  => 0,
            ]);


            if ($request->hasFile('img_url')) {
                $image = $request->file('img_url');
                $fileName = time() . '.' . $image->getClientOriginalExtension();
                $path = 'reseller/' . $fileName;

                // Choose disk dynamically
                $disk = checkSettings('store_image_to_s3') === 'enable' ? 's3' : 'public';

                // Upload file
                $success = Storage::disk($disk)->putFileAs('reseller', $image, $fileName);




                if ($disk === 's3') {
                    Storage::disk('s3')->setVisibility($path, 'public');

                    $url = Storage::disk('s3')->url($path);


                    $reseller->img_url = $url;
                } else {
                    $reseller->img_url = $path;
                }

                $reseller->save();
            }

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

            Toastr::success('Reseller Added Successufll', 'Success');
            return redirect()->route('resellers.index');
        } catch (Exception $e) {
            DB::rollBack();
            Toastr::error('Reseller Added Failed', 'Success');
            return redirect()->back();
        }
    }

    public function show(Reseller $reseller)
    {
        //
    }

    public function edit(Reseller $reseller)
    {
        $reseller = Reseller::find($reseller->id);

        $payment = json_decode($reseller->payment_charges);
        return view('reseller.update', [
            'reseller' => $reseller,
            'page_title' => 'Update Manager Information',
            'payment' => $payment
        ]);
    }

    public function update(Request $request, $id)
    {
        $this->validate(
            $request,
            [
                'name' => 'required',
                'reseller_type' => 'required',
                'address' => 'required',
                'contact' => 'required',
                'billable' => 'required',
                'img_url' => 'image|mimes:jpeg,png,jpg,gif|min:20|max:5120',
            ]
        );



        if (
            $request->reseller_type == 'own' && ($request->commission_percentage == null || $request->commission_percentage <= 0)
            && auth()->user()->can('update-manager-commission') && checkSettings('manager-commission-percentage') === 'enable'
        ) {
            Toastr::error('For Own type, Manager Miscellaneous Expense must be greater than 0.', 'Error');
            return redirect()->back()->withInput();
        }



        DB::beginTransaction();
        try {
            $type = 'Manager';
            $old_info = Reseller::where('id', $id)->first();

            if ($old_info->reseller_type == "other" && $request->reseller_type == "own") {
                if (checkSettings('save_other_to_own_time_client') != 'enable') {
                    Toastr::error('Sorry, its not Permited', 'Error');
                    return redirect()->back();
                }
            }

            $payment = json_encode([
                'bkash_charges' => $request->bkash_charges,
                'rocket_charges' => $request->rocket_charges,
                'nagad_charges' => $request->nagad_charges,
                'upay_charges' => $request->upay_charges,
                'ucash_charges' => $request->ucash_charges,
            ]);

            $reseller = Reseller::find($id);
            if ($reseller->manager_unique_code != null && $reseller->manager_unique_code != '') {
                // keep the same code
                $manager_unique_code = $reseller->manager_unique_code;
            } else {
                // generate new code
                $manager_unique_code = 'manager'.rand(100000, 999999);
            }
            $reseller->update([
                'name'       => $request->name,
                'reseller_type' => $request->reseller_type,
                'address'    => $request->address,
                'contact'    => $request->contact,
                'remark'     => $request->remark,
                'status'     => $request->status ?? 'active',
                'billable'   => $request->billable,
                'payment_charges' => $payment,
                'bank_name' => $request->bank_name ?? '',
                'branch_name' => $request->branch_name ?? '',
                'routing_number' => $request->routing_number ?? '',
                'bank_account_no' => $request->bank_account_no ?? '',
                'account_name' => $request->account_name ?? '',
                'manager_unique_code' => $manager_unique_code,
                'enable_online_recharge' => $request->enable_online_recharge ?? 0,
            ]);

            if ($request->commission_percentage != null) {
                $reseller->commission_percentage = $request->commission_percentage;
                $reseller->save();
            }

            if ($request->img_url != null) {
                $image = $request->file('img_url');
                $fileName = time() . '.' . $image->getClientOriginalExtension();
                $path = 'reseller/' . $fileName;

                // Choose disk dynamically
                $disk = checkSettings('store_image_to_s3') === 'enable' ? 's3' : 'public';

                // Upload file
                $success = Storage::disk($disk)->putFileAs('reseller', $image, $fileName);

                if ($disk === 's3') {
                    Storage::disk('s3')->setVisibility($path, 'public');

                    $url = Storage::disk('s3')->url($path);

                    $reseller->img_url = $url;
                } else {
                    $reseller->img_url = $path;
                }

                $reseller->save();
            }



            $new_info = Reseller::find($reseller->id);
            (new EditLogHistory)->editLogSave($reseller, $type, $old_info, $new_info);

            if ($old_info->reseller_type == "other" && $new_info->reseller_type == "own") {
                if (checkSettings('save_other_to_own_time_client')) {

                    $allPops = Pop::where('reseller_id', $id)->pluck('id');

                    Client::whereIn('pop_id', $allPops)->update([
                        'billing_start_date' => now(),
                    ]);
                }
            }

            $bill_generate = $request->reseller_type == 'own' ? 'yes' : 'no';
            Pop::where('reseller_id', $id)->update(['bill_generate' => $bill_generate]);
            DB::commit();
            Artisan::call('cache:clear');

            Toastr::success('Reseller Update Successufll', 'Success');
            return redirect()->back();
        } catch (Exception $e) {
        }
    }


    public function destroy(Reseller $reseller)
    {
        //
    }

    public function permission($id)
    {
        $allPackage = Packages::all();

        $reseller = Reseller::find($id);

        return view('reseller.package', [
            'reseller' => $reseller,
            'packages' => $allPackage,
            'page_title' => 'Assign Package Permission'
        ]);
    }


    public function permissionUpdate(Request $request)
    {
        // dd($request->all());
        $this->validate($request, [
            'reseller_id' => 'required'
        ]);

        $reseller = Reseller::find($request->reseller_id);
        $packages = Packages::all();
        $old_package_list = [];
        foreach ($packages as $p) {
            if (in_array($p->id, explode(',', $reseller->package_list)) == true) {
                $old_package_list[] = $p->id;
            }
        }

        try {
            if (isset($request->package_id) && !empty($request->package_id)) {
                $package_list = implode(',', $request->package_id);
            } else {
                $package_list = '';
            }

            $new_package_list = explode(',', $package_list);
            $old_package_list = array_map('strval', $old_package_list);
            $removed_items  = array_diff($old_package_list, $new_package_list);
            // $added_items  = array_diff($new_package_list, $old_package_list);
            $pop = Pop::where('reseller_id', $request->reseller_id)->pluck('id')->toArray();
            $clients = Client::whereIn('pop_id', $pop);
            $client = $clients->where('package_id', $removed_items)->count();
            $package = Packages::whereIn('id', $removed_items)->pluck('package_name')->toArray();
            if (checkSettings('remove-package-permission') == 'disable') {
                if ($client) {
                    $packageList = implode(', ', $package);
                    Toastr::error("কিছু ক্লায়েন্ট এই $packageList প্যাকেজগুলো ব্যবহার করছে যা আপনি সরাতে চান", 'Error');
                    return redirect()->back();
                }
            }

            $reseller = Reseller::find($request->reseller_id);
            $reseller->package_list = $package_list;
            $reseller->save();

            clearCache('reseller');
            return redirect()->route('reseller.permission', $request->reseller_id)->with('success_message', 'Package Assigned Success');
        } catch (Exception $e) {
            dd($e);
            return redirect()->route('reseller.permission', $request->reseller_id)
                ->with('error_message', 'Some Thing is wrong!!');
        }
    }



    public function resellerRecharge($id, Request $request)
    {
        $reseller = Reseller::find($id);
        $rechargeList = ResellerRechargeReport::with('reseller', 'user', 'balance')
            ->where('reseller_id', $id)
            ->orderBy('id', 'desc')
            ->take(10);

        return view('reseller.resellerRecharge', [
            'page_title'   => 'Manager Recharge',
            'reseller'     => $reseller,
            'rechargeList' =>  $rechargeList->get(),
            'paid_amount' => false
        ]);
    }



    public function resellerRechargeUpdate(Request $request)
    {


        $txn_id = $request->uuid;

        $this->validate($request, [
            'amount' => 'required|numeric'
        ]);

        if (ResellerRechargeReport::where('txn_id', $txn_id)->count() > 0 && checkSettings('reseller-recharge-duplicate-protect') == 'enable') {
            Toastr::error('Duplicate Transaction', 'Error');
            return redirect()->back();
        }


        if (checkSettings('reseller-recharge-paid-option') == 'disable') {
            $paid_amount = $request->amount;
        } else {
            $paid_amount = $request->paid_amount;
        }

        $reseller = Reseller::find($request->type_id);

        DB::beginTransaction();
        try {

            if ($reseller->reseller_type == 'other') {
                $actions = 'Reseller payment received from ' . $reseller->name . ' ' . $reseller->contact;
                UserAccounting::userAcStore($paid_amount, $actions);
            }

            $status = Balance::balanceUpdate($request->type, $request->type_id, $request->amount, $request->remark, $paid_amount, '', $request->recharge_type, null, null, $txn_id);
            clearCache('reseller');

            $totalRecharge = ResellerRechargeReport::with('reseller', 'user', 'balance')->where('reseller_id', $reseller->id)->sum('amount');

            if ($status === 'success') {
                DB::commit();
                $sms_setting = getSmsMessage()->where('tamplate_name', 'reseller_balance_recharge_sms')->count() > 0 ? json_decode(getSmsMessage()->where('tamplate_name', 'reseller_balance_recharge_sms')->first()->tamplate_body, true) : '';
                if (!empty($sms_setting) && $sms_setting["sendsms"] == "Yes") {
                    try {
                        (new ResellerAccountRechargeSms())->sendSms($reseller->id, $request->amount, $totalRecharge);
                    } catch (\Exception $e) {
                    }
                }
                Toastr::success('Recharge Successfull', 'success');
                return redirect()->route('reseller.recharge', $request->type_id); //->with('success_message', 'Recharge Success');
            }else{
                DB::rollBack();
                Toastr::error('Recharge Failed', 'Error');
                return redirect()->back();
            }
        } catch (\Throwable $th) {

            DB::rollBack();
            Log::error("Shimul: " . $th->getMessage());
            Log::error($th);

            Toastr::error('Recharge UnSuccessfull', 'error');
            return redirect()->route('reseller.recharge', $request->type_id);
        }
    }

    public function managerBalance()
    {
        // $managerBalance = Reseller::all();
        $managerBalance = DB::table('resellers')
            ->join('reseller_recharge_reports', 'resellers.id', '=', 'reseller_recharge_reports.reseller_id')
            ->select('resellers.*', 'reseller_recharge_reports.after_recharge_balance')
            ->get();
        return view('billing.managerBalance', ['managerBalance' => $managerBalance]);
    }

    public function recharge() {}

    public function resellerPop(Request $request)
    {
        $popes = Pop::where('reseller_id', $request->reseller)->get();
        $temp_packages = Reseller::where('id', $request->reseller)->first();
        $packages = explode(",", $temp_packages->package_list);
        $packages = DB::table('packages')
            ->whereIn('id', $packages)
            ->get();
        $data = [
            'popes' => $popes,
            'packages' => $packages,

        ];

        return $data;
    }

    public function activeManager()
    {
        $resellers = Reseller::resellerList()->where('status', 'active');
        //$resellers = $t->with('')
        $resellersCount = $resellers->count();

        $due = ResellerRechargeReport::selectRaw('sum(amount) as tamount,sum(paid_amount) as tpaid,reseller_id')
            ->groupBy('reseller_id')
            ->get();

        $check_res_user = ResellerUser::where('user_id', auth()->user()->id)->pluck('reseller_id')->toArray();
        $managers = Reseller::with('commission')->whereIn('id', $check_res_user)->get();
        $accounts = ResellerCommissionReference::selectRaw('sum(received_amount) as ramount, sum(paid_amount) as pamount,reseller_id')->groupBy('reseller_id')->get();

        return view('reseller.activemanager', [
            'resellers' => $resellers->paginate(5000),
            //'rechargeList' => $rechargeList,
            'page_title' => 'Manager List',
            'paid_amount' => false,
            'due' => $due,
            'managers'       => $managers,
            'accounts'      => $accounts,
            'resellersCount' => $resellersCount
        ]);
    }
    public function inactiveManager()
    {
        $resellers = Reseller::resellerList()->where('status', 'inactive');
        //$resellers = $t->with('')
        $resellersCount = $resellers->count();

        $due = ResellerRechargeReport::selectRaw('sum(amount) as tamount,sum(paid_amount) as tpaid,reseller_id')
            ->groupBy('reseller_id')
            ->get();

        $check_res_user = ResellerUser::where('user_id', auth()->user()->id)->pluck('reseller_id')->toArray();
        $managers = Reseller::with('commission')->whereIn('id', $check_res_user)->get();
        $accounts = ResellerCommissionReference::selectRaw('sum(received_amount) as ramount, sum(paid_amount) as pamount,reseller_id')->groupBy('reseller_id')->get();

        return view('reseller.inactivemanager', [
            'resellers' => $resellers->paginate(5000),
            //'rechargeList' => $rechargeList,
            'page_title' => 'Manager List',
            'paid_amount' => false,
            'due' => $due,
            'managers'       => $managers,
            'accounts'      => $accounts,
            'resellersCount' => $resellersCount
        ]);
    }
}
