<?php

declare(strict_types=1);

final class MyronModuleEntitlementRepository
{
    public function __construct(private readonly ?MyronLicenseRepository $licenseRepository = null)
    {
    }

    /**
     * @return list<array<string, mixed>>
     */
    public function listModules(): array
    {
        $snapshot = $this->currentSnapshot();
        if ($snapshot === null || $snapshot->status !== MyronLicenseStatus::ACTIVE) {
            return [];
        }

        $modules = [];
        foreach ($snapshot->activeSkus as $sku) {
            $skuId = trim((string) ($sku['id'] ?? ''));
            $targetType = trim((string) ($sku['targetType'] ?? ''));
            if (str_starts_with($skuId, 'legacy-') || ($targetType !== '' && !in_array($targetType, ['module', 'module-bundle'], true))) {
                continue;
            }
            $definition = $this->moduleDefinition($skuId, $sku);
            $packageState = $this->packageState($definition['slug'], $skuId);

            $modules[] = [
                'slug' => $definition['slug'],
                'skuId' => $skuId,
                'displayName' => (string) ($sku['displayName'] ?? $definition['displayName']),
                'package' => $definition['package'],
                'status' => (string) ($sku['status'] ?? $snapshot->status),
                'packageStatus' => $packageState['status'],
                'installedVersion' => $packageState['installedVersion'],
                'renewsAt' => $sku['renewsAt'] ?? $snapshot->renewsAt,
                'expiresAt' => $snapshot->expiresAt,
            ];
        }

        return $modules;
    }

    /**
     * @return list<array<string, mixed>>
     */
    public function entitlements(?string $moduleSlug = null): array
    {
        $snapshot = $this->currentSnapshot();
        if ($snapshot === null || $snapshot->status !== MyronLicenseStatus::ACTIVE) {
            return [];
        }

        $entitlements = [];
        foreach ($this->listModules() as $module) {
            $slug = (string) ($module['slug'] ?? '');
            if ($moduleSlug !== null && $moduleSlug !== '' && $slug !== $moduleSlug) {
                continue;
            }

            $skuId = (string) ($module['skuId'] ?? '');
            $definition = $this->moduleDefinition($skuId, $module);

            $capabilities = [];
            foreach ($definition['capabilities'] as $capability) {
                if (($snapshot->capabilities[$capability] ?? false) === true) {
                    $capabilities[] = $capability;
                }
            }

            $entitlements[] = [
                'moduleSlug' => $slug,
                'skuId' => $skuId,
                'status' => (string) ($module['status'] ?? $snapshot->status),
                'capabilities' => $capabilities,
                'renewsAt' => $module['renewsAt'] ?? $snapshot->renewsAt,
            ];
        }

        return $entitlements;
    }

    private function currentSnapshot(): ?MyronEntitlementSnapshot
    {
        if ($this->licenseRepository instanceof MyronLicenseRepository) {
            return $this->licenseRepository->currentSnapshot();
        }

        if (function_exists('myronLicenseRepository')) {
            return myronLicenseRepository()->currentSnapshot();
        }

        return null;
    }

    public function currentSnapshotForRuntime(): ?MyronEntitlementSnapshot
    {
        return $this->currentSnapshot();
    }

    /**
     * @return array{status:string,installedVersion:string}
     */
    private function packageState(string $slug, string $skuId): array
    {
        if (!function_exists('myronModulePackageInstallLedger')) {
            return ['status' => 'unknown', 'installedVersion' => ''];
        }

        try {
            $ledger = myronModulePackageInstallLedger();
            return [
                'status' => $ledger->hasTrustedInstallForSlug($slug, $skuId) ? 'installed' : 'pending',
                'installedVersion' => $ledger->installedVersionForSku($skuId),
            ];
        } catch (Throwable) {
            return ['status' => 'unknown', 'installedVersion' => ''];
        }
    }

    /**
     * @param array<string, mixed> $source
     * @return array{slug:string,displayName:string,package:string,capabilities:list<string>}
     */
    private function moduleDefinition(string $skuId, array $source): array
    {
        $definitions = [
            'pro-funnels' => [
                'slug' => 'funnels',
                'displayName' => 'Funnels',
                'package' => 'pro-funnels',
                'capabilities' => [
                    'modules.install',
                    'analytics.providers',
                    'attribution.remove_public_bar',
                    'code.custom_injection',
                    'commerce.checkout_primitives',
                    'feeds.custom_api',
                    'forms.webhooks',
                    'site_type.mkt',
                ],
            ],
            'pro-lms' => [
                'slug' => 'lms',
                'displayName' => 'LMS',
                'package' => 'pro-lms',
                'capabilities' => [
                    'modules.install',
                    'site_type.edu',
                ],
            ],
            'pro-commerce' => [
                'slug' => 'commerce',
                'displayName' => 'Commerce',
                'package' => 'pro-commerce',
                'capabilities' => [
                    'modules.install',
                    'payment.providers',
                    'commerce.full',
                ],
            ],
            'pro-devops' => [
                'slug' => 'devops',
                'displayName' => 'Pro Operations',
                'package' => 'pro-devops',
                'capabilities' => [
                    'modules.install',
                    'snapshots.devops',
                    'devops.environments',
                    'multi_environment_workflow',
                    'deployment_group',
                ],
            ],
            'pro-byok-ai' => [
                'slug' => 'byok_ai',
                'displayName' => 'BYOK LLM',
                'package' => 'pro-byok-ai',
                'capabilities' => [
                    'modules.install',
                    'ai.byok_provider_config',
                    'mcp.byok_ai_actions',
                ],
            ],
        ];
        if (isset($definitions[$skuId])) {
            return $definitions[$skuId];
        }

        $slug = preg_replace('/^(pro|personal|agency|enterprise)-/', '', $skuId) ?? $skuId;
        $slug = str_replace('_', '-', strtolower($slug));
        $displayName = trim((string) ($source['displayName'] ?? ''));
        if ($displayName === '') {
            $displayName = implode(' ', array_map('ucfirst', explode('-', $slug)));
        }

        return [
            'slug' => $slug,
            'displayName' => $displayName,
            'package' => $skuId,
            'capabilities' => [],
        ];
    }
}
