<?php

namespace App\Http\Controllers\API\v1;

use App\Models\Role;
use App\Models\RoleCompanyAccess;
use App\Models\RolePermission;
use App\Models\Dealership;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\Controller;
use Illuminate\Validation\Rule;
use Throwable;

class RoleController extends Controller
{

    /**
     * Get search roles
     *
     */
    public function index(Request $request)
    {
        $perPage = $request->input('per_page',PHP_INT_MAX);

        $keyword = $request->input('keyword', '');
        $system_id = $request->input('system_id', null);
        $sortBy = $request->input('sortBy', null);
        $sortType = $request->input('sortType', null);
        $data = Role::with(['group', ])->where(fn ($q) => $q->where('name', 'like', '%'.$keyword.'%')
            ->orWhere('description', 'like', '%'.$keyword.'%'))
        ->when($system_id, fn ($qs) => $qs->whereHas('group', fn($q) => $q->where('system_id', '=', $system_id)->orWhereNull('system_id')))
        ->when($sortBy, fn($qs) => $qs->orderBy($sortBy, $sortType))
        ->paginate($perPage);

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

    /**
     * Get all role info
     *
     */
    public function show($id)
    {
        return response()->json([
            'status'  => true,
            'message' => 'Role info',
            'data'    => Role::where('id', '=', $id)->first()
        ]);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => [
                'required',
                'min:2',
                Rule::unique('roles')->whereNull('deleted_at'),
            ]
        ]);


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

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

