<?php

declare(strict_types=1);

namespace App\Services\Entitlements;

use App\Models\ManagedEnvironment;
use App\Models\Workspace;
use App\Models\WorkspaceSetting;
use App\Services\Settings\SettingsResolver;
use Carbon\CarbonInterface;

final class WorkspaceEntitlementResolver
{
    public const SETTING_DOMAIN = 'entitlements';

    public const SETTING_PLAN_PROFILE = 'plan_profile';

    public const SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_VALUE = 'managed_tenant_limit_override_value';

    public const SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_REASON = 'managed_tenant_limit_override_reason';

    public const SETTING_REVIEW_PACK_GENERATION_OVERRIDE_VALUE = 'review_pack_generation_override_value';

    public const SETTING_REVIEW_PACK_GENERATION_OVERRIDE_REASON = 'review_pack_generation_override_reason';

    public const KEY_MANAGED_TENANT_ACTIVATION_LIMIT = 'managed_tenant_activation_limit';

    public const KEY_REVIEW_PACK_GENERATION_ENABLED = 'review_pack_generation_enabled';

    public function __construct(
        private SettingsResolver $settingsResolver,
        private WorkspacePlanProfileCatalog $planProfileCatalog,
    ) {}

    /**
     * @return array{
     *     plan_profile: array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool},
     *     decisions: array<string, array{
     *         workspace_id: int,
     *         plan_profile_id: string,
     *         plan_profile_label: string,
     *         plan_profile_description: string,
     *         key: string,
     *         effective_value: int|bool,
     *         source: 'plan_profile_default'|'workspace_override',
     *         rationale: string|null,
     *         current_usage: int|null,
     *         remaining_capacity: int|null,
     *         is_blocked: bool,
     *         block_reason: string|null,
     *         last_changed_at: CarbonInterface|null,
     *         last_changed_by: string|null
     *     }>
     * }
     */
    public function summary(Workspace $workspace): array
    {
        $planProfile = $this->resolvePlanProfile($workspace);

        return [
            'plan_profile' => $planProfile,
            'decisions' => [
                self::KEY_MANAGED_TENANT_ACTIVATION_LIMIT => $this->resolve($workspace, self::KEY_MANAGED_TENANT_ACTIVATION_LIMIT, $planProfile),
                self::KEY_REVIEW_PACK_GENERATION_ENABLED => $this->resolve($workspace, self::KEY_REVIEW_PACK_GENERATION_ENABLED, $planProfile),
            ],
        ];
    }

    /**
     * @return array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool}
     */
    public function resolvePlanProfile(Workspace $workspace): array
    {
        $planProfileId = $this->settingsResolver->resolveValue(
            workspace: $workspace,
            domain: self::SETTING_DOMAIN,
            key: self::SETTING_PLAN_PROFILE,
        );

        return $this->planProfileCatalog->resolve(is_string($planProfileId) ? $planProfileId : null);
    }

    /**
     * @param  array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool}|null  $planProfile
     * @return array{
     *     workspace_id: int,
     *     plan_profile_id: string,
     *     plan_profile_label: string,
     *     plan_profile_description: string,
     *     key: string,
     *     effective_value: int|bool,
     *     source: 'plan_profile_default'|'workspace_override',
     *     rationale: string|null,
     *     current_usage: int|null,
     *     remaining_capacity: int|null,
     *     is_blocked: bool,
     *     block_reason: string|null,
     *     last_changed_at: CarbonInterface|null,
     *     last_changed_by: string|null
     * }
     */
    public function resolve(Workspace $workspace, string $key, ?array $planProfile = null): array
    {
        $planProfile ??= $this->resolvePlanProfile($workspace);
        $lastChanged = $this->lastChangedMetadata($workspace);

        return match ($key) {
            self::KEY_MANAGED_TENANT_ACTIVATION_LIMIT => $this->resolveManagedTenantActivationLimitDecision($workspace, $planProfile, $lastChanged),
            self::KEY_REVIEW_PACK_GENERATION_ENABLED => $this->resolveReviewPackGenerationDecision($workspace, $planProfile, $lastChanged),
            default => throw new \InvalidArgumentException(sprintf('Unknown workspace entitlement key: %s', $key)),
        };
    }

