<?php

declare(strict_types=1);

namespace App\Support\Livewire\TrustedState;

use InvalidArgumentException;

final class TrustedStatePolicy
{
    public const MANAGED_ENVIRONMENT_ONBOARDING_WIZARD = 'managed_environment_onboarding_wizard';

    public const TENANT_REQUIRED_PERMISSIONS = 'tenant_required_permissions';

    /**
     * @return array{
     *     name: string,
     *     state_class: string,
     *     php_type: string,
     *     source_of_truth: string,
     *     used_for_protected_action: bool,
     *     revalidation_required: bool,
     *     implementation_markers: list<string>,
     *     notes: string
     * }
     */
    private function field(
        string $name,
        TrustedStateClass $stateClass,
        string $phpType,
        string $sourceOfTruth,
        bool $usedForProtectedAction,
        bool $revalidationRequired,
        array $implementationMarkers,
        string $notes,
    ): array {
        return [
            'name' => $name,
            'state_class' => $stateClass->value,
            'php_type' => $phpType,
            'source_of_truth' => $sourceOfTruth,
            'used_for_protected_action' => $usedForProtectedAction,
            'revalidation_required' => $revalidationRequired,
            'implementation_markers' => $implementationMarkers,
            'notes' => $notes,
        ];
    }

    /**
     * @return array<string, array{
     *     component_name: string,
     *     plane: string,
     *     route_anchor: string|null,
     *     authority_sources: list<string>,
     *     locked_identities: list<string>,
     *     locked_identity_fields: list<array{
     *         name: string,
     *         state_class: string,
     *         php_type: string,
     *         source_of_truth: string,
     *         used_for_protected_action: bool,
     *         revalidation_required: bool,
     *         implementation_markers: list<string>,
     *         notes: string
     *     }>,
     *     mutable_selectors: list<string>,
     *     mutable_selector_fields: list<array{
     *         name: string,
     *         state_class: string,
     *         php_type: string,
     *         source_of_truth: string,
     *         used_for_protected_action: bool,
     *         revalidation_required: bool,
     *         implementation_markers: list<string>,
     *         notes: string
     *     }>,
     *     server_derived_authority_fields: list<array{
     *         name: string,
     *         state_class: string,
     *         php_type: string,
     *         source_of_truth: string,
     *         used_for_protected_action: bool,
     *         revalidation_required: bool,
     *         implementation_markers: list<string>,
     *         notes: string
     *     }>,
     *     forbidden_public_authority_fields: list<string>
     * }>
     */
    public function firstSlice(): array
    {
        return [
            self::MANAGED_ENVIRONMENT_ONBOARDING_WIZARD => [
                'component_name' => 'Managed environment onboarding wizard',
                'plane' => 'admin_workspace',
                'route_anchor' => 'onboarding_draft',
                'authority_sources' => [
                    'route_binding',
                    'workspace_context',
                    'persisted_onboarding_draft',
                    'explicit_scoped_query',
                ],
                'locked_identities' => [
                    'workspace_id',
                    'managed_environment_id',
                    'onboarding_session_id',
                ],
                'locked_identity_fields' => [
                    $this->field(
                        name: 'managedEnvironmentId',
                        stateClass: TrustedStateClass::LockedIdentity,
                        phpType: '?int',
                        sourceOfTruth: 'persisted_onboarding_draft',
                        usedForProtectedAction: true,
                        revalidationRequired: true,
                        implementationMarkers: [
                            "#[Locked]\n    public ?int \$managedEnvironmentId = null;",
                            'public ?int $managedEnvironmentId = null;',
                            'currentManagedEnvironmentRecord()',
                        ],
                        notes: 'Continuity-only tenant identity; protected actions must re-resolve the tenant record before use.',
                    ),
                    $this->field(
                        name: 'onboardingSessionId',
                        stateClass: TrustedStateClass::LockedIdentity,
                        phpType: '?int',
                        sourceOfTruth: 'persisted_onboarding_draft',
                        usedForProtectedAction: true,
                        revalidationRequired: true,
                        implementationMarkers: [
                            "#[Locked]\n    public ?int \$onboardingSessionId = null;",
                            'public ?int $onboardingSessionId = null;',
                            'currentOnboardingSessionRecord()',
                        ],
                        notes: 'Continuity-only draft identity; protected actions re-resolve canonical draft truth from the persisted session.',
                    ),
                ],
                'mutable_selectors' => [
                    'selected_provider_connection_id',
                    'selected_bootstrap_operation_types',
                ],
                'mutable_selector_fields' => [
                    $this->field(
                        name: 'selectedProviderConnectionId',
                        stateClass: TrustedStateClass::Presentation,
                        phpType: '?int',
                        sourceOfTruth: 'explicit_scoped_query',
                        usedForProtectedAction: true,
                        revalidationRequired: true,
                        implementationMarkers: [
                            'public ?int $selectedProviderConnectionId = null;',
                            'selectedProviderConnectionId',
                            'resolveOnboardingDraft(',
                        ],
                        notes: 'Provider selection is a mutable proposal and must be validated against the canonical draft and workspace before use.',
                    ),
                    $this->field(
                        name: 'selectedBootstrapOperationTypes',
                        stateClass: TrustedStateClass::Presentation,
                        phpType: 'array<int, string>',
                        sourceOfTruth: 'presentation_only',
                        usedForProtectedAction: false,
                        revalidationRequired: false,
                        implementationMarkers: [
                            'public array $selectedBootstrapOperationTypes = [];',
                        ],
                        notes: 'Wizard UI choice only; it does not define tenant or workspace authority.',
                    ),
                ],
                'server_derived_authority_fields' => [
                    $this->field(
                        name: 'workspace',
                        stateClass: TrustedStateClass::ServerDerivedAuthority,
                        phpType: 'Workspace',
                        sourceOfTruth: 'workspace_context',
                        usedForProtectedAction: true,
                        revalidationRequired: true,
                        implementationMarkers: [
                            'public Workspace $workspace;',
                            'currentWorkspaceForMember(',
                        ],
                        notes: 'Workspace membership and current workspace context outrank any client-submitted state.',
                    ),
                    $this->field(
                        name: 'onboardingSession',
                        stateClass: TrustedStateClass::ServerDerivedAuthority,
                        phpType: '?ManagedEnvironmentOnboardingSession',
                        sourceOfTruth: 'persisted_onboarding_draft',
                        usedForProtectedAction: true,
                        revalidationRequired: true,
                        implementationMarkers: [
                            'public ?ManagedEnvironmentOnboardingSession $onboardingSession = null;',
                            'resolveOnboardingDraft(',
                            'currentOnboardingSessionRecord()',
                        ],
                        notes: 'Draft model instances remain convenience state only and are refreshed from canonical persisted draft truth.',
                    ),
                    $this->field(
                        name: 'managedEnvironment',
                        stateClass: TrustedStateClass::ServerDerivedAuthority,
                        phpType: '?ManagedEnvironment',
                        sourceOfTruth: 'explicit_scoped_query',
                        usedForProtectedAction: true,
                        revalidationRequired: true,
                        implementationMarkers: [
                            'public ?ManagedEnvironment $managedEnvironment = null;',
                            'currentManagedEnvironmentRecord()',
                        ],
                        notes: 'ManagedEnvironment model instances are display helpers only and must be re-derived from draft or scoped tenant queries.',
                    ),
                ],
                'forbidden_public_authority_fields' => [
                    'workspace',
                    'managedEnvironment',
                    'onboardingSession',
                ],
            ],
            self::TENANT_REQUIRED_PERMISSIONS => [
                'component_name' => 'ManagedEnvironment required permissions',
                'plane' => 'admin_tenant',
                'route_anchor' => 'tenant',
                'authority_sources' => [
                    'route_binding',
                    'workspace_context',
                    'explicit_scoped_query',
                ],
                'locked_identities' => [
                    'scoped_tenant_id',
                ],
                'locked_identity_fields' => [
                    $this->field(
                        name: 'scopedTenantId',
                        stateClass: TrustedStateClass::LockedIdentity,
                        phpType: '?int',
                        sourceOfTruth: 'route_binding',
                        usedForProtectedAction: true,
                        revalidationRequired: true,
                        implementationMarkers: [
                            "#[Locked]\n    public ?int \$scopedTenantId = null;",
                            'public ?int $scopedTenantId = null;',
                            'trustedScopedTenant()',
                        ],
                        notes: 'Route-derived tenant identity stays locked for continuity and is re-scoped against workspace context before use.',
                    ),
                ],
                'mutable_selectors' => [
                    'status',
                    'type',
                    'features',
                    'search',
                ],
                'mutable_selector_fields' => [
                    $this->field(
                        name: 'status',
                        stateClass: TrustedStateClass::Presentation,
                        phpType: 'string',
                        sourceOfTruth: 'presentation_only',
                        usedForProtectedAction: false,
                        revalidationRequired: false,
                        implementationMarkers: [
                            "SelectFilter::make('status')",
                            "'status' => ['value' => 'missing'],",
                            "'status' => \$filters['status']['value'] ?? data_get(\$this->tableFilters, 'status.value'),",
                        ],
                        notes: 'Filter-only state for the permissions view model.',
                    ),
                    $this->field(
                        name: 'type',
                        stateClass: TrustedStateClass::Presentation,
                        phpType: 'string',
                        sourceOfTruth: 'presentation_only',
                        usedForProtectedAction: false,
                        revalidationRequired: false,
                        implementationMarkers: [
                            "SelectFilter::make('type')",
                            "'type' => ['value' => 'all'],",
                            "'type' => \$filters['type']['value'] ?? data_get(\$this->tableFilters, 'type.value'),",
                        ],
                        notes: 'Filter-only state for the permissions view model.',
                    ),
                    $this->field(
                        name: 'features',
                        stateClass: TrustedStateClass::Presentation,
                        phpType: 'array<int, string>',
                        sourceOfTruth: 'presentation_only',
                        usedForProtectedAction: false,
                        revalidationRequired: false,
                        implementationMarkers: [
                            "SelectFilter::make('features')",
                            "'features' => ['values' => []],",
                            "'features' => \$filters['features']['values'] ?? data_get(\$this->tableFilters, 'features.values', []),",
                        ],
                        notes: 'Filter-only state for the permissions view model.',
                    ),
                    $this->field(
                        name: 'search',
                        stateClass: TrustedStateClass::Presentation,
                        phpType: 'string',
                        sourceOfTruth: 'presentation_only',
                        usedForProtectedAction: false,
                        revalidationRequired: false,
                        implementationMarkers: [
                            '->searchable()',
                            "'search' => \$search ?? \$this->tableSearch,",
                            "\$this->tableSearch = '';",
                        ],
                        notes: 'Filter-only state for the permissions view model.',
                    ),
                ],
                'server_derived_authority_fields' => [
                    $this->field(
                        name: 'scopedTenant',
                        stateClass: TrustedStateClass::ServerDerivedAuthority,
                        phpType: '?ManagedEnvironment',
                        sourceOfTruth: 'explicit_scoped_query',
                        usedForProtectedAction: true,
                        revalidationRequired: true,
                        implementationMarkers: [
                            'resolveScopedTenant()',
                            'trustedScopedTenant()',
                            'currentWorkspaceId(request())',
                        ],
                        notes: 'ManagedEnvironment scope remains route- and workspace-derived even when mutable filters change.',
                    ),
                ],
                'forbidden_public_authority_fields' => [
                    'scopedTenant',
                ],
            ],
        ];
    }

