<?php

namespace App\Http\Controllers\Customer;

use App\Classes\MikrotikService\Mikrotik;
use App\Classes\Notification;
use App\Classes\SMS\TokenSms;
use App\Classes\TokenClass;
use App\Http\Controllers\Controller;
use App\Jobs\SendSmsJob;
use Illuminate\Http\Request;
use App\Models\Client;
use App\Models\Employee;
use App\Models\Nas;
use App\Models\Pop;
use App\Models\Reseller;
use App\Models\TokenCat;
use App\Models\TokenCode;
use App\Models\Token;
use App\Models\TokenNote;
use App\Models\TokenSource;
use App\Models\User;
use Brian2694\Toastr\Facades\Toastr;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;


class TokenController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $details['userinfo'] = CustomerFrontController::getinfo($request);

        // dd($details);
        $tokenCategory = TokenCat::all();
        //dd($tokenCategory);
        $tokenCode = TokenCode::all();
        //dd($tokenCode);

        $username = $details['userinfo']->userid;


        return view('Customer.token_create', [
            'page_title' => 'token_create',
            'details'    => $details,
            'tokenCategory' => $tokenCategory,
            'tokenCode' => $tokenCode,
            'type' => 'token_create'
        ]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $details['userinfo'] = CustomerFrontController::getinfo($request);
        $userid = $details['userinfo']->id;
        $username = $details['userinfo']->userid;
        $usercontact = $details['userinfo']['clientsinfo']->contact_no;
        // dd($details);

        DB::beginTransaction();

        try {

            $token = new Token();
            $token->tokenCategory = $request->tokenCategory;
            $token->tokenCode = $request->tokenCode;
            $token->description = $request->description;
            $token->clientId = $userid;
            $token->reporterContact = $usercontact;
            $token->createByClient = $username;
            $token->save();



            $token->save();

            $token->token =  $token->id + 1000000;
            $token->save();

            DB::commit();

            Toastr::success('Token Created Successfully', 'Success');
            return redirect()->route('pendingTokenList');
        } catch (\Throwable $th) {


            DB::rollback();
        }
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }



    public function customerTokenList(Request $request)
    {
        $details['userinfo'] = CustomerFrontController::getinfo($request);

        $username = $details['userinfo']->userid;
        $token = Token::where('createByClient', $username)

            ->orderBy('id', 'desc')
            ->get();

        return view('Customer.token_list', [
            'page_title' => 'Tokenlist',
            'details'    => $details,
            'token'      => $token

        ]);
    }

    public function PendingTokenList(Request $request)
    {

        $details['userinfo'] = CustomerFrontController::getinfo($request);

        if (!$details['userinfo']) {
            return redirect()->route('customer_login');
        }

        $username = $details['userinfo']->userid;

        $token = Token::where('createByClient', $username)
            ->where('status', 'Active')
            ->orderBy('id', 'desc')
            ->get();



        return view('Customer.pendingTokenlist', [
            'page_title' => 'Pending List',
            'details'    => $details,
            'token'      => $token

        ]);
    }

    public function addToken(Request $request)
    {
        $query = Token::with([
            'category',
            'Code',
            'clients',
            'creator',
            'employees',
            'clients.clientsinfo',
            'clients.pops',
            'clients.pops.reseller',
        ])->where('status', 'Active');

        // Filter by Reseller if provided
        if ($request->reseller_id) {
            $resellerId = $request->reseller_id;
            $query->whereHas('clients.pops.reseller', function ($q) use ($resellerId) {
                $q->where('id', $resellerId);
            });
        }
        if ($request->token_type) {
            $query->where('token_type', $request->token_type);
        }

        if($request->reseller_id || $request->token_type){
            $table = true;
        }else{
            $table = false;
        }

        // Filter by role
        if (auth()->user()->hasRole('Admin')) {
            $list = $query;
        } elseif (auth()->user()->hasRole(['Reseller Admin', 'Reseller', 'Sub Reseller'])) {
            $pop = Pop::poplist(); // Assuming it returns a Collection of pops accessible to the user
            $query->whereHas('clients', function ($q) use ($pop) {
                $q->whereIn('pop_id', $pop->pluck('id'));
            });

            $list = $query;
        } else {
            $list = $query;
        }

        // Finally get the data
        $tokens = $list->get();


        $online = null;
        if (checkAPI()) {
            $online = mikrotikOnlineAndOfflineUsers();
        }else {
            $clist = Client::list()->paginate(5000);
            $online = Client::online($clist->pluck('userid'));
        }
        $resellers = Reseller::list();

        $data = [
            'token' => $tokens,
            'token_categories' => TokenCat::get(),
            'employees' => Employee::where('status', 'active')->orderBy('name', 'ASC')->get(),
            'tokenSource' => TokenSource::get(),
            'mikrotik_online_users' => $online,
            'resellers' => $resellers,
            'reseller_id' => $request->reseller_id ?? null,
            'table' => $table,
            'tokenCount' => $tokens->count(),
        ];
        // dd($data);
        return view('token.addToken.index', $data);
    }


    public function getTokenCode(Request $request)
    {
        $tokenCode = TokenCode::where('tokenCategory', $request->tokenCategory)->get();
        return $tokenCode;
    }

    public function getCustomer(Request $request)
    {
        $customers = Client::list()->Where('userid', 'like', "%{$request->search}%")->get();
        return $customers;
    }

    public function assignToken(Request $request)
    {
        $token = Token::with('Code')->find($request->id_token_assign_model);
        // dd($request->all());
        $token->assignToken = $request->employee_modal;
        $token->assignUserId = auth()->user()->id;
        $token->assign_time = now();
        $token->update();
        $token_sms = new TokenSms();
        $client_username = Client::find($token->clientId);
        if (checkSettings('token-create-sms') == 'enable') {

            $token_sms->assignTokenSms($token->id);

        }

        (new Notification)->supportNotify(
            "..::[Token Assign]::..
                \nToken ID: " . $token->token .
                "\nAssign BY: " . auth()->user()->name .
                "\nAssigned To: " . employee_name($token->assignToken) .
                "\nClient ID: " . $token->clientId .
                "\nClient Username: " . $client_username->userid .
                "\nCustomer Name : " . $token->reportedBy .
                "\nCustomer Contact: " . $token->reporterContact .
                "\nProblem: " . $token->description
        );
        Toastr::success('Token Assign Successfully', 'Success');
        return redirect()->back();
    }

    public function closeTokenModal(Request $request)
    {
        if (checkSettings('close_token_after_customer_online') == 'enable' && checkAPI() == true) {

            $list = Token::with('clients.pops.nas')->find($request->id_token_close_model);
            // dd($list);
            // $list = Client::find($request->clientId);
            $mkIp = $list->clients->pops->nas->nasname;
            $mkUser = $list->clients->pops->nas->mikrotick_user;
            $mkPass = $list->clients->pops->nas->mikrotick_user_password;
            $mkPort = $list->clients->pops->nas->mikrotick_port;
            $mk = new Mikrotik($mkIp, $mkUser, $mkPass, $mkPort ? (int)$mkPort : 8728);

            $last_online = [];
            try {
                $userStatus = $mk->getActiveConnection($list->clients->userid);
                $last_online['framedipaddress'] = $userStatus["address"];
            } catch (Exception $err) {
                $last_online = null;
            }

            if ($last_online == null) {
                Toastr::error('Customer is not online', 'Error');
                return redirect()->back();
            }
        }
        if ($request->remark) {
            $token = Token::with('clients.clientsinfo', 'category', 'employees', 'Code')->find($request->id_token_close_model);
            $token->status = 'Inactive';
            $token->remarks = $request->remark;
            $token->ping_loss = $request->ping_loss;
            $token->optical_power = $request->optical_power;
            $token->remote = $request->remote;
            $token->autoreboot = $request->autoreboot;
            $token->issue_type = $request->issue_type;
            $token->client_feedback = $request->client_feedback;
            $token->close_time = now();
            $token->closeUserId = auth()->user()->id;
            $token->update();
            $client_username = Client::find($token->clientId);
            if (checkSettings('token-close-sms') == 'enable') {

                (new TokenSms)->closeTokenSms($token);
            }

            (new Notification)->supportNotify(
                "..::[Token Close]::..
                \nToken ID: " . $token->token .
                    "\nClosed BY: " . auth()->user()->name .
                    "\nClient ID: " . $token->clientId .
                    "\nClient Username: " . $client_username->userid .
                    "\nCustomer Name : " . $token->reportedBy .
                    "\nCustomer Contact: " . $token->reporterContact .
                    "\nClose Reason: " . $token->remarks
            );

            Toastr::success('Token Closed Successfully');
        } else {

            Toastr::error('Remarks is required', 'Error');
        }

        return redirect()->back();
    }

    public function tokenSaveNew(Request $request)
    {
        $this->validate($request, [
            'clientId' => 'required',
            'tokenCategory' => 'required',
            'tokenCode' => 'required',
            'description' => 'required',
            'reportedBy' => 'required',
            'reporterContact' => 'required|min:11|max:11',
            'token_type' => 'required',
        ]);

        $token_class = new TokenClass();
        $token = $token_class->saveToken($request);
        $token_sms = new TokenSms();
        $client_username = Client::find($token->clientId);
        if (checkSettings('token-create-sms') == 'enable') {
            $token_sms->createSms($token->id);
        }

        (new Notification)->supportNotify(
            "..::[New Token]::..
                    \nToken ID: " . $token->token .
                "\nCreated BY: " . auth()->user()->name .
                "\nClient ID: " . $request->clientId .
                "\nClient Username: " . $client_username->userid .
                "\nCustomer Name : " . $request->reportedBy .
                "\nCustomer Contact: " . $request->reporterContact .
                "\nProblem: " . $request->description
        );

        if (isset($request->employee)) {
            if ($request->employee != null) {

                if (checkSettings('token-create-sms') == 'enable') {

                    $token_sms->assignTokenSms($token->id);
                }

                (new Notification)->supportNotify(
                    "..::[Token Assign]::..
                            \nToken ID: " . $token->token .
                        "\nAssign BY: " . auth()->user()->name .
                        "\nAssigned To: " . employee_name($token->assignToken) .
                        "\nClient ID: " . $token->clientId .
                        "\nClient Username: " . $client_username->userid .
                        "\nCustomer Name : " . $token->reportedBy .
                        "\nCustomer Contact: " . $token->reporterContact .
                        "\nProblem: " . $token->description
                );
            }
        }

        Toastr::success('Token Created Successfully');
        return redirect()->back();
    }

    public function customerAccountCheck()
    {
        $clients = Client::withTrashed()->with('customerAccount', 'paymentBill', 'generatedBill', 'balanceAdjustment', 'pop')
            ->whereHas('pop', function ($q) {
                return $q->where('bill_generate', 'yes');
            })
            ->whereHas('generatedBill', function ($q) {
                return $q->where('due_amount', '>', 0);
            })->get();
        $data = [
            'clients' => $clients
        ];

        return view('token.addToken.check', $data);
    }

    public function addNoteToken(Request $request)
    {
        $token_note = new TokenNote();
        $token_note->token_id = $request->add_modal_token_id;
        $token_note->note = $request->note_remark;
        $token_note->note_type = $request->note_for;
        $token_note->user_id = auth()->user()->id;
        $token_note->save();

        if ($request->note_for == 'customer') {
            (new TokenSms)->TokenNoteCustomerSms($token_note->id);
        }

        Toastr::success('Note Added Successfully');
        return redirect()->back();
    }

    public function getTokenNote(Request $request)
    {
        $token_notes = TokenNote::with('user')->where('token_id', $request->token_id)->get();
        $token_note_delete = false;
        if (auth()->user()->hasPermissionTo('token-note-delete')) {
            $token_note_delete = true;
        }

        $data = [
            'token_notes' => $token_notes,
            'token_note_delete' => $token_note_delete
        ];
        return $data;
    }

    public function deleteTokenNote(Request $request)
    {
        $token_note = TokenNote::find($request->token_note_id);
        $token_note->delete();

        return 1;
    }

    public function reAssignTokenFromModal(Request $request)
    {

        $token = Token::with('Code')->find($request->id_token_re_assign_model);

        $data = [];
        $old_data = $token->previous_data;
        $old_data = json_decode($old_data);
        if ($old_data == null) {
            $data[] = $token;
        } else {
            $data = $old_data;
            $data[] = array_push($data, $token);
        }

        $token->assignToken = $request->employee;
        $token->assignUserId = auth()->user()->id;
        $token->assign_time = now();
        $token->previous_data = json_encode($data);
        $token->update();
        $token_sms = new TokenSms();

        if (checkSettings('token-create-sms') == 'enable') {
            // dd($token->id);
            $token_sms->reAssignTokenSMS($token->id);
        }

        Toastr::success('Token Re-Assign Successfully', 'Success');
        return redirect()->back();
    }

    public function userWiseToken()
    {
        $start = Carbon::now()->startOfMonth();
        $end = today();
        $users = User::whereHas('userdetails', function ($q) {
            $q->where('user_status', 'active');
        })->where('id', '>', 1)
            ->where('email', '!=', 'soiket@outlook.com')
            ->where('email', '!=', 'support@yetfix.com')
            ->where('email', '!=', 'admin@billingfix.xyz')
            ->get();

        return view('token.user_wise_token.index', [
            'start'      => $start,
            'end'        => $end,
            'users'      => $users,
            'employees'  => Employee::where('status', 'active')->get(),
        ]);
    }

    public function userWiseTokenReport(Request $request)
    {
        if ($request->ajax()) {
            // dd($request->all());
            $start = Carbon::parse($request->from_date)->startOfDay();
            $end = Carbon::parse($request->to_date)->endOfDay();

            $token = $this->tokenCount($start, $end, $request->user, $request->employee);

            return view('token.user_wise_token.result', compact('token'));
        }
    }

    public function tokenCount($start, $end, $user, $employee)
    {
        $start_of_day = Carbon::parse($start)->format('Y-m-d 00:00:00');
        $end_of_day = Carbon::parse($end)->format('Y-m-d 23:59:59');

        $tokenCreate = '';
        $tokenClose = '';
        $tokenAssign = '';

        if ($user != null) {

            $tokenCreate = DB::select("select COUNT(*) as total,createdBy from tokens where date(created_at) BETWEEN '$start_of_day' AND '$end_of_day' and createdBy = '$user' GROUP BY createdBy;");
            $tokenClose  = DB::select("select COUNT(*) as total,closeUserId from tokens where date(created_at) BETWEEN '$start_of_day' AND '$end_of_day' and closeUserId is not null and closeUserId = '$user' GROUP BY closeUserId;");
        } elseif ($employee != null) {

            $tokenAssign = DB::select("select COUNT(*) as total,assignToken from tokens where date(close_time) BETWEEN '$start_of_day' AND '$end_of_day' and assignToken = '$employee' GROUP BY assignToken;");
        } else {

            $tokenCreate = DB::select("select COUNT(*) as total,createdBy from tokens where date(created_at) BETWEEN '$start_of_day' AND '$end_of_day' GROUP BY createdBy;");
            $tokenClose  = DB::select("select COUNT(*) as total,closeUserId from tokens where date(created_at) BETWEEN '$start_of_day' AND '$end_of_day' and closeUserId is not null GROUP BY closeUserId;");
            $tokenAssign = DB::select("select COUNT(*) as total,assignToken from tokens where date(close_time) BETWEEN '$start_of_day' AND '$end_of_day' GROUP BY assignToken;");
        }

        $users = user_list();
        $userWiseTokenReport = [];
        foreach ($users as $user) {
            if ($tokenCreate != '' && $tokenClose != '') {

                foreach ($tokenCreate as $tcreate) {
                    if ($tcreate->createdBy == $user->id) {
                        $userWiseTokenReport[$user->id]['tokenCreate'] = $tcreate->total;
                    }
                }
                foreach ($tokenClose as $tclose) {
                    if ($tclose->closeUserId == $user->id) {
                        $userWiseTokenReport[$user->id]['tokenClose'] = $tclose->total;
                    }
                }
                if (isset($userWiseTokenReport[$user->id]['tokenCreate']) ||  isset($userWiseTokenReport[$user->id]['tokenClose'])) {
                    $userWiseTokenReport[$user->id]['name'] = $user->name;
                }
            }
        }

        $employees = employee_list();
        $employWiseTokenReport = [];
        foreach ($employees as $employee) {
            if ($tokenAssign != '') {
                foreach ($tokenAssign as $tassign) {
                    if ($tassign->assignToken == $employee->id) {
                        $employWiseTokenReport[$employee->id]['assignToken'] = $tassign->total;
                    }
                }
                if (isset($employWiseTokenReport[$employee->id]['assignToken'])) {
                    $employWiseTokenReport[$employee->id]['name'] = $employee->name;
                }
            }
        }

        return  [
            'userWiseTokenReport' => collect($userWiseTokenReport),
            'employWiseTokenReport' => collect($employWiseTokenReport),
        ];
    }
}
