<?php

namespace App\Http\Controllers;

use App\Classes\EditLogHistory;
use App\Models\LogHistory;
use Exception;
use App\Models\User;
use App\Models\User_details;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Role;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Auth;
use App\Models\Permission;

class RolesController extends Controller
{

    public function __construct()
    {
        $this->middleware('permission:role_index|role_create|role_edit|role_destroy', ['only' => ['index', 'show']]);
        $this->middleware('permission:role_create', ['only' => ['create', 'store']]);
        $this->middleware('permission:role_edit', ['only' => ['edit', 'update']]);
        $this->middleware('permission:role_destroy', ['only' => ['destroy']]);
    }

    public function index()
    {
        $roles = Role::with('permissions')->where('name', '!=', 'SoftwareAdmin')->get();
        return view('role.roleList', [
            'list' => $roles
        ]);
    }

    public function create()
    {
        if (Auth::user()->email == 'admin@gmail.com') {
            return redirect()->back()->with('error_message', 'You can not Add New Role');
        }

        return view('role.createRole', [
            'page_title' => 'Create New Role'
        ]);
    }

    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required|unique:roles',

        ]);
        Role::create(['name' => $request->name]);
        return redirect()->back()->with('success_message', 'Role Created successfully');
    }

    public function show($id)
    {
        //
    }

    public function edit($id)
    {
        return view('role.editRole', [
            'page_title' => 'Edit Role',
            'role'       => Role::find($id)
        ]);
    }

    public function update(Request $request, $id)
    {
        if (Auth::user()->email == 'admin@gmail.com') {
            return redirect()->back()->with('error_message', 'You can not Change Role Name');
        }

        $this->validate($request, [
            'name' => 'required|unique:roles,name,' . $id,
        ]);
        Role::whereId($id)->update([
            'name' => $request->name
        ]);

        return redirect()->back()->with('success_message', 'Role updated successfully');
    }

    public function destroy($id)
    {
        //
    }

    public function assignPermission($id)
    {
        $role = Role::find($id);
        $grouped = permissionDisplayGrouped();

        return view('role.assignPermission', [
            'page_title'     => 'Assign Permission',
            'role'           => $role,
            'permisssions'   => $grouped ? null : Permission::where('status', 'enable')->get(),
            'permisssions_grouped' => $grouped ? Permission::getGroupedForAssign('enable') : null,
            'display_grouped' => $grouped,
        ]);
    }

    public function permissionUpdate(Request $request)
    {
        if (Auth::user()->email == 'admin@gmail.com') {
            return redirect()->back()->with('error_message', 'You can not Change Permission');
        }

        $type = 'RolePermission';
        $role = Role::findOrFail($request->id);
        $oldPermissions = $role->permissions->pluck('name')->sort()->values()->toArray();

        $permissions = $request->permissions;
        $role->syncPermissions($permissions);

        // $newPermissions = $request->input('permissions', []);
        // $role->syncPermissions($newPermissions);

        $role->refresh();
        $updatedPermissions = $role->permissions->pluck('name')->sort()->values()->toArray();

        $addedPermissions = implode(', ', array_diff($updatedPermissions, $oldPermissions));
        $removedPermissions = implode(', ', array_diff($oldPermissions, $updatedPermissions));

        LogHistory::create([
            'log_type'   => $type,
            'log_id'     => $role->id,
            'old_info'   => json_encode(['permissions' => $removedPermissions]),
            'new_info'   => json_encode(['permissions'   => $addedPermissions]),
            'edit_by'    => Auth::user()->id
        ]);

        return redirect()->route('roles.index')->with('success_message', 'Permission Assigned for ' . $request->name);
    }

    public function userRole($email)
    {
        $list = User::where('email', $email)->first();
        return view('role.userRole', [
            'page_title' => 'Assign Role to User ',
            'roles'       => Role::where('name', '!=', 'SoftwareAdmin')->get(),
            'user'       => $list
        ]);
    }


    public function userRoleUpdate(Request $request)
    {
        $user = User::find($request->id);

        $type = 'UserRole';
        // Get old roles before updating
        $oldRoles = $user->roles->pluck('name')->sort()->values()->toArray();

        if (Auth::user()->email == 'admin@gmail.com' || $user->id == 1) {
            if ($user->hasRole('Admin') || $user->hasRole('Software Admin')) {
                return redirect()->back()->with('error_message', 'You can not change Admin Role');
            } else {
                $user_detils = User_details::where('user_id', $user->id)->first();

                if ($user_detils != null) {
                    $user_detils->last_edit_by = Auth::user()->id;
                    $user_detils->save();
                    $user->syncRoles($request->role);
                } else {
                    return redirect()->back()->with('error_message', 'You can not change');
                }
                Artisan::call('cache:clear');
            }
        } else {
            $user_detils = User_details::where('user_id', $user->id)->first();
            // dd(auth()->user()->id);
            $user_detils->last_edit_by = auth()->user()->id;
            $user_detils->save();

            $user->syncRoles($request->role);
        }

        // Refresh user to get updated roles
        $user->refresh();
        $newRoles = $user->roles->pluck('name')->sort()->values()->toArray();

        // Calculate differences - only store what changed
        $removedRoles = array_diff($oldRoles, $newRoles);
        $addedRoles = array_diff($newRoles, $oldRoles);

        // Prepare old_info and new_info with only the differences
        $old_info = ['roles' => implode(', ', $removedRoles)];
        $new_info = ['roles' => implode(', ', $addedRoles)];

        (new EditLogHistory)->editLogSave($user, $type, $old_info, $new_info);

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

        return redirect()->back()->with('success_message', 'Role Update Done');
    }
}