    /**
     * @return array{
     *     component_name: string,
     *     plane: string,
     *     route_anchor: string|null,
     *     authority_sources: list<string>,
     *     locked_identities: list<string>,
     *     locked_identity_fields: list<array{
     *         name: string,
     *         state_class: string,
     *         php_type: string,
     *         source_of_truth: string,
     *         used_for_protected_action: bool,
     *         revalidation_required: bool,
     *         implementation_markers: list<string>,
     *         notes: string
     *     }>,
     *     mutable_selectors: list<string>,
     *     mutable_selector_fields: list<array{
     *         name: string,
     *         state_class: string,
     *         php_type: string,
     *         source_of_truth: string,
     *         used_for_protected_action: bool,
     *         revalidation_required: bool,
     *         implementation_markers: list<string>,
     *         notes: string
     *     }>,
     *     server_derived_authority_fields: list<array{
     *         name: string,
     *         state_class: string,
     *         php_type: string,
     *         source_of_truth: string,
     *         used_for_protected_action: bool,
     *         revalidation_required: bool,
     *         implementation_markers: list<string>,
     *         notes: string
     *     }>,
     *     forbidden_public_authority_fields: list<string>
     * }
     */
    public function forComponent(string $component): array
    {
        $policy = $this->firstSlice()[$component] ?? null;

        if ($policy === null) {
            throw new InvalidArgumentException("Unknown trusted-state component [{$component}].");
        }

        return $policy;
    }

    /**
     * @return list<string>
     */
    public function components(): array
    {
        return array_keys($this->firstSlice());
    }
}