    /**
     * @param  array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool}  $planProfile
     * @param  array{last_changed_at: CarbonInterface|null, last_changed_by: string|null}  $lastChanged
     * @return array{
     *     workspace_id: int,
     *     plan_profile_id: string,
     *     plan_profile_label: string,
     *     plan_profile_description: string,
     *     key: string,
     *     effective_value: int,
     *     source: 'plan_profile_default'|'workspace_override',
     *     rationale: string|null,
     *     current_usage: int,
     *     remaining_capacity: int,
     *     is_blocked: bool,
     *     block_reason: string|null,
     *     last_changed_at: CarbonInterface|null,
     *     last_changed_by: string|null
     * }
     */
    private function resolveManagedTenantActivationLimitDecision(Workspace $workspace, array $planProfile, array $lastChanged): array
    {
        $overrideValue = $this->settingsResolver->resolveDetailed(
            workspace: $workspace,
            domain: self::SETTING_DOMAIN,
            key: self::SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_VALUE,
        );

        $overrideReason = $this->settingsResolver->resolveValue(
            workspace: $workspace,
            domain: self::SETTING_DOMAIN,
            key: self::SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_REASON,
        );

        $effectiveValue = is_int($overrideValue['value'])
            ? $overrideValue['value']
            : (int) $planProfile['managed_tenant_limit_default'];

        $source = $overrideValue['source'] === 'workspace_override'
            ? 'workspace_override'
            : 'plan_profile_default';

        $currentUsage = ManagedEnvironment::activeQuery()
            ->where('workspace_id', (int) $workspace->getKey())
            ->count();

        $remainingCapacity = $effectiveValue - $currentUsage;
        $isBlocked = $currentUsage >= $effectiveValue;
        $rationale = $source === 'workspace_override'
            ? (is_string($overrideReason) && $overrideReason !== '' ? $overrideReason : null)
            : (string) $planProfile['description'];

        return [
            'workspace_id' => (int) $workspace->getKey(),
            'plan_profile_id' => (string) $planProfile['id'],
            'plan_profile_label' => (string) $planProfile['label'],
            'plan_profile_description' => (string) $planProfile['description'],
            'key' => self::KEY_MANAGED_TENANT_ACTIVATION_LIMIT,
            'effective_value' => $effectiveValue,
            'source' => $source,
            'rationale' => $rationale,
            'current_usage' => $currentUsage,
            'remaining_capacity' => $remainingCapacity,
            'is_blocked' => $isBlocked,
            'block_reason' => $isBlocked
                ? $this->managedTenantLimitBlockReason($currentUsage, $effectiveValue, $source, $planProfile, $rationale)
                : null,
            'last_changed_at' => $lastChanged['last_changed_at'],
            'last_changed_by' => $lastChanged['last_changed_by'],
        ];
    }

