<?php

declare(strict_types=1);

namespace App\Support\PortfolioCompare;

use App\Models\ManagedEnvironment;
use InvalidArgumentException;

final readonly class CrossEnvironmentCompareSelection
{
    public ManagedEnvironment $sourceEnvironment;

    public ManagedEnvironment $targetEnvironment;

    /**
     * @var list<string>
     */
    public array $policyTypes;

    /**
     * @param  list<string>  $policyTypes
     */
    public function __construct(
        ManagedEnvironment $sourceEnvironment,
        ManagedEnvironment $targetEnvironment,
        array $policyTypes = [],
    ) {
        $this->sourceEnvironment = $sourceEnvironment;
        $this->targetEnvironment = $targetEnvironment;

        if ((int) $this->sourceEnvironment->getKey() === (int) $this->targetEnvironment->getKey()) {
            throw new InvalidArgumentException('Source and target environments must differ.');
        }

        if ((int) $this->sourceEnvironment->workspace_id !== (int) $this->targetEnvironment->workspace_id) {
            throw new InvalidArgumentException('Source and target environments must belong to the same workspace.');
        }

        $this->policyTypes = $this->normalizePolicyTypes($policyTypes);
    }

    public function workspaceId(): int
    {
        return (int) $this->sourceEnvironment->workspace_id;
    }

    public function sourceEnvironmentId(): int
    {
        return (int) $this->sourceEnvironment->getKey();
    }

    public function targetEnvironmentId(): int
    {
        return (int) $this->targetEnvironment->getKey();
    }

    public function hasPolicyTypeFilter(): bool
    {
        return $this->policyTypes !== [];
    }

    /**
     * @param  list<string>  $policyTypes
     * @return list<string>
     */
    private function normalizePolicyTypes(array $policyTypes): array
    {
        $normalized = array_values(array_unique(array_filter(array_map(static function (mixed $policyType): ?string {
            if (! is_string($policyType)) {
                return null;
            }

            $normalizedPolicyType = trim($policyType);

            return $normalizedPolicyType !== '' ? $normalizedPolicyType : null;
        }, $policyTypes))));

        sort($normalized, SORT_STRING);

        return $normalized;
    }
}
