<?php

namespace Modules\Auth\Services;

use App\Models\User;

use Modules\Core\Enums\RolesEnum;
use Modules\Core\Exceptions\ApiValidationException;

class RoleGuardService
{
    public function validate(User $targetUser, array $roles): void
    {
        $authUser = authUser();
        $config = config('role_hierarchy');

        /*
        |--------------------------------------------------------------------------
        | Only Admin and Super Admin can assign roles
        |--------------------------------------------------------------------------
        */

        if (!$authUser->hasAnyRole($config['role_managers'])) {
            ApiValidationException::message(
                'You are not authorized to assign roles.'
            );
        }

        /*
        |--------------------------------------------------------------------------
        | Only one Super Admin
        |--------------------------------------------------------------------------
        */

        if (in_array(RolesEnum::SUPER_ADMIN->value, $roles)) {
            if (count($roles) > 1) {
                ApiValidationException::message(
                    'Super Admin must have single role only.'
                );
            }

            $exists = User::role(RolesEnum::SUPER_ADMIN->value)
                ->where('id', '!=', $targetUser->id)
                ->exists();

            if ($exists) {
                ApiValidationException::message(
                    'Only one Super Admin allowed.'
                );
            }
        }

        /*
        |--------------------------------------------------------------------------
        | First admin protection
        |--------------------------------------------------------------------------
        */

        $firstAdmin = User::where('id', $config['first_admin_id'])->first();

        if ($firstAdmin && $targetUser->id === $firstAdmin->id) {
            if (count($roles) > 1) {
                ApiValidationException::message(
                    'First Admin must keep single role.'
                );
            }
        }

        /*
        |--------------------------------------------------------------------------
        | Admin cannot assign Super Admin
        |--------------------------------------------------------------------------
        */

        if ($authUser->hasRole(RolesEnum::ADMIN->value)) {
            if (in_array(RolesEnum::SUPER_ADMIN->value, $roles)) {
                ApiValidationException::message(
                    'Admin cannot assign Super Admin role.'
                );
            }

            if ($targetUser->hasRole(RolesEnum::SUPER_ADMIN->value)) {
                ApiValidationException::message(
                    'Admin cannot modify Super Admin.'
                );
            }
        }

        /*
        |--------------------------------------------------------------------------
        | Employee protection
        |--------------------------------------------------------------------------
        */

        if ($targetUser->isEmployeeUser() && !in_array(RolesEnum::EMPLOYEES->value, $roles)) {
            ApiValidationException::message(
                'Employees role cannot be removed.'
            );
        }

        /*
        |--------------------------------------------------------------------------
        | Department roles require employee role
        |--------------------------------------------------------------------------
        */

        if (array_intersect($roles, $config['department_roles'])) {
            if (!$targetUser->isEmployeeUser()) {
                ApiValidationException::message(
                    'Department roles can only be assigned to employees.'
                );
            }

            if (!in_array(RolesEnum::EMPLOYEES->value, $roles) && !$targetUser->hasRole(RolesEnum::EMPLOYEES->value)) {
                ApiValidationException::errors([
                    'roles' => ['Department roles require Employees role.']
                ]);
            }
        }

        /*
        |--------------------------------------------------------------------------
        | System owner protection
        |--------------------------------------------------------------------------
        */

        if ($targetUser->id === $config['system_owner_id'] && ! in_array(RolesEnum::SUPER_ADMIN->value, $roles)) {
            ApiValidationException::message(
                'System owner must keep Super Admin role.'
            );
        }
    }
}
