<?php

namespace App\Services\Auth;

use App\Models\Tenant;
use App\Models\TenantMembership;
use App\Models\User;
use App\Support\TenantRole;

/**
 * Capability Resolver
 *
 * Resolves user memberships and capabilities for a given tenant.
 * Caches results per request to avoid N+1 queries.
 */
class CapabilityResolver
{
    private array $resolvedMemberships = [];

    /**
     * Get the user's role for a tenant
     */
    public function getRole(User $user, Tenant $tenant): ?TenantRole
    {
        if ($user->isPlatformSuperadmin()) {
            return TenantRole::Owner;
        }

        $membership = $this->getMembership($user, $tenant);

        if ($membership === null) {
            return null;
        }

        return TenantRole::tryFrom($membership['role']);
    }

    /**
     * Check if user can perform a capability on a tenant
     */
    public function can(User $user, Tenant $tenant, string $capability): bool
    {
        if ($user->isPlatformSuperadmin()) {
            return true;
        }

        $role = $this->getRole($user, $tenant);

        if ($role === null) {
            return false;
        }

        return RoleCapabilityMap::hasCapability($role, $capability);
    }

    /**
     * Check if user has any membership for a tenant
     */
    public function isMember(User $user, Tenant $tenant): bool
    {
        if ($user->isPlatformSuperadmin()) {
            return true;
        }

        return $this->getMembership($user, $tenant) !== null;
    }

    /**
     * Get membership details (cached per request)
     */
    private function getMembership(User $user, Tenant $tenant): ?array
    {
        $cacheKey = "membership_{$user->id}_{$tenant->id}";

        if (! isset($this->resolvedMemberships[$cacheKey])) {
            $membership = TenantMembership::query()
                ->where('user_id', $user->id)
                ->where('tenant_id', $tenant->id)
                ->first(['role', 'source', 'source_ref']);

            $this->resolvedMemberships[$cacheKey] = $membership?->toArray();
        }

        return $this->resolvedMemberships[$cacheKey];
    }

    /**
     * Clear cached memberships (useful for testing or after membership changes)
     */
    public function clearCache(): void
    {
        $this->resolvedMemberships = [];
    }
}
