<?php

namespace App\Http\Controllers;

use App\Classes\EditLogHistory;
use App\Models\Packages;
use App\Models\SubPackage;
use App\Models\Pop;
use App\Models\Reseller;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class PackagesController extends Controller
{
    public function __construct()
    {

        $this->middleware('permission:package_index|package_create|package_edit|package_destroy|specific_management_services', ['only' => ['index', 'show']]);
        $this->middleware('permission:package_create', ['only' => ['create', 'store']]);
        $this->middleware('permission:package_edit', ['only' => ['edit', 'update']]);
        $this->middleware('permission:package_destroy', ['only' => ['destroy']]);


        $this->middleware('permission:sub-package-permission', ['only' => ['permissionUpdate']]);
        $this->middleware('permission:sub-package-permission-form|specific_management_services', ['only' => ['subPackagePermission']]);
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        // Don't load packages here - DataTables will load them via AJAX
        return view('packages.index', [
            'page_title' => 'Packages List',
            'url' => route('packages.create'),
            // 'add_button' => 'true',
            'class' => 'text-white bg-blue-600',
            'value' => 'Add New Package'
        ]);
    }

    public function getPackagesData(Request $request)
    {
        // Get DataTables parameters
        $draw = $request->get('draw');
        $start = $request->get('start', 0);
        $length = $request->get('length', 10);
        $searchValue = $request->get('search')['value'] ?? '';

        // Get ordering information from DataTables request
        $orderColumn = isset($request->get('order')[0]['column']) ? (int)$request->get('order')[0]['column'] : 0;
        $orderDir = isset($request->get('order')[0]['dir']) ? $request->get('order')[0]['dir'] : 'desc';

        // Use column name from request instead of index (works across platforms and permission levels)
        // This is critical because columns are conditionally shown based on permissions
        $orderBy = 'id'; // default fallback
        $requestColumns = $request->get('columns', []);

        if (isset($requestColumns[$orderColumn]['name']) && !empty($requestColumns[$orderColumn]['name'])) {
            $columnName = trim($requestColumns[$orderColumn]['name']);

            // Map column names to database columns (case-insensitive for cross-platform compatibility)
            $sortableColumns = ['id', 'package_name', 'package_rate', 'client_payment_amount', 'pool_name', 'created_at', 'commission'];

            // Check if column name matches a sortable database column (case-insensitive)
            $columnNameLower = strtolower($columnName);
            foreach ($sortableColumns as $dbColumn) {
                if (strtolower($dbColumn) === $columnNameLower) {
                    $orderBy = $dbColumn;
                    break;
                }
            }
            // For non-sortable columns (reseller_name, action), keep default 'id'
        }

        // Build base query for total count
        $baseQuery = $this->buildConditionalQuery();
        $recordsTotal = $baseQuery->count();

        // Build filtered query
        $query = $this->buildConditionalQuery();

        // Apply search filter
        if (!empty($searchValue)) {
            $query->where(function($q) use ($searchValue) {
                $q->where('packages.id', 'like', '%' . $searchValue . '%')
                  ->orWhere('packages.package_name', 'like', '%' . $searchValue . '%')
                  ->orWhere('packages.package_rate', 'like', '%' . $searchValue . '%')
                  ->orWhere('packages.client_payment_amount', 'like', '%' . $searchValue . '%')
                  ->orWhere('packages.pool_name', 'like', '%' . $searchValue . '%')
                  ->orWhere('packages.profile_name', 'like', '%' . $searchValue . '%')
                  ->orWhere('packages.commission', 'like', '%' . $searchValue . '%');
            });
        }

        // Get filtered count
        $recordsFiltered = $query->count();

        // Apply ordering - ensure column is qualified with table name for cross-platform compatibility
        $validSortColumns = ['id', 'package_name', 'package_rate', 'client_payment_amount', 'pool_name', 'created_at', 'commission'];
        if (in_array(strtolower($orderBy), array_map('strtolower', $validSortColumns))) {
            $query->orderBy('packages.' . $orderBy, $orderDir);
        } else {
            // Fallback to id if column is invalid
            $query->orderBy('packages.id', $orderDir);
        }

        // Apply pagination
        $packages = $query->skip($start)->take($length)->get();

        // Pre-load resellers data efficiently to avoid N+1
        $resellersMap = [];
        if (checkSettings('resseller-name-in-package') == 'enable' && auth()->user()->can('reseller-show-in-package')) {
            $allResellers = Reseller::select('id', 'name', 'package_list')->get();
            foreach ($allResellers as $reseller) {
                if (!empty($reseller->package_list)) {
                    $packageIds = array_filter(explode(',', $reseller->package_list));
                    foreach ($packageIds as $packageId) {
                        $packageId = (int) trim($packageId);
                        if ($packageId > 0) {
                            if (!isset($resellersMap[$packageId])) {
                                $resellersMap[$packageId] = [];
                            }
                            $resellersMap[$packageId][] = $reseller;
                        }
                    }
                }
            }
        }

        // Format data for DataTables
        $data = [];
        foreach ($packages as $row) {
            $rowData = [
                'id' => $row->id,
                'package_name' => $row->package_name,
            ];

            // Add package rate column
            if (auth()->user()->canAny(['show-package-rate', 'specific_management_services'])) {
                $rowData['package_rate'] = $row->package_rate;
            }

            // Add client payment amount column
            if (auth()->user()->canAny(['show-package-rate', 'specific_management_services'])
                && checkSettings('ResellerClientOnlineRecharge') == 'enable'
                && checkSettings('setClientPaymentAmountToClient') != 'enable') {
                $rowData['client_payment_amount'] = $row->client_payment_amount;
            }

            // Add reseller name column
            if (checkSettings('resseller-name-in-package') == 'enable' && auth()->user()->can('reseller-show-in-package')) {
                $resellerNames = [];
                if (isset($resellersMap[$row->id])) {
                    foreach ($resellersMap[$row->id] as $reseller) {
                        $resellerNames[] = '<span class="btn btn-warning p-1 mb-1">' . htmlspecialchars($reseller->name) . '</span>';
                    }
                }
                $rowData['reseller_name'] = !empty($resellerNames)
                    ? '<div class="overflow-auto" style="height:100px">' . implode(' ', $resellerNames) . '</div>'
                    : '<div class="overflow-auto" style="height:100px"></div>';
            }

            // Add pool/profile name column
            if (auth()->user()->can('ip-pool')) {
                $rowData['pool_name'] = checkAPI() ? ($row->profile_name ?? '') : ($row->pool_name ?? '');
            }

            // Add created date
            $rowData['created_at'] = date('d-M-Y H:i:s', strtotime($row->created_at));

            // Add commission column
            if (auth()->user()->can('pack-commission')) {
                $rowData['commission'] = $row->commission;
            }

            // Generate action buttons HTML
            $csrfToken = csrf_token();
            $actionHtml = '<div class="d-flex">';

            if (auth()->user()->can('package_edit')) {
                $actionHtml .= '<a href="' . route('packages.edit', $row->id) . '" class="btn btn-primary btn-sm">Edit</a>';
            }

            if (auth()->user()->can('package_destroy')) {
                // Use a dedicated class for JS binding and keep markup simple (confirmation handled in JS)
                $actionHtml .= '<form class="delete-package-form ml-1" action="' . route('packages.destroy', $row->id) . '" method="POST">
                    <input type="hidden" name="_method" value="DELETE">
                    <input type="hidden" name="_token" value="' . $csrfToken . '">
                    <button type="submit" class="btn btn-danger btn-sm">Delete</button>
                </form>';
            }

            if (auth()->user()->can('view-package-log-history')) {
                $actionHtml .= '<a href="' . route('editLog-history', ['id' => $row->id, 'type' => 'Package']) . '" class="btn btn-primary pull-right btn-sm ml-1">History</a>';
            }

            $actionHtml .= '</div>';
            $rowData['action'] = $actionHtml;

            $data[] = $rowData;
        }

        return response()->json([
            'draw' => intval($draw),
            'recordsTotal' => $recordsTotal,
            'recordsFiltered' => $recordsFiltered,
            'data' => $data
        ]);
    }

    private function buildConditionalQuery()
    {
        $id = auth()->id();

        if (auth()->user()->hasRole('Sub Reseller')) {
            $plist = [];
            return Packages::whereIn('id', $plist);
        } elseif (auth()->user()->hasRole(['Reseller Admin', 'Reseller'])) {
            $reseller_ids = DB::table('reseller_user')->where('user_id', $id)->pluck('reseller_id')->toArray();
            $resellers = Reseller::whereIn('id', $reseller_ids)->pluck('package_list')->toArray();
            $plist = array_unique(explode(',', implode(',', $resellers)));
            $plist = array_filter($plist); // Remove empty values
            return Packages::whereIn('id', $plist);
        } else {
            return Packages::query();
        }
    }


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


    public function store(Request $request)
    {
        $this->validate($request, [
            'package_name'  => 'required|unique:packages,package_name',
            'package_rate'  => 'required',
            'pool_name'     => checkAPI() ? '' : 'required',
        ]);

        DB::beginTransaction();

        try {

            $package_id = Packages::create([
                'package_name'  => trim($request->package_name),
                'package_rate' => trim($request->package_rate),
                'pool_name'     => checkAPI() ? $request->profile_name : $request->pool_name,
                'commission'     => $request->commission ?? 0,
                'profile_name'     => checkAPI() ? $request->profile_name : $request->pool_name,
                'speed_up'     => $request->speed_up ?? '0',
                'speed_down'     => $request->speed_down ?? '0',
                'limite_quantity'     => $request->limite_quantity,
                'package_bandwidth'     => $request->package_bandwidth,
                'btrc_package_price'    => $request->btrc_package_price ?? 0.00,
                'client_payment_amount'    => $request->client_payment_amount ?? 0,
                'created_by' => auth()->user()->id
            ])->id;

            if (!checkAPI()) {
                DB::table('radgroupcheck')->insert([
                    [
                        'groupname' => $package_id,
                        'attribute' => 'Framed-Protocol',
                        'op'        => '==',
                        'value'     => 'PPP'
                    ],
                    [
                        'groupname' => $package_id,
                        'attribute' => 'Simultaneous-Use',
                        'op'        => ':=',
                        'value'     => 1
                    ]
                ]);

                DB::table('radgroupreply')->insert([
                    'groupname' => $package_id,
                    'attribute' => 'Framed-Pool',
                    'op'        => '=',
                    'value'     => $request->pool_name
                ]);
            }

            DB::commit();

            Toastr::success('Packages Added successfull', 'Success');
            return redirect()->back(); //route('packages.index');
        } catch (\Exception $e) {
            DB::rollback();
            // $request->session()->flash('error_message', 'Something wrong');
            Toastr::error('Something wrong', 'Error');
        }
    }


    public function show(Packages $packages)
    {
        //
    }


    public function edit($id)
    {
        $list = Packages::find($id);
        return view('packages.update', [
            'page_title' => 'Edit Packages List',
            'list' => $list
        ]);
    }


    public function update(Request $request, $id)
    {
        $this->validate($request, [
            'package_name'  => 'required|unique:packages,package_name,' . $id,
            'package_rate'  => 'required',
            'pool_name'     => checkAPI() ? '' : 'required',
            'profile_name'  => checkAPI() ? 'required' : '',

        ]);



        DB::beginTransaction();

        try {

            $type = 'Package';
            $old_info = Packages::where('id', $id)->first();

            Packages::where('id', $id)
                ->update([
                    'package_name'  => $request->package_name,
                    'package_rate'  => $request->package_rate,
                    'pool_name'     => checkAPI() ? $request->profile_name : $request->pool_name,
                    'commission'    => $request->commission ?? 0,
                    'profile_name'  => checkAPI() ? $request->profile_name : $request->pool_name,
                    'speed_up'     => $request->speed_up ?? '0',
                    'speed_down'     => $request->speed_down ?? '0',
                    'limite_quantity'     => $request->limite_quantity,
                    'package_bandwidth'     => $request->package_bandwidth,
                    'btrc_package_price'    => $request->btrc_package_price ?? 0.00,
                    'client_payment_amount'    => $request->client_payment_amount ?? 0.00,
                ]);

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

            if (!checkAPI()) {
                DB::table('radgroupreply')
                    ->where('groupname', $id)
                    ->update([
                        'value'     => $request->pool_name
                    ]);
            }

            DB::commit();

            // $request->session()->flash('success_message', 'Packages Update successfull');
            Toastr::success('Packages Update successfull', 'Success');
            return redirect()->route('packages.index');
        } catch (\Exception $e) {
            DB::rollback();
            // $request->session()->flash('error_message', 'Something wrong');
            Toastr::error('Something wrong', 'Error');
        }
    }


    public function destroy(Request $request, $id)
    {
        $package_in_reseller = Reseller::where('package_list', 'like', '%' . $id . '%')->get();
        if ($package_in_reseller) {
            foreach ($package_in_reseller as $reseller) {
                $package_list = explode(',', $reseller->package_list);
                $key = in_array($id, $package_list);
                if ($key) {
                    $message = 'This package is in use by reseller';
                    if ($request->ajax()) {
                        return response()->json(['status' => 'error', 'message' => $message], 400);
                    }
                    Toastr::error($message, 'Error');
                    return redirect()->back();
                }
            }
        }
        $package_in_sub_package = SubPackage::where('package_id', $id)->first();
        if ($package_in_sub_package) {
            $message = 'This package is in use by sub package';
            if ($request->ajax()) {
                return response()->json(['status' => 'error', 'message' => $message], 400);
            }
            Toastr::error($message, 'Error');
            return redirect()->back();
        }
        $package_in_clients = DB::table('clients')->where('package_id', $id)->get()->count();
        if ($package_in_clients > 0) {
            $message = 'This package is in use by clients';
            if ($request->ajax()) {
                return response()->json(['status' => 'error', 'message' => $message], 400);
            }
            Toastr::error($message, 'Error');
            return redirect()->back();
        }

        Packages::where('id', $id)->delete();
        $message = 'Packages Delete successfull';
        if ($request->ajax()) {
            return response()->json(['status' => 'success', 'message' => $message]);
        }
        Toastr::success($message, 'Success');
        return redirect()->back();
    }

    public function subPackagePermission($id)
    {


        $pop = Pop::find($id);
        $allPackage = SubPackage::where('reseller_id', $pop->reseller_id)->get();
        return view('pop.package', [
            'pop' => $pop,
            'packages' => $allPackage,
            'page_title' => 'Assign Sub Package Permission'
        ]);
    }
    public function permissionUpdate(Request $request)
    {

        $this->validate($request, [
            'reseller_id' => 'required'
        ]);



        try {

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

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

            // return redirect()->route('sub_package_permission', $request->reseller_id)->with('success_message', 'Package Assigned Success');
            Toastr::success('Package Assigned Success', 'Success');
            return redirect()->route('sub_package_permission', $request->reseller_id);

            // }
        } catch (\Exception $e) {

            // return redirect()->route('sub_package_permission', $request->reseller_id)
            //     ->with('error_message', 'Some Thing is wrong!!');
            Toastr::error('Some Thing is wrong!!', 'Error');
            return redirect()->route('sub_package_permission', $request->reseller_id);
        }
    }

    public function packageProfile(Request $request)
    {
        $tepm_package = Packages::find($request->package);
        return $tepm_package;
    }
}
