<?php

declare(strict_types=1);

namespace App\Support\CustomerHealth;

use InvalidArgumentException;

final class CustomerHealthDimensionCatalog
{
    public const string ONBOARDING_READINESS = 'onboarding_readiness';

    public const string PROVIDER_CONNECTION_HEALTH = 'provider_connection_health';

    public const string OPERATIONAL_STABILITY = 'operational_stability';

    public const string GOVERNANCE_PRESSURE = 'governance_pressure';

    public const string REVIEW_PACK_READINESS = 'review_pack_readiness';

    public const string ENGAGEMENT_FRESHNESS = 'engagement_freshness';

    /**
     * @var array<string, array{label: string, windowed: bool}>
     */
    private const DEFINITIONS = [
        self::ONBOARDING_READINESS => [
            'label' => 'Onboarding readiness',
            'windowed' => false,
        ],
        self::PROVIDER_CONNECTION_HEALTH => [
            'label' => 'Provider connection health',
            'windowed' => false,
        ],
        self::OPERATIONAL_STABILITY => [
            'label' => 'Operational stability',
            'windowed' => true,
        ],
        self::GOVERNANCE_PRESSURE => [
            'label' => 'Governance pressure',
            'windowed' => false,
        ],
        self::REVIEW_PACK_READINESS => [
            'label' => 'Review-pack readiness',
            'windowed' => true,
        ],
        self::ENGAGEMENT_FRESHNESS => [
            'label' => 'Engagement freshness',
            'windowed' => true,
        ],
    ];

    /**
     * @return list<string>
     */
    public function names(): array
    {
        return array_keys(self::DEFINITIONS);
    }

    /**
     * @return array{label: string, windowed: bool}
     */
    public function definition(string $dimension): array
    {
        $definition = self::DEFINITIONS[$dimension] ?? null;

        if (! is_array($definition)) {
            throw new InvalidArgumentException("Unknown customer health dimension [{$dimension}].");
        }

        return $definition;
    }

    public function label(string $dimension): string
    {
        return $this->definition($dimension)['label'];
    }

    public function isWindowed(string $dimension): bool
    {
        return $this->definition($dimension)['windowed'];
    }

    /**
     * @return array<string, string>
     */
    public function visibleDimensions(): array
    {
        $dimensions = [];

        foreach ($this->names() as $dimension) {
            $dimensions[$dimension] = $this->label($dimension);
        }

        return $dimensions;
    }

    /**
     * @param  list<string>  $levels
     */
    public function resolveOverallLevel(array $levels): string
    {
        foreach (['critical', 'warn', 'unknown'] as $level) {
            if (in_array($level, $levels, true)) {
                return $level;
            }
        }

        return 'ok';
    }
}