<?php

namespace App\Services\Auth;

use App\Support\Auth\Capabilities;
use App\Support\TenantRole;

/**
 * Role to Capability Mapping (Single Source of Truth)
 *
 * This class defines which capabilities each role has.
 * All capability strings MUST be references from the Capabilities registry.
 */
class RoleCapabilityMap
{
    private static array $roleCapabilities = [
        TenantRole::Owner->value => [
            Capabilities::TENANT_VIEW,
            Capabilities::TENANT_MANAGE,
            Capabilities::TENANT_DELETE,
            Capabilities::TENANT_SYNC,
            Capabilities::SUPPORT_DIAGNOSTICS_VIEW,
            Capabilities::SUPPORT_REQUESTS_CREATE,
            Capabilities::TENANT_INVENTORY_SYNC_RUN,
            Capabilities::TENANT_FINDINGS_VIEW,
            Capabilities::TENANT_FINDINGS_TRIAGE,
            Capabilities::TENANT_FINDINGS_ASSIGN,
            Capabilities::TENANT_FINDINGS_RESOLVE,
            Capabilities::TENANT_FINDINGS_CLOSE,
            Capabilities::TENANT_FINDINGS_RISK_ACCEPT,
            Capabilities::FINDING_EXCEPTION_VIEW,
            Capabilities::FINDING_EXCEPTION_MANAGE,
            Capabilities::TENANT_VERIFICATION_ACKNOWLEDGE,

            Capabilities::TENANT_MEMBERSHIP_VIEW,
            Capabilities::TENANT_MEMBERSHIP_MANAGE,

            Capabilities::TENANT_ROLE_MAPPING_VIEW,
            Capabilities::TENANT_ROLE_MAPPING_MANAGE,

            Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE,
            Capabilities::TENANT_BACKUP_SCHEDULES_RUN,

            Capabilities::PROVIDER_VIEW,
            Capabilities::PROVIDER_MANAGE,
            Capabilities::PROVIDER_MANAGE_DEDICATED,
            Capabilities::PROVIDER_RUN,

            Capabilities::AUDIT_VIEW,

            Capabilities::ENTRA_ROLES_VIEW,
            Capabilities::ENTRA_ROLES_MANAGE,

            Capabilities::PERMISSION_POSTURE_VIEW,

            Capabilities::REVIEW_PACK_VIEW,
            Capabilities::REVIEW_PACK_MANAGE,
            Capabilities::ENVIRONMENT_REVIEW_VIEW,
            Capabilities::ENVIRONMENT_REVIEW_MANAGE,
            Capabilities::MANAGED_ENVIRONMENT_TRIAGE_REVIEW_MANAGE,
            Capabilities::EVIDENCE_VIEW,
            Capabilities::EVIDENCE_MANAGE,
        ],

        TenantRole::Manager->value => [
            Capabilities::TENANT_VIEW,
            Capabilities::TENANT_MANAGE,
            Capabilities::TENANT_SYNC,
            Capabilities::SUPPORT_DIAGNOSTICS_VIEW,
            Capabilities::SUPPORT_REQUESTS_CREATE,
            Capabilities::TENANT_INVENTORY_SYNC_RUN,
            Capabilities::TENANT_FINDINGS_VIEW,
            Capabilities::TENANT_FINDINGS_TRIAGE,
            Capabilities::TENANT_FINDINGS_ASSIGN,
            Capabilities::TENANT_FINDINGS_RESOLVE,
            Capabilities::TENANT_FINDINGS_CLOSE,
            Capabilities::TENANT_FINDINGS_RISK_ACCEPT,
            Capabilities::FINDING_EXCEPTION_VIEW,
            Capabilities::FINDING_EXCEPTION_MANAGE,
            Capabilities::TENANT_VERIFICATION_ACKNOWLEDGE,

            Capabilities::TENANT_MEMBERSHIP_VIEW,

            Capabilities::TENANT_ROLE_MAPPING_VIEW,

            Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE,
            Capabilities::TENANT_BACKUP_SCHEDULES_RUN,

            Capabilities::PROVIDER_VIEW,
            Capabilities::PROVIDER_MANAGE,
            Capabilities::PROVIDER_RUN,

            Capabilities::AUDIT_VIEW,

            Capabilities::ENTRA_ROLES_VIEW,
            Capabilities::ENTRA_ROLES_MANAGE,

            Capabilities::PERMISSION_POSTURE_VIEW,

            Capabilities::REVIEW_PACK_VIEW,
            Capabilities::REVIEW_PACK_MANAGE,
            Capabilities::ENVIRONMENT_REVIEW_VIEW,
            Capabilities::ENVIRONMENT_REVIEW_MANAGE,
            Capabilities::MANAGED_ENVIRONMENT_TRIAGE_REVIEW_MANAGE,
            Capabilities::EVIDENCE_VIEW,
            Capabilities::EVIDENCE_MANAGE,
        ],

        TenantRole::Operator->value => [
            Capabilities::TENANT_VIEW,
            Capabilities::TENANT_SYNC,
            Capabilities::SUPPORT_DIAGNOSTICS_VIEW,
            Capabilities::SUPPORT_REQUESTS_CREATE,
            Capabilities::TENANT_INVENTORY_SYNC_RUN,
            Capabilities::TENANT_FINDINGS_VIEW,
            Capabilities::TENANT_FINDINGS_TRIAGE,
            Capabilities::FINDING_EXCEPTION_VIEW,

            Capabilities::TENANT_MEMBERSHIP_VIEW,
            Capabilities::TENANT_ROLE_MAPPING_VIEW,

            Capabilities::TENANT_BACKUP_SCHEDULES_RUN,

            Capabilities::PROVIDER_VIEW,
            Capabilities::PROVIDER_RUN,

            Capabilities::AUDIT_VIEW,

            Capabilities::ENTRA_ROLES_VIEW,

            Capabilities::PERMISSION_POSTURE_VIEW,

            Capabilities::REVIEW_PACK_VIEW,
            Capabilities::ENVIRONMENT_REVIEW_VIEW,
            Capabilities::MANAGED_ENVIRONMENT_TRIAGE_REVIEW_MANAGE,
            Capabilities::EVIDENCE_VIEW,
        ],

        TenantRole::Readonly->value => [
            Capabilities::TENANT_VIEW,
            Capabilities::TENANT_FINDINGS_VIEW,
            Capabilities::FINDING_EXCEPTION_VIEW,

            Capabilities::TENANT_MEMBERSHIP_VIEW,
            Capabilities::TENANT_ROLE_MAPPING_VIEW,

            Capabilities::PROVIDER_VIEW,

            Capabilities::AUDIT_VIEW,

            Capabilities::ENTRA_ROLES_VIEW,

            Capabilities::PERMISSION_POSTURE_VIEW,

            Capabilities::REVIEW_PACK_VIEW,
            Capabilities::ENVIRONMENT_REVIEW_VIEW,
            Capabilities::EVIDENCE_VIEW,
        ],
    ];

    /**
     * Get all capabilities for a given role
     *
     * @return array<string>
     */
    public static function getCapabilities(TenantRole|string $role): array
    {
        $roleValue = $role instanceof TenantRole ? $role->value : $role;

        return self::$roleCapabilities[$roleValue] ?? [];
    }

    /**
     * Get all role values that grant a given capability.
     *
     * @return array<string>
     */
    public static function rolesWithCapability(string $capability): array
    {
        $roles = [];

        foreach (self::$roleCapabilities as $role => $capabilities) {
            if (in_array($capability, $capabilities, true)) {
                $roles[] = $role;
            }
        }

        return $roles;
    }

    /**
     * Check if a role has a specific capability
     */
    public static function hasCapability(TenantRole|string $role, string $capability): bool
    {
        return in_array($capability, self::getCapabilities($role), true);
    }
}