    /**
     * @param  array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool}  $planProfile
     * @param  array{last_changed_at: CarbonInterface|null, last_changed_by: string|null}  $lastChanged
     * @return array{
     *     workspace_id: int,
     *     plan_profile_id: string,
     *     plan_profile_label: string,
     *     plan_profile_description: string,
     *     key: string,
     *     effective_value: bool,
     *     source: 'plan_profile_default'|'workspace_override',
     *     rationale: string|null,
     *     current_usage: null,
     *     remaining_capacity: null,
     *     is_blocked: bool,
     *     block_reason: string|null,
     *     last_changed_at: CarbonInterface|null,
     *     last_changed_by: string|null
     * }
     */
    private function resolveReviewPackGenerationDecision(Workspace $workspace, array $planProfile, array $lastChanged): array
    {
        $overrideValue = $this->settingsResolver->resolveDetailed(
            workspace: $workspace,
            domain: self::SETTING_DOMAIN,
            key: self::SETTING_REVIEW_PACK_GENERATION_OVERRIDE_VALUE,
        );

        $overrideReason = $this->settingsResolver->resolveValue(
            workspace: $workspace,
            domain: self::SETTING_DOMAIN,
            key: self::SETTING_REVIEW_PACK_GENERATION_OVERRIDE_REASON,
        );

        $effectiveValue = is_bool($overrideValue['value'])
            ? $overrideValue['value']
            : (bool) $planProfile['review_pack_generation_default'];

        $source = $overrideValue['source'] === 'workspace_override'
            ? 'workspace_override'
            : 'plan_profile_default';

        $rationale = $source === 'workspace_override'
            ? (is_string($overrideReason) && $overrideReason !== '' ? $overrideReason : null)
            : (string) $planProfile['description'];

        return [
            'workspace_id' => (int) $workspace->getKey(),
            'plan_profile_id' => (string) $planProfile['id'],
            'plan_profile_label' => (string) $planProfile['label'],
            'plan_profile_description' => (string) $planProfile['description'],
            'key' => self::KEY_REVIEW_PACK_GENERATION_ENABLED,
            'effective_value' => $effectiveValue,
            'source' => $source,
            'rationale' => $rationale,
            'current_usage' => null,
            'remaining_capacity' => null,
            'is_blocked' => ! $effectiveValue,
            'block_reason' => $effectiveValue
                ? null
                : $this->reviewPackGenerationBlockReason($source, $planProfile, $rationale),
            'last_changed_at' => $lastChanged['last_changed_at'],
            'last_changed_by' => $lastChanged['last_changed_by'],
        ];
    }

    /**
     * @return array{last_changed_at: CarbonInterface|null, last_changed_by: string|null}
     */
    private function lastChangedMetadata(Workspace $workspace): array
    {
        $record = WorkspaceSetting::query()
            ->where('workspace_id', (int) $workspace->getKey())
            ->where('domain', self::SETTING_DOMAIN)
            ->whereIn('key', [
                self::SETTING_PLAN_PROFILE,
                self::SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_VALUE,
                self::SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_REASON,
                self::SETTING_REVIEW_PACK_GENERATION_OVERRIDE_VALUE,
                self::SETTING_REVIEW_PACK_GENERATION_OVERRIDE_REASON,
            ])
            ->whereNotNull('updated_by_user_id')
            ->with('updatedByUser:id,name')
            ->latest('updated_at')
            ->latest('id')
            ->first();

        if (! $record instanceof WorkspaceSetting) {
            return [
                'last_changed_at' => null,
                'last_changed_by' => null,
            ];
        }

        return [
            'last_changed_at' => $record->updated_at,
            'last_changed_by' => $record->updatedByUser?->name,
        ];
    }

    /**
     * @param  array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool}  $planProfile
     */
    private function managedTenantLimitBlockReason(int $currentUsage, int $effectiveValue, string $source, array $planProfile, ?string $rationale): string
    {
        $prefix = $source === 'workspace_override'
            ? 'This workspace override currently allows'
            : sprintf('The %s plan profile currently allows', $planProfile['label']);

        $message = sprintf(
            '%s %d active managed tenant%s, and this workspace already has %d active managed tenant%s.',
            $prefix,
            $effectiveValue,
            $effectiveValue === 1 ? '' : 's',
            $currentUsage,
            $currentUsage === 1 ? '' : 's',
        );

        if ($source === 'workspace_override' && $rationale !== null) {
            $message .= ' Reason: '.$rationale;
        }

        return $message;
    }

    /**
     * @param  array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool}  $planProfile
     */
    private function reviewPackGenerationBlockReason(string $source, array $planProfile, ?string $rationale): string
    {
        $message = $source === 'workspace_override'
            ? 'Review pack generation is disabled by workspace override.'
            : sprintf('Review pack generation is disabled by the %s plan profile.', $planProfile['label']);

        if ($source === 'workspace_override' && $rationale !== null) {
            $message .= ' Reason: '.$rationale;
        }

        return $message;
    }
}