<?php

namespace App\Controllers;

use App\Controllers\BaseController;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Shield\Entities\User;

// Models
use App\Models\EmployeeModel;


// Entities
use App\Entities\Employee;


class AdministratorController extends BaseController
{
    private function superadminAndAdminOnly()
    {
        if(!auth()->user()->inGroup('admin', 'superadmin'))
            return redirect()->to('/hi')->with('error', 'You do not have access to User Maintenance page.');
    }

    public function index()
    {
        $this->superadminAndAdminOnly();

        $users = auth()->getProvider()->findAll();

        $htmlTable = new \CodeIgniter\View\Table();
        $htmlTable->setTemplate($this->adminLTETableTemplate());

        $data['tblUsers'] = "";
        
        if($users == null)
        {
            $data['tblUsers'] = '<p>No users found.</p>';
        }
        else
        {
            $htmlTable->setHeading('Employee ID', 'Username', 'Email', 'Display Name', 'Active', 'Action');

            foreach($users as $user)
            {
                if(!auth()->user()->inGroup('superadmin') && $user->inGroup('superadmin')) continue;

                //$iconView = '<a href="#" class="ml-3" data-toggle="modal" data-target="#mdlViewUser" onclick="GetUserById(' . $user->id . ')"><i class="fas fa-eye "></i></a>';
                $iconView = '<a href="#" class="ml-3" onclick="GetUserByIdForView(' . $user->id . ')" data-toggle="tooltip" title="View User"><i class="fas fa-eye "></i></a>';
                $iconEdit = '<a href="#" class="ml-3" data-toggle="tooltip" title="Edit User"' . 
                            'data-id="' . $user->id . 
                            '" data-employeeid="' . $user->employee_id . 
                            '" data-displayname="' . $user->display_name . 
                            '" data-username="' . $user->username . 
                            '" data-email="' . $user->email . 
                            '" data-active="' . $user->active . 
                            '" onclick="GetUserByIdForEdit(this)"><i class="fas fa-edit"></i></a>';
                //$iconDelete = '<form action="adminuser/deleteuser" method="POST" class="d-inline-block" data-toggle="tooltip" title="Delete User"><input type="hidden" name="id" value="' . $user->id . '"/><a type="submit" onclick="return DeleteUserByID()" class="ml-3"><i class="fas fa-trash"></i></a></form>';
                $iconDelete = '<a href="/adminuser/deleteuser/' . $user->id . '" onclick="return confirm(\'Are you sure you want to delete this user?\')" class="ml-3"><i class="fas fa-trash"></i></a>';
                $iconUserGroup = '<a href="/adminuser/editusergroup/' . $user->id . '" class="ml-3" data-toggle="tooltip" title="Change User Group"><i class="fas fa-users"></i></a>';
                $iconUserPermission = '<a href="/adminuser/edituserpermission/' . $user->id . '" class="ml-3" data-toggle="tooltip" title="Change User Permission"><i class="fas fa-lock"></i></a>';
                $iconChangePass = '<a href="#" class="ml-3" ' . 
                            'data-id="' . $user->id . 
                            '" data-displayname="' . $user->display_name . 
                            '" data-username="' . $user->username .  
                            '" onclick="GetUserByIdForPassEdit(this)" data-toggle="tooltip" title="Change Password"><i class="fas fa-key"></i></a>';
                $htmlTable->addRow($user->employee_id, $user->username, $user->email, $user->display_name, $user->active ? "Yes" : "No", "$iconView $iconEdit $iconUserGroup $iconUserPermission $iconChangePass $iconDelete");
            }
            $data['tblUsers'] =  $htmlTable->generate();
        }

        return view('admin/usermaintenance', $data);
    }

    public function newUserView()
    {
        $this->superadminAndAdminOnly();

        return view('admin/newuserview');
    }