        try {

            $role = Role::create($request->all());

            //save company access
            if($request['companies']) {
                // dd($request->companies);
                foreach($request->companies as $company_id) {
                    $dealerships = [];
                    if($request['dealerships']) {
                        foreach($request->dealerships as $dealer_id) {
                            $dealership = Dealership::find($dealer_id);
                            if($dealership->company_id == $company_id) {
                                $dealerships[] = [
                                    'role_id' => $role->id,
                                    'company_id' => $company_id,
                                    'dealership_id' => $dealer_id,
                                    'created_at' => $role->created_at,
                                    'updated_at' => $role->updated_at,

                                ];
                            }
                        }
                    }
                    // dd($dealerships);
                    if(!empty($dealerships)) {
                        RoleCompanyAccess::insert($dealerships);
                    }
                    else {
                        RoleCompanyAccess::create([
                            'role_id' => $role->id,
                            'company_id' => $company_id,
                            'dealership_id' => 0,
                            'created_at' => $role->created_at,
                            'updated_at' => $role->updated_at,
                        ]);
                    }
                }
            }

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

            return response()->json([
                'status' => true,
                'message' => 'Role saved successfully!',
                'data' => $role
            ], 201);

        } catch (Throwable $e) {

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

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

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

        $validator = Validator::make($request->all(), [
            'name' => [
                'required',
                'min:2',
                Rule::unique('roles')->ignore($id)->whereNull('deleted_at'),
            ]
        ]);

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

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

        try {

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

            $data->touch();

            //find Role in CompanyAccess
            $roleCompanyAccess = RoleCompanyAccess::where('role_id', $data->id);
            $roleCompanyAccess->delete();

            //save company access
            if($request['companies']) {
                foreach($request->companies as $company_id) {
                    $dealerships = [];
                    if($request['dealerships']) {
                        foreach($request->dealerships as $dealer_id) {
                            $dealership = Dealership::where(['id' => $dealer_id, 'company_id'=>$company_id])->first();
                            if($dealership && $dealership->company_id == $company_id) {
                                $dealerships[] = [
                                    'role_id' => $data->id,
                                    'company_id' => $company_id,
                                    'dealership_id' => $dealer_id,
                                    'created_at' => $data->updated_at,
                                    'updated_at' => $data->updated_at,
                                ];
                            }
                        }
                    }
                    if(!empty($dealerships)) {
                        RoleCompanyAccess::insert($dealerships);
                    }
                    else {
                        RoleCompanyAccess::create([
                            'role_id' => $data->id,
                            'company_id' => $company_id,
                            'dealership_id' => 0,
                            'created_at' => $data->updated_at,
                            'updated_at' => $data->updated_at,
                        ]);
                    }
                }
            }

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

            return response()->json([
                'status' => true,
                'message' => 'Role updated successfully!',
                'data' => $data
            ], 201);

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


    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        // if ( ! _userAccess('can.delete.roles')) {
        //     return response()->json([
        //         'status' => false,
        //         'message'    => 'Unauthorized.'
        //     ]);
        // }

        $validator = Validator::make(['id' => $id], [
            'id' => 'required|exists:id'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => false,
                'message' => 'Validation error',
                'data' => $validator->errors()
            ]);
        }

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

        try {

            $role = Role::find($id);

            $role->delete();

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

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

        } catch (Throwable $e) {

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

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

        $data = RoleCompanyAccess::select('role_company_access.company_id', 'role_company_access.dealership_id', DB::raw("companies.name AS company_name"), DB::raw("dealerships.name AS dealership_name"))
            ->orderBy('companies.name')
            ->leftJoin('companies', 'role_company_access.company_id', '=', 'companies.id')
            ->leftJoin('dealerships', 'role_company_access.dealership_id', '=', 'dealerships.id')
            ->where('role_company_access.role_id', $id)
            ->get();
        // if($id != 1) {
        //     $data = $data->toArray();
        // } else {
        //     $data = Store::select('dealerships.id', 'dealerships.name')
        //     ->orderBy('dealerships.name')
        //     ->get();
        //     $data = $data->toArray();
        //     array_unshift($data,['company_id'=>'all','name'=>'ALL']);
        // }
        return response()->json([
            'status' => true,
            'role'   => Role::find($id),
            'data'   => $data
        ]);
    }

    public function AllRoleCompanyAccess(Request $request) {
        $role_ids = $request->input('role_ids');
        if(!in_array(1, $role_ids)) {
            $data = RoleCompanyAccess::select('dealerships.id','dealerships.name')->distinct('dealerships.name')
                ->orderBy('dealerships.name')
                ->leftJoin('dealerships', 'role_company_access.company_id', '=', 'dealerships.id')
                ->whereIn('role_company_access.role_id', $role_ids)
                ->get();
            /**if has all access get all dealerships */
            if(in_array(0,array_column($data->toArray(),'company_id'))) {
                $data = Dealership::select('dealerships.*')
                    ->orderBy('dealerships.name')
                    ->get();
            }
        } else {
            $data = Dealership::select('dealerships.*')
                ->orderBy('dealerships.name')
                ->get();
        }

        return response()->json([
            'status' => true,
            'roles'   => Role::find($role_ids),
            'data'   => $data
        ]);
    }


    /**
     * Get module access assigned to role and store
     *
     */
    // public function dealershipPermissions($id, $company_id)
    // {
    //     $data = Role::dealershipPermissions($id, $company_id);
    //     $data = Arr::pluck($data, 'name');

    //     return response()->json([
    //         'status' => true,
    //         'message'    => 'Assigned Permissions list',
    //         'data'   => $data
    //     ]);
    // }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function copyRoleAccess(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'role_id' =>'required',
            'company_id' =>'required',
            'dealership_id' =>'required',
            'target_role_id' =>'required',
            // 'company_id' =>'required',
            // 'dealership_id' =>'required',
        ]);


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

        $data = RolePermission::where(['role_id' => $request->role_id, 'company_id' => $request->company_id, 'dealership_id' => $request->dealership_id])->get();

        if(!$data || !$data->isNotEmpty()) {
            return response()->json([
                'status' => false,
                'message' => 'Record not found',
            ], 422);
        }

        // return response()->json(['data' => $data]);
        DB::connection()->beginTransaction();

        try {
            $newData = [];
            if(!$request->target_company_id) {
                $roleData = RoleCompanyAccess::where('role_id', $request->target_role_id)->get();
                if(!$roleData) {
                    return response()->json([
                        'status' => false,
                        'message' => 'Record not found',
                    ], 422);
                }
                $roleData = $roleData->select('role_id','company_id','dealership_id')->toArray();
                // return response()->json(['data' => $roleData]);
                foreach($roleData as $role) {
                    RolePermission::where($role)->delete();
                    foreach($data->select('module_id','permission_id')->toArray() as $row) {
                        $row = array_merge($row, $role);
                        RolePermission::create($row);
                        $newData[] = $row;
                    }
                }
            } else {
                foreach($data->select('module_id','permission_id')->toArray() as $row) {
                    $row = array_merge($row, ['role_id' => $request->target_role_id, 'company_id' => $request->target_company_id, 'dealership_id' => $request->target_dealership_id]);
                    $newData[] = $row;
                    // RolePermission::create($row);
                }

            }

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

            return response()->json([
                'status' => true,
                'message' => 'Role permission saved copied!',
                'data' => $newData
            ], 201);

        } catch (Throwable $e) {

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


}
