<?php

declare(strict_types=1);

namespace App\Support\PortfolioCompare;

use App\Models\Tenant;
use InvalidArgumentException;

final readonly class CrossTenantCompareSelection
{
    public Tenant $sourceTenant;

    public Tenant $targetTenant;

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

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

        if ((int) $this->sourceTenant->getKey() === (int) $this->targetTenant->getKey()) {
            throw new InvalidArgumentException('Source and target tenants must differ.');
        }

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

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

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

    public function sourceTenantId(): int
    {
        return (int) $this->sourceTenant->getKey();
    }

    public function targetTenantId(): int
    {
        return (int) $this->targetTenant->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;
    }
}