    public function saveNewUser()
    {
        // Get the User Provider (UserModel by default)
        $users = auth()->getProvider();

        $user = new User([
            'username' => $this->request->getPost('username'),
            'email'    => $this->request->getPost('email'),
            'password' => $this->request->getPost('password'),
            'employee_id' => $this->request->getPost('employee_id'),
            'display_name' => $this->request->getPost('display_name'),
        ]);
        
        if($users->save($user))
        {
            // To get the complete user object with ID, we need to get from the database
            $user = $users->findById($users->getInsertID());

            // Add to default group
            $users->addToDefaultGroup($user);

            // Activate user
            $user->activate();

            return redirect()->to('/adminuser')->with('message', "{$user->display_name} user added.");
        }
        else
            return redirect()->back()->with('error', 'User creation failed.');
    }

    public function editUserGroupView($id)
    {
        $this->superadminAndAdminOnly();

        $user = auth()->getProvider()->findById($id);

        $data['user'] = $user;
        $data['allgroups'] = $this->getAllGroupsWithMembership($user);

        return view('admin/editusergroupview', $data);
    }

    public function saveEditedUserGroup()
    {
        $selectedGroups = $this->request->getPost('membershipgroups');
        $userid = $this->request->getPost('id');
        
        $user = auth()->getProvider()->findById($userid);

        call_user_func_array([$user, 'syncGroups'], $selectedGroups);

        return redirect()->back()->with('message', 'User Group Updated.');
    }

    public function editUserPermissionView($id)
    {
        $this->superadminAndAdminOnly();

        $user = auth()->getProvider()->findById($id);

        $data['user'] = $user;
        $data['membershipgroups'] = $this->getAllowedPermissionHierarchy($user);
        $data['allgroups'] = $this->getAllGroupsWithMembership($user);

        return view('admin/edituserpermissionview', $data);
    }


    public function updateUser()
    {
        // Get the User Provider (UserModel by default)
        $users = auth()->getProvider();

        $id = $this->request->getPost('id');
        $email = $this->request->getPost('email');
        $employeeid = $this->request->getPost('employee_id');
        $displayname = $this->request->getPost('display_name');
        $active = $this->request->getPost('active');

        $user = $users->findById($id);
        $user->fill([
            'email' => $email,
            'employee_id' => $employeeid,
            'display_name' => $displayname,
            'active' => $active ? 1 : 0
        ]);
        $users->save($user);

        return redirect()->to('/adminuser')->with('message', 'User updated successfully.');
    }

    public function updateUserPass()
    {
        // Get the User Provider (UserModel by default)
        $users = auth()->getProvider();

        $id = $this->request->getPost('id');
        $password = $this->request->getPost('password');

        $user = $users->findById($id);
        $user->fill([
            'password' => $password
        ]);
        $users->save($user);

        return redirect()->to('/adminuser')->with('message', 'User updated successfully.');
    }

    public function deleteUser($userid)
    {
        $users = auth()->getProvider();
        $result = $users->delete($userid, true);

        if($result)
            return redirect()->to('/adminuser')->with('message', 'User updated successfully.');    
        else
            return redirect()->to('/adminuser')->with('error', 'User deletion failed.');
    }

    public function newUserFromEmployeeList()
    {
        $data['employeeList'] = (new EmployeeModel())->findAll();

        return view('admin/newuserfromemplist', $data);
    }

    public function createUserFromEmployeeList($employeeid)
    {
        $users = auth()->getProvider();

        $employee = (new EmployeeModel())->where(['company_issued_id' => $employeeid, 'deleted_at' => NULL])->first();
        
        $user = new User([
            'username' => $employee->company_issued_id,
            'email'    => $employee->email_address,
            'password' => $employee->company_issued_id,
            'company_id' => $employee->company_id,
            'sys_emp_id' => $employee->employee_id,
            'employee_id' => $employee->company_issued_id,
            'display_name' => $employee->first_name." ".$employee->last_name,
        ]);

        if($users->save($user))
        {
            // To get the complete user object with ID, we need to get from the database
            $user = $users->findById($users->getInsertID());

            // Add to default group
            $users->addToDefaultGroup($user);

            // Activate user
            $user->activate();

            return redirect()->back()->with('message', 'User created successfully.');
        }
        else
            return redirect()->back()->with('error', 'User creation failed.');
    }



