<?php

namespace App\Services;

use App\Models\User;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use Illuminate\Support\Collection;

class RoleAssignmentService
{
    /**
     * Assign a role to a user.
     *
     * @param User $user
     * @param string $roleName
     * @return void
     */
    public function assignRole(User $user, string $roleName): void
    {
        $role = Role::where('name', $roleName)->first();

        if ($role) {
            $user->assignRole($role);
        }
    }

    /**
     * Sync roles for a user (replace all existing roles).
     *
     * @param User $user
     * @param array $roleNames
     * @return void
     */
    public function syncRoles(User $user, array $roleNames): void
    {
        $user->syncRoles($roleNames);
    }

    /**
     * Remove a role from a user.
     *
     * @param User $user
     * @param string $roleName
     * @return void
     */
    public function removeRole(User $user, string $roleName): void
    {
        $user->removeRole($roleName);
    }

    /**
     * Get permissions for a role.
     *
     * @param string $roleName
     * @return Collection
     */
    public function getPermissionsForRole(string $roleName): Collection
    {
        $role = Role::where('name', $roleName)->first();

        if (!$role) {
            return collect();
        }

        return $role->permissions;
    }

    /**
     * Sync permissions for a role.
     *
     * @param Role $role
     * @param array $permissionNames
     * @return void
     */
    public function syncPermissions(Role $role, array $permissionNames): void
    {
        $permissions = Permission::whereIn('name', $permissionNames)->get();
        $role->syncPermissions($permissions);
    }

    /**
     * Check if a user can assign a specific role.
     *
     * @param User $assigner
     * @param string $roleName
     * @return bool
     */
    public function canAssignRole(User $assigner, string $roleName): bool
    {
        // Only Super Manager can assign Super Manager or Manager roles
        if (in_array($roleName, ['Super Manager', 'Manager'])) {
            return $assigner->hasRole('Super Manager');
        }

        // Super Manager and Manager can assign other roles
        return $assigner->hasAnyRole(['Super Manager', 'Manager']);
    }

    /**
     * Get all available roles.
     *
     * @return Collection
     */
    public function getAllRoles(): Collection
    {
        return Role::with('permissions')->orderBy('name')->get();
    }

    /**
     * Get roles that can be assigned by a user.
     *
     * @param User $user
     * @return Collection
     */
    public function getAssignableRoles(User $user): Collection
    {
        if ($user->hasRole('Super Manager')) {
            return $this->getAllRoles();
        }

        if ($user->hasRole('Manager')) {
            return Role::whereNotIn('name', ['Super Manager', 'Manager'])
                ->orderBy('name')
                ->get();
        }

        return collect();
    }

    /**
     * Create a new role with permissions.
     *
     * @param string $name
     * @param string $theme
     * @param array $permissionNames
     * @return Role
     */
    public function createRole(string $name, string $theme = 'default', array $permissionNames = []): Role
    {
        $role = Role::create([
            'name' => $name,
            'guard_name' => 'web',
        ]);

        $role->update(['theme' => $theme]);

        if (!empty($permissionNames)) {
            $this->syncPermissions($role, $permissionNames);
        }

        return $role;
    }

    /**
     * Update role theme.
     *
     * @param Role $role
     * @param string $theme
     * @return void
     */
    public function updateRoleTheme(Role $role, string $theme): void
    {
        $role->update(['theme' => $theme]);
    }

    /**
     * Get default theme for a role.
     *
     * @param string $roleName
     * @return string
     */
    public function getDefaultTheme(string $roleName): string
    {
        $themes = [
            'Super Manager' => 'dark',
            'Manager' => 'blue',
            'Members' => 'default',
            'Trainers' => 'green',
            'Trainees' => 'light',
            'Mentor' => 'purple',
            'Mentee' => 'light',
            'Partners' => 'blue',
            'Contributor' => 'green',
            'Health Marketor' => 'red',
        ];

        return $themes[$roleName] ?? 'default';
    }

    /**
     * Get all permissions grouped by resource.
     *
     * @return Collection
     */
    public function getPermissionsGrouped(): Collection
    {
        return Permission::all()->groupBy(function ($permission) {
            $parts = explode(' ', $permission->name);
            return $parts[1] ?? 'other';
        });
    }
}
