<?php

namespace App\Http\Controllers\API\v1;

use App\Http\Controllers\Controller;
use App\Models\Menu;
use App\Models\User;
use App\Models\RoleGroup;
use App\Models\Role;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Throwable;

class MenuController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {
        DB::enableQueryLog();
            $perPage = $request->input('per_page',PHP_INT_MAX);
            $keyword = $request->input('keyword', '');
            $keyword = str_replace(" ","%",$keyword);
            $data = Menu::with(['system'])
            ->where(fn($q) =>
                $q->where('name', 'like', '%'.$keyword.'%')
                    ->orWhere('description', 'like', '%'.$keyword.'%')
                    ->orWhereHas('system', fn($qs) => $qs->where('name', 'like', '%'.$keyword.'%')
                    ->orWhere('code', 'like', '%'.$keyword.'%'))
            )
            ->orderBy('name');

            $data = $data->paginate($perPage);
            return response()->json($data);
    }

     public function list(Request $request)
    {
        $data = Menu::with(['system'])->orderByDesc('sort')->get();

        return response()->json(["data" => $data]);
    }

    /**
     * dealership a newly created resource in storage.
     */
    public function dealership(Request $request)
    {
        // Validate the incoming request data
        $validator = Validator::make($request->all(), [
            'name' => 'required|min:2|unique:menus,name'
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        DB::connection()->beginTransaction();

        try {
            $data = Menu::create($request->all());

            DB::connection()->commit();

            return response()->json($data);

        } catch (Throwable $e) {
            DB::connection()->rollback();
            return response()->json([
                'status'  => false,
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        /** Validate the incoming request data */
        $validator = Validator::make($request->only(['name']), [
            'name' => "required|unique:menus,name"
        ]);

        if ($validator->fails()) {
            if ($validator->fails()) {
                $errors = $validator->errors();
                $first = $errors->getMessages();
                return response()->json([
                    'status'  => false,
                    'message' => (reset($first))[0],
                    'errors'  => $errors
                ], Response::HTTP_UNPROCESSABLE_ENTITY);
            }
        }

        DB::connection()->beginTransaction();

        try {

            $request_data = array_merge($request->all(), [
                'parent_id' => $request->parent_id ?? 0,
                'created_at'    => $this->current_datetime,
            'updated_at'    => $this->current_datetime]);

            $menu = Menu::create($request_data);

            DB::connection()->commit();

            return response()->json([
                'message' => 'Saved successfully!',
                'data'    => $menu
            ], 201);

        } catch (Throwable $e) {

            DB::connection()->rollback();
            return response()->json([
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }
    }
    /**
     * Display the specified resource.
     */
    public function show(int $id)
    {
        $data = Menu::find($id);
        if (!$data) {
            return response()->json(['messages' => 'No data found.'], 202);
        }
        return response()->json($data);
    }

    public function all(Request $request)
    {
        DB::enableQueryLog();
        $keyword = $request->input('keyword', '');
        $keyword = str_replace(" ","%",$keyword);
        $parents = Menu::with(['system'])->where(['parent_id' => 0, 'enabled' => 1]);

        // $parents->where(fn($q) =>
        //     $q->where('name', 'like', '%'.$keyword.'%')
        //         ->orWhere('name', 'like', '%'.$keyword.'%')
        //         ->orWhereHas('system', fn($qs) => $qs->where('name', 'like', '%'.$keyword.'%')
        //         ->orWhere('code', 'like', '%'.$keyword.'%'))
        // );
        $parents = $parents->get();
            $data = Menu::with(['system'])->select('menus.*', 'parent.name as parent_name')
            ->orderBy('menus.parent_id')->orderByRaw('CAST(menus.sort AS UNSIGNED) ASC')
            ->leftJoin('menus as parent', 'parent.id', '=', 'menus.parent_id');
            $data->where(fn($q) =>
                $q->where('menus.name', 'like', '%'.$keyword.'%')
                    ->orWhere('parent.name', 'like', '%'.$keyword.'%')
                    ->orWhereHas('system', fn($qs) => $qs->where('name', 'like', '%'.$keyword.'%')
                    ->orWhere('code', 'like', '%'.$keyword.'%'))
            );

        $data = $data->get();
        // dd(DB::getQueryLog());
        // $data = $data->toArray();
        // dd($data);
        // $menus = [];
        // foreach($parents as $row) {
        //     $child = array_filter($data, function ($child) use ($row) {
        //         return $child['parent_id'] == $row['id'];
        //     });
        //     $self = array_filter($data, function ($child) use ($row) {
        //         return $child['id'] == $row['id'];
        //     });
        //     if(!empty($child) || !empty($self)) {
        //         $menus[] = [
        //             'parent' => $row,
        //             'child' => !empty($child) ? $child : null,
        //         ];
        //     }
        // }
        $menus = $parents->map(fn($parent) => [
            'parent' => $parent,
            'child' => $data->filter(fn($child) => $child['parent_id'] == $parent['id'])->isNotEmpty()
        ? $data->filter(fn($child) => $child['parent_id'] == $parent['id'])->values()
        : null
        ])->filter(fn($menu) => (stripos($menu['parent']['name'], $keyword) !== false || $menu['child'] !== null))->values()->toArray();
        return response()->json([
            'data'    => $menus
        ]);
    }
    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, int $id)
    {
        $data = Menu::find($id);

        if (!$data) {
            return response()->json(['messages' => 'No data found.'], Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        DB::connection()->beginTransaction();

        try {

            $data->fill(array_merge(
                $request->all(),
                [
                    'parent_id' => $request->parent_id ?? 0,
                    'updated_at' => $this->current_datetime,
                ]
            ));
            $data->save();

            $data->touch();

            DB::connection()->commit();

            return response()->json([
                'data' => $data
            ], 201);

        } catch (Throwable $e) {
            DB::connection()->rollback();
            return response()->json([
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id)
    {
        $data = Menu::find($id);

        if (!$data) {
            return response()->json(['messages' => 'No data found.'], Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        DB::connection()->beginTransaction();

        try {
            $data->delete();

            DB::connection()->commit();

            return response()->json([
                'status'  => true,
                'message' => 'Record successfully deleted.',
                'data'    => $data,
            ]);

        } catch (Throwable $e) {
            DB::connection()->rollback();
            return response()->json([
                'status'  => false,
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }
    }


    public function userMenu(Request $request, $user_id)
    {
        $user = User::find($user_id);
        $parents = collect();
        $data = collect();
        $system_id = $request->system_id ?? null;
        $role_groups = $user->roles->pluck('group_id')->toArray();
        DB::enableQueryLog();
        $groups = RoleGroup::whereIn('id', $role_groups)
        ->where(fn($q) => $q->where('system_id',$system_id)->orWhereNull('system_id'))
        ->get()->pluck('id')->toArray();

        if (in_array(1, $role_groups)) {
            DB::enableQueryLog();
            $data = Menu::select('menus.*')
                ->distinct('menu.id')
                ->orderBy('menus.parent_id')
                ->orderByRaw('CAST(menus.sort AS UNSIGNED) ASC')
                ->join('modules', 'menus.id', '=', 'modules.menu_id')
                ->where('menus.enabled', '1')
                ->where(fn($q) =>
                    $q->where('modules.system_id', $system_id)
                    ->orWhereNull('modules.system_id')
                )
                ;
                $data= $data->get();
            // dd(DB::getQueryLog());
            $parent_ids = $data->filter(fn($item) => $item['parent_id'] === 0)
                ->pluck('id')
                ->merge($data->pluck('parent_id'))
                ->unique();

            $parents = Menu::whereIn('id', $parent_ids)->get();
        } else {
            $roles = $user->roles->filter(fn($role) => in_array($role['group_id'],  $role_groups))->pluck('id')->toArray();
            // dd($roles);
            $roles = $roles ?? [];  // If $roles is a variable, make sure it's an array

            if(empty($request->input('companies', []))){
                $companies = (array) $request->input('company_id');
            } else {
                $companies = $request->input('companies', []);
            }

            if(empty($request->input('dealerships', []))){
                $dealerships = (array) $request->input('dealership_id');
            } else {
                $dealerships = $request->input('dealerships', []);
            }

            DB::enableQueryLog();
            $data = Menu::select('menus.*')
                ->distinct('menu.id')
                ->orderBy('menus.parent_id')
                ->orderByRaw('CAST(menus.sort AS UNSIGNED) ASC')
                ->join('modules', 'menus.id', '=', 'modules.menu_id')
                ->join('role_permissions', function ($join) use ($companies, $dealerships, $roles) {
                    $join->on('modules.id', '=', 'role_permissions.module_id')
                        ->on(function ($joinc) use ($companies) {
                            $joinc->whereIn('role_permissions.company_id', $companies)
                                ->orWhere('role_permissions.company_id', '=', 0);
                        })
                        ->on(function ($join2) use ($dealerships) {
                            $join2->whereIn('role_permissions.dealership_id', $dealerships)
                                ->orWhere('role_permissions.dealership_id', '=', 0);
                        })
                        ->whereIn('role_permissions.role_id', $roles);
                })
                ->where('menus.enabled', '1')
                ->where(function ($q) use ($system_id) {
                    $q->where('modules.system_id', $system_id)
                    ->orWhereNull('modules.system_id');
                });

            $data= $data->get();
            // dd($data->toArray());
            // dd(DB::getQueryLog());
            $parent_ids = $data->filter(fn($item) => $item['parent_id'] === 0)
                ->pluck('id')
                ->merge($data->pluck('parent_id'))
                ->unique();

            $parents = Menu::whereIn('id', $parent_ids)->get();
        }

        $menus = $parents
        ->sortBy('sort') // Sort the parents by the 'sort' field
        ->map(fn($parent) => [
            'parent' => $parent,
            'child' => $data->filter(fn($child) => $child['parent_id'] == $parent['id'])->isNotEmpty()
            ? $data
                ->filter(fn($child) => $child['parent_id'] == $parent['id'])
                ->sortBy('sort') // Sort the children by the 'sort' field
                ->values()
            : null
        ])->filter(fn($menu) => $menu['child'] !==null || ($menu['parent']['url'] !== '#' && !empty($menu['parent']['url'])))
        ->values()
        ->toArray();

        // $menus = $parents->map(fn($parent) => [
        //     'parent' => $parent,
        //     'child' => $data->filter(fn($child) => $child['parent_id'] == $parent['id'])->isNotEmpty()
        // ? $data->filter(fn($child) => $child['parent_id'] == $parent['id'])->values()
        // : null
        // ])->filter(fn($menu) => $menu['child'] !== null || ($menu['parent']['url'] !== '#' && !empty($menu['parent']['url'])))->values()->toArray();

        return response()->json([
            'status'  => true,
            'message' => 'All menus',
            'data'    => $menus
        ]);

    }
    // public function userMenu(Request $request, $user_id)
    // {
    //     // dd($request->input('ou_code'));
    //     // \DB::enableQueryLog();
    //     $user = User::find($user_id);
    //     if($user->roles[0]->level == 100) {
    //         $data = Menu::select('menus.*', 'parent.name as parent_name')
    //             ->orderBy('menus.parent_id')->orderByRaw('CAST(menus.sort AS UNSIGNED) ASC')
    //             ->leftJoin('menus as parent', 'parent.id', '=', 'menus.parent_id')
    //             ->where('menus.enabled', '1');
    //     }
    //     else {
    //         $data = Menu::select('menus.*', 'parent.name as parent_name','parent.icon AS parent_icon','parent.sort as parent_sort', 'parent.url as parent_url')
    //             ->orderBy('menus.parent_id')->orderByRaw('CAST(menus.sort AS UNSIGNED) ASC')
    //             ->leftJoin('menus as parent', 'parent.id', '=', 'menus.parent_id')
    //             // ->leftJoin('user_menu_access as umc', 'umc.id', '=', 'menus.id')
    //             // ->where('umc.user_id', $user_id)
    //             // ->where('umc.ou_code', $request->input('ou_code'))
    //             ->where('menus.enabled', '1');
    //     }
    //     if ($request->keyword) {
    //         $keyword = "%$request->keyword%";
    //         $data->where(function($query) use ($keyword) {
    //             $query->where('menus.name', 'like', $keyword)
    //             ->orWhere('parent.name', 'like', $keyword);
    //         });
    //     }

    //     $data = $data->get();
    //     // dd(\DB::getQueryLog());
    //     $data = $data->toArray();
    //     // dd($data);
    //     $menus = [];
    //     $parents = array_filter($data, function ($parent) {
    //         return $parent['parent_id'] == 0;
    //     });
    //     foreach($parents as $row) {
    //         $menus[] = [
    //             'parent' => $row,
    //             'child' => array_filter($data, function ($child) use ($row) {
    //                 return $child['parent_id'] == $row['id'];
    //             }),
    //         ];
    //     }
    //     return response()->json([
    //         'status'  => true,
    //         'message' => 'All menus',
    //         'data'    => $menus
    //     ]);
    // }
}