    // Methods called by AJAX and return JSON

    public function getUserById($id)
    {
        $this->superadminAndAdminOnly();

        $user = auth()->getProvider()->findById($id);
        
        $data['user'] = $user;
        
        $data['groups'] = $user->getGroups();
        $data['permissions'] = $this->getAllowedPermissionHierarchy($user);

        return $this->response->setJSON($data);
    }

    // .Methods called by AJAX and return JSON



    // Class specific methods
    private function adminLTETableTemplate()
    {
        $template = [
            'table_open' => '<table class="table table-head-fixed table-hover text-nowrap">'
        ];

        return $template;
    }

    private function getAllowedPermissionFlat($user)
    {
        $allPermissionList = config('AuthGroups')->permissions;
        $allowedPermissions = [];

        foreach($allPermissionList as $key => $value)
        {
            if($user->can($key))
            {
                $groupPermission = explode(".", $key);
                $allowedPermissions[] = ['id' => $key, 'group' => $groupPermission[0], 'permission' => $groupPermission[1], 'description' => $value, 'original' => [$key => $value]];
            }
        }

        return $allowedPermissions;
    }

    private function getAllPermissionWithAllowedFlat($user)
    {
        $allPermissionList = config('AuthGroups')->permissions;
        $allowedPermissions = [];

        foreach($allPermissionList as $key => $value)
        {
            $groupPermission = explode(".", $key);
                $allowedPermissions[] = ['id' => $key, 'group' => $groupPermission[0], 'permission' => $groupPermission[1], 'description' => $value, 'allowed' => $user->can($key), 'original' => [$key => $value]];
        }

        return $allowedPermissions;
    }

    private function getAllowedPermissionHierarchy($user)
    {
        $allPermissionList = config('AuthGroups')->permissions;
        $allowedPermissions = [];

        foreach ($allPermissionList as $key => $value) {
            if ($user->can($key)) { // Check if the user has permission
                $groupPermission = explode(".", $key);
                $group = $groupPermission[0];
                $permission = $groupPermission[1];
        
                // Initialize the group if it doesn't exist
                if (!isset($allowedPermissions[$group])) {
                    $allowedPermissions[$group] = [
                        'group' => $group,
                        'ismember' => $user->inGroup($group),
                        'permissions' => []
                    ];
                }
        
                // Add the permission to the respective group
                $allowedPermissions[$group]['permissions'][] = [
                    'id' => $key,
                    'permission' => $permission,
                    'description' => $value,
                    'allowed' => $user->can($key),
                    'original' => [$key => $value]
                ];
            }
        }        

        return $allowedPermissions;
    }

    private function getAllPermissionWithAllowedHierarchy($user)
    {
        $allPermissionList = config('AuthGroups')->permissions;
        $allowedPermissions = [];

        foreach ($allPermissionList as $key => $value) {
            $groupPermission = explode(".", $key);
            $group = $groupPermission[0];
            $permission = $groupPermission[1];
    
            // Initialize the group if it doesn't exist
            if (!isset($allowedPermissions[$group])) {
                $allowedPermissions[$group] = [
                    'group' => $group,
                    'ismember' => $user->inGroup($group),
                    'permissions' => []
                ];
            }
    
            // Add the permission to the respective group
            $allowedPermissions[$group]['permissions'][] = [
                'id' => $key,
                'permission' => $permission,
                'description' => $value,
                'allowed' => $user->can($key),
                'original' => [$key => $value]
            ];
        }

        return $allowedPermissions;
    }

    private function getAllGroupsWithMembership($user)
    {
        $groups = config('AuthGroups')->groups;

        foreach ($groups as $key => $value) {
            $groups[$key]['ismember'] = $user->inGroup($key);
        }

        if(!$user->inGroup('superadmin'))
        {
            if(array_key_exists('superadmin', $groups))
            {
                unset($groups['superadmin']);
            }
        }

        return $groups;
    }
}
