<?php

declare(strict_types=1);

namespace App\Support\Filament;

use App\Models\AlertDelivery;
use App\Models\Finding;
use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeDomain;
use App\Support\Baselines\BaselineProfileStatus;
use App\Support\Inventory\InventoryPolicyTypeMeta;
use App\Support\OperationCatalog;
use App\Support\RestoreRunStatus;
use Illuminate\Support\Str;

final class FilterOptionCatalog
{
    /**
     * @return array<string, string>
     */
    public static function alertDeliveryStatuses(): array
    {
        return self::badgeOptions(BadgeDomain::AlertDeliveryStatus, [
            AlertDelivery::STATUS_QUEUED,
            AlertDelivery::STATUS_DEFERRED,
            AlertDelivery::STATUS_SENT,
            AlertDelivery::STATUS_FAILED,
            AlertDelivery::STATUS_SUPPRESSED,
            AlertDelivery::STATUS_CANCELED,
        ]);
    }

    /**
     * @return array<string, string>
     */
    public static function baselineProfileStatuses(): array
    {
        return collect(BaselineProfileStatus::cases())
            ->mapWithKeys(fn (BaselineProfileStatus $status): array => [
                $status->value => $status->label(),
            ])
            ->all();
    }

    /**
     * @return array<string, string>
     */
    public static function findingStatuses(bool $includeLegacyAcknowledged = true): array
    {
        $options = self::badgeOptions(BadgeDomain::FindingStatus, [
            Finding::STATUS_NEW,
            Finding::STATUS_TRIAGED,
            Finding::STATUS_IN_PROGRESS,
            Finding::STATUS_REOPENED,
            Finding::STATUS_RESOLVED,
            Finding::STATUS_CLOSED,
            Finding::STATUS_RISK_ACCEPTED,
        ]);

        if (! $includeLegacyAcknowledged) {
            return $options;
        }

        return [
            Finding::STATUS_NEW => $options[Finding::STATUS_NEW],
            Finding::STATUS_TRIAGED => $options[Finding::STATUS_TRIAGED],
            Finding::STATUS_ACKNOWLEDGED => self::legacyFindingAcknowledgedLabel(),
            Finding::STATUS_IN_PROGRESS => $options[Finding::STATUS_IN_PROGRESS],
            Finding::STATUS_REOPENED => $options[Finding::STATUS_REOPENED],
            Finding::STATUS_RESOLVED => $options[Finding::STATUS_RESOLVED],
            Finding::STATUS_CLOSED => $options[Finding::STATUS_CLOSED],
            Finding::STATUS_RISK_ACCEPTED => $options[Finding::STATUS_RISK_ACCEPTED],
        ];
    }

    /**
     * @param  iterable<mixed>|null  $types
     * @return array<string, string>
     */
    public static function operationTypes(?iterable $types = null): array
    {
        $values = collect($types ?? array_keys(OperationCatalog::labels()))
            ->filter(fn (mixed $type): bool => is_string($type) && trim($type) !== '')
            ->map(fn (string $type): string => trim($type))
            ->unique()
            ->sort()
            ->values();

        return $values
            ->mapWithKeys(fn (string $type): array => [$type => OperationCatalog::label($type)])
            ->sort()
            ->all();
    }

    /**
     * @param  iterable<mixed>|null  $types
     * @return array<string, string>
     */
    public static function policyTypes(?iterable $types = null): array
    {
        $values = $types === null
            ? collect(InventoryPolicyTypeMeta::all())->pluck('type')
            : collect($types);

        return $values
            ->filter(fn (mixed $type): bool => is_string($type) && trim($type) !== '')
            ->map(fn (string $type): string => trim($type))
            ->unique()
            ->mapWithKeys(function (string $type): array {
                $label = InventoryPolicyTypeMeta::metaFor($type)['label'] ?? null;

                return [$type => is_string($label) && $label !== '' ? $label : $type];
            })
            ->sort()
            ->all();
    }

    /**
     * @param  iterable<mixed>|null  $platforms
     * @return array<string, string>
     */
    public static function platforms(?iterable $platforms = null): array
    {
        $values = collect($platforms ?? [])
            ->merge(collect(InventoryPolicyTypeMeta::all())->pluck('platform'))
            ->merge(['all', 'android', 'ios', 'iOS', 'ipadOS', 'macOS', 'macos', 'mobile', 'windows', 'windows10', 'windows11'])
            ->filter(fn (mixed $platform): bool => is_string($platform) && trim($platform) !== '')
            ->map(fn (string $platform): string => trim($platform))
            ->unique()
            ->sort()
            ->values();

        return $values
            ->mapWithKeys(fn (string $platform): array => [$platform => self::platformLabel($platform)])
            ->sort()
            ->all();
    }

    /**
     * @return array<string, string>
     */
    public static function restoreRunOutcomes(): array
    {
        return [
            'succeeded' => 'Succeeded',
            'partial' => 'Partial',
            'failed' => 'Failed',
        ];
    }

    /**
     * @return array<string, string>
     */
    public static function restoreRunStatuses(): array
    {
        return self::badgeOptions(BadgeDomain::RestoreRunStatus, [
            RestoreRunStatus::Draft->value,
            RestoreRunStatus::Scoped->value,
            RestoreRunStatus::Checked->value,
            RestoreRunStatus::Previewed->value,
            RestoreRunStatus::Pending->value,
            RestoreRunStatus::Queued->value,
            RestoreRunStatus::Running->value,
            RestoreRunStatus::Completed->value,
            RestoreRunStatus::Partial->value,
            RestoreRunStatus::Failed->value,
            RestoreRunStatus::Cancelled->value,
            RestoreRunStatus::Aborted->value,
            RestoreRunStatus::CompletedWithErrors->value,
        ]);
    }

    /**
     * @param  array<int, string>  $values
     * @return array<string, string>
     */
    private static function badgeOptions(BadgeDomain $domain, array $values): array
    {
        return collect($values)
            ->mapWithKeys(fn (string $value): array => [$value => BadgeCatalog::spec($domain, $value)->label])
            ->all();
    }

    private static function legacyFindingAcknowledgedLabel(): string
    {
        return BadgeCatalog::spec(BadgeDomain::FindingStatus, Finding::STATUS_ACKNOWLEDGED)->label.' (legacy acknowledged)';
    }

    private static function platformLabel(string $platform): string
    {
        return match (Str::of($platform)
            ->trim()
            ->lower()
            ->replace(['_', '-'], '')
            ->toString()) {
            'windows', 'windows10', 'windows11' => 'Windows',
            'ios', 'ipados' => 'iOS',
            'macos' => 'macOS',
            default => InventoryPolicyTypeMeta::all()
                ? (string) \App\Support\Badges\TagBadgeCatalog::spec(\App\Support\Badges\TagBadgeDomain::Platform, $platform)->label
                : $platform,
        };
    }
}
