<?php

declare(strict_types=1);

namespace App\Support\Baselines;

use App\Models\OperationRun;
use App\Support\Governance\PlatformSubjectDescriptorNormalizer;
use Illuminate\Support\Str;

final class BaselineCompareEvidenceGapDetails
{
    public static function fromOperationRun(?OperationRun $run): array
    {
        if (! $run instanceof OperationRun || ! is_array($run->context)) {
            return self::empty();
        }

        return self::fromContext($run->context);
    }

    /**
     * @param  array<string, mixed>  $context
     */
    public static function fromContext(array $context): array
    {
        $baselineCompare = $context['baseline_compare'] ?? null;

        if (! is_array($baselineCompare)) {
            return self::empty();
        }

        return self::fromBaselineCompare($baselineCompare);
    }

    /**
     * @param  array<string, mixed>  $baselineCompare
     */
    public static function fromBaselineCompare(array $baselineCompare): array
    {
        $evidenceGaps = $baselineCompare['evidence_gaps'] ?? null;
        $evidenceGaps = is_array($evidenceGaps) ? $evidenceGaps : [];

        $byReason = self::normalizeCounts($evidenceGaps['by_reason'] ?? null);
        $normalizedSubjects = self::normalizeSubjects($evidenceGaps['subjects'] ?? null);

        foreach ($normalizedSubjects['subjects'] as $reasonCode => $subjects) {
            if (! array_key_exists($reasonCode, $byReason)) {
                $byReason[$reasonCode] = count($subjects);
            }
        }

        $count = self::normalizeTotalCount(
            $evidenceGaps['count'] ?? null,
            $byReason,
            $normalizedSubjects['subjects'],
        );
        $detailState = self::detailState($count, $normalizedSubjects);
        $buckets = [];

        foreach (self::orderedReasons($byReason, $normalizedSubjects['subjects']) as $reasonCode) {
            $rows = $detailState === 'structured_details_recorded'
                ? array_map(
                    static fn (array $subject): array => self::projectSubjectRow($subject),
                    $normalizedSubjects['subjects'][$reasonCode] ?? [],
                )
                : [];
            $reasonCount = $byReason[$reasonCode] ?? count($rows);

            if ($reasonCount <= 0 && $rows === []) {
                continue;
            }

            $recordedCount = count($rows);
            $structuralCount = count(array_filter(
                $rows,
                static fn (array $row): bool => (bool) ($row['structural'] ?? false),
            ));
            $transientCount = count(array_filter(
                $rows,
                static fn (array $row): bool => (bool) ($row['retryable'] ?? false),
            ));
            $operationalCount = max(0, $recordedCount - $structuralCount - $transientCount);

            $searchText = trim(implode(' ', array_filter([
                Str::lower($reasonCode),
                Str::lower(self::reasonLabel($reasonCode)),
                ...array_map(
                    static fn (array $row): string => (string) ($row['search_text'] ?? ''),
                    $rows,
                ),
            ])));

            $buckets[] = [
                'reason_code' => $reasonCode,
                'reason_label' => self::reasonLabel($reasonCode),
                'count' => $reasonCount,
                'recorded_count' => $recordedCount,
                'missing_detail_count' => max(0, $reasonCount - $recordedCount),
                'structural_count' => $structuralCount,
                'operational_count' => $operationalCount,
                'transient_count' => $transientCount,
                'detail_state' => self::bucketDetailState($detailState, $recordedCount),
                'search_text' => $searchText,
                'rows' => $rows,
            ];
        }

        $recordedSubjectsTotal = array_sum(array_map(
            static fn (array $bucket): int => (int) ($bucket['recorded_count'] ?? 0),
            $buckets,
        ));
        $structuralCount = array_sum(array_map(
            static fn (array $bucket): int => (int) ($bucket['structural_count'] ?? 0),
            $buckets,
        ));
        $operationalCount = array_sum(array_map(
            static fn (array $bucket): int => (int) ($bucket['operational_count'] ?? 0),
            $buckets,
        ));
        $transientCount = array_sum(array_map(
            static fn (array $bucket): int => (int) ($bucket['transient_count'] ?? 0),
            $buckets,
        ));
        $legacyMode = $detailState === 'legacy_broad_reason';

        return [
            'summary' => [
                'count' => $count,
                'by_reason' => $byReason,
                'detail_state' => $detailState,
                'recorded_subjects_total' => $recordedSubjectsTotal,
                'missing_detail_count' => max(0, $count - $recordedSubjectsTotal),
                'structural_count' => $structuralCount,
                'operational_count' => $operationalCount,
                'transient_count' => $transientCount,
                'legacy_mode' => $legacyMode,
                'requires_regeneration' => $legacyMode,
            ],
            'buckets' => $buckets,
        ];
    }

    /**
     * @param  array<string, mixed>  $baselineCompare
     * @return array<string, mixed>
     */
    public static function diagnosticsPayload(array $baselineCompare): array
    {
        return array_filter([
            'reason_code' => self::stringOrNull($baselineCompare['reason_code'] ?? null),
            'subjects_total' => self::intOrNull($baselineCompare['subjects_total'] ?? null),
            'resume_token' => self::stringOrNull($baselineCompare['resume_token'] ?? null),
            'fidelity' => self::stringOrNull($baselineCompare['fidelity'] ?? null),
            'strategy' => is_array($baselineCompare['strategy'] ?? null) ? $baselineCompare['strategy'] : null,
            'coverage' => is_array($baselineCompare['coverage'] ?? null) ? $baselineCompare['coverage'] : null,
            'evidence_capture' => is_array($baselineCompare['evidence_capture'] ?? null) ? $baselineCompare['evidence_capture'] : null,
            'evidence_gaps' => is_array($baselineCompare['evidence_gaps'] ?? null) ? $baselineCompare['evidence_gaps'] : null,
        ], static fn (mixed $value): bool => $value !== null && $value !== []);
    }

    public static function reasonLabel(string $reason): string
    {
        $reason = trim($reason);

        return match ($reason) {
            'ambiguous_match' => 'Ambiguous inventory match',
            'policy_record_missing' => 'Policy record missing',
            'inventory_record_missing' => 'Inventory record missing',
            'foundation_not_policy_backed' => 'Foundation not policy-backed',
            'invalid_subject' => 'Invalid subject',
            'duplicate_subject' => 'Duplicate subject',
            'capture_failed' => 'Evidence capture failed',
            'retryable_capture_failure' => 'Retryable evidence capture failure',
            'budget_exhausted' => 'Capture budget exhausted',
            'throttled' => 'Graph throttled',
            'invalid_support_config' => 'Invalid support configuration',
            'missing_current' => 'Missing current evidence',
            'missing_role_definition_baseline_version_reference' => 'Missing baseline role definition evidence',
            'missing_role_definition_current_version_reference' => 'Missing current role definition evidence',
            'missing_role_definition_compare_surface' => 'Missing role definition compare surface',
            'rollout_disabled' => 'Rollout disabled',
            'policy_not_found' => 'Legacy policy not found',
            default => Str::of($reason)->replace('_', ' ')->trim()->ucfirst()->toString(),
        };
    }

    public static function subjectClassLabel(string $subjectClass): string
    {
        return match (trim($subjectClass)) {
            SubjectClass::PolicyBacked->value => 'Policy-backed',
            SubjectClass::InventoryBacked->value => 'Inventory-backed',
            SubjectClass::FoundationBacked->value => 'Foundation-backed',
            default => 'Derived',
        };
    }

    public static function resolutionOutcomeLabel(string $resolutionOutcome): string
    {
        return match (trim($resolutionOutcome)) {
            ResolutionOutcome::ResolvedPolicy->value => 'Resolved policy',
            ResolutionOutcome::ResolvedInventory->value => 'Resolved inventory',
            ResolutionOutcome::PolicyRecordMissing->value => 'Policy record missing',
            ResolutionOutcome::InventoryRecordMissing->value => 'Inventory record missing',
            ResolutionOutcome::FoundationInventoryOnly->value => 'Foundation inventory only',
            ResolutionOutcome::InvalidSubject->value => 'Invalid subject',
            ResolutionOutcome::DuplicateSubject->value => 'Duplicate subject',
            ResolutionOutcome::AmbiguousMatch->value => 'Ambiguous match',
            ResolutionOutcome::InvalidSupportConfig->value => 'Invalid support configuration',
            ResolutionOutcome::Throttled->value => 'Graph throttled',
            ResolutionOutcome::CaptureFailed->value => 'Capture failed',
            ResolutionOutcome::RetryableCaptureFailure->value => 'Retryable capture failure',
            ResolutionOutcome::BudgetExhausted->value => 'Budget exhausted',
        };
    }

    public static function operatorActionCategoryLabel(string $operatorActionCategory): string
    {
        return match (trim($operatorActionCategory)) {
            OperatorActionCategory::Retry->value => 'Retry',
            OperatorActionCategory::RunInventorySync->value => 'Run inventory sync',
            OperatorActionCategory::RunPolicySyncOrBackup->value => 'Run policy sync or backup',
            OperatorActionCategory::ReviewPermissions->value => 'Review permissions',
            OperatorActionCategory::InspectSubjectMapping->value => 'Inspect subject mapping',
            OperatorActionCategory::ProductFollowUp->value => 'Product follow-up',
            default => 'No action',
        };
    }

    /**
     * @param  array<string, int>  $byReason
     * @return list<array{reason_code: string, reason_label: string, count: int}>
     */
    public static function topReasons(array $byReason, int $limit = 5): array
    {
        $normalized = self::normalizeCounts($byReason);
        arsort($normalized);

        return array_map(
            static fn (string $reason, int $count): array => [
                'reason_code' => $reason,
                'reason_label' => self::reasonLabel($reason),
                'count' => $count,
            ],
            array_slice(array_keys($normalized), 0, $limit),
            array_slice(array_values($normalized), 0, $limit),
        );
    }

    /**
     * @return array<string, list<string>>
     */
    public static function subjectReasonsFromOperationRun(?OperationRun $run): array
    {
        $details = self::fromOperationRun($run);
        $buckets = is_array($details['buckets'] ?? null) ? $details['buckets'] : [];
        $reasonMap = [];

        foreach ($buckets as $bucket) {
            if (! is_array($bucket)) {
                continue;
            }

            $reasonCode = self::stringOrNull($bucket['reason_code'] ?? null);

            if ($reasonCode === null) {
                continue;
            }

            $rows = is_array($bucket['rows'] ?? null) ? $bucket['rows'] : [];

            foreach ($rows as $row) {
                if (! is_array($row)) {
                    continue;
                }

                $policyType = self::stringOrNull($row['policy_type'] ?? null);
                $subjectKey = self::stringOrNull($row['subject_key'] ?? null);

                if ($policyType === null || $subjectKey === null) {
                    continue;
                }

                $compositeKey = self::subjectCompositeKey($policyType, $subjectKey);
                $reasonMap[$compositeKey] ??= [];
                $reasonMap[$compositeKey][] = $reasonCode;
            }
        }

        return array_map(
            static fn (array $reasons): array => array_values(array_unique(array_filter($reasons, 'is_string'))),
            $reasonMap,
        );
    }

    public static function subjectCompositeKey(string $policyType, string $subjectKey): string
    {
        return trim(mb_strtolower($policyType)).'|'.trim(mb_strtolower($subjectKey));
    }

    /**
     * @param  list<array<string, mixed>>  $buckets
     * @return list<array<string, mixed>>
     */
    public static function tableRows(array $buckets): array
    {
        $rows = [];

        foreach ($buckets as $bucket) {
            if (! is_array($bucket)) {
                continue;
            }

            $bucketRows = is_array($bucket['rows'] ?? null) ? $bucket['rows'] : [];

            foreach ($bucketRows as $row) {
                if (! is_array($row)) {
                    continue;
                }

                $reasonCode = self::stringOrNull($row['reason_code'] ?? null);
                $policyType = self::stringOrNull($row['policy_type'] ?? null);
                $subjectKey = self::stringOrNull($row['subject_key'] ?? null);
                $subjectClass = self::stringOrNull($row['subject_class'] ?? null);
                $resolutionOutcome = self::stringOrNull($row['resolution_outcome'] ?? null);
                $operatorActionCategory = self::stringOrNull($row['operator_action_category'] ?? null);

                if ($reasonCode === null || $policyType === null || $subjectKey === null || $subjectClass === null || $resolutionOutcome === null || $operatorActionCategory === null) {
                    continue;
                }

                $rows[] = [
                    '__id' => md5(implode('|', [$reasonCode, $policyType, $subjectKey, $resolutionOutcome])),
                    'reason_code' => $reasonCode,
                    'reason_label' => self::reasonLabel($reasonCode),
                    'policy_type' => $policyType,
                    'governed_subject_label' => (string) ($row['governed_subject_label'] ?? self::governedSubjectLabel($policyType)),
                    'governed_subject' => is_array($row['governed_subject'] ?? null) ? $row['governed_subject'] : self::subjectDescriptor($policyType),
                    'subject_key' => $subjectKey,
                    'subject_class' => $subjectClass,
                    'subject_class_label' => self::subjectClassLabel($subjectClass),
                    'resolution_path' => self::stringOrNull($row['resolution_path'] ?? null),
                    'resolution_outcome' => $resolutionOutcome,
                    'resolution_outcome_label' => self::resolutionOutcomeLabel($resolutionOutcome),
                    'operator_action_category' => $operatorActionCategory,
                    'operator_action_category_label' => self::operatorActionCategoryLabel($operatorActionCategory),
                    'structural' => (bool) ($row['structural'] ?? false),
                    'retryable' => (bool) ($row['retryable'] ?? false),
                    'search_text' => self::stringOrNull($row['search_text'] ?? null) ?? '',
                ];
            }
        }

        return $rows;
    }

    /**
     * @param  list<array<string, mixed>>  $rows
     * @return array<string, string>
     */
    public static function reasonFilterOptions(array $rows): array
    {
        return collect($rows)
            ->filter(fn (array $row): bool => filled($row['reason_code'] ?? null) && filled($row['reason_label'] ?? null))
            ->mapWithKeys(fn (array $row): array => [
                (string) $row['reason_code'] => (string) $row['reason_label'],
            ])
            ->sortBy(fn (string $label): string => Str::lower($label))
            ->all();
    }

    /**
     * @param  list<array<string, mixed>>  $rows
     * @return array<string, string>
     */
    public static function policyTypeFilterOptions(array $rows): array
    {
        return collect($rows)
            ->filter(fn (array $row): bool => filled($row['policy_type'] ?? null))
            ->mapWithKeys(fn (array $row): array => [
                (string) $row['policy_type'] => (string) ($row['governed_subject_label'] ?? $row['policy_type']),
            ])
            ->sortBy(fn (string $label): string => Str::lower($label))
            ->all();
    }

    /**
     * @param  list<array<string, mixed>>  $rows
     * @return array<string, string>
     */
    public static function subjectClassFilterOptions(array $rows): array
    {
        return collect($rows)
            ->filter(fn (array $row): bool => filled($row['subject_class'] ?? null))
            ->mapWithKeys(fn (array $row): array => [
                (string) $row['subject_class'] => (string) ($row['subject_class_label'] ?? self::subjectClassLabel((string) $row['subject_class'])),
            ])
            ->sortBy(fn (string $label): string => Str::lower($label))
            ->all();
    }

    /**
     * @param  list<array<string, mixed>>  $rows
     * @return array<string, string>
     */
    public static function actionCategoryFilterOptions(array $rows): array
    {
        return collect($rows)
            ->filter(fn (array $row): bool => filled($row['operator_action_category'] ?? null))
            ->mapWithKeys(fn (array $row): array => [
                (string) $row['operator_action_category'] => (string) ($row['operator_action_category_label'] ?? self::operatorActionCategoryLabel((string) $row['operator_action_category'])),
            ])
            ->sortBy(fn (string $label): string => Str::lower($label))
            ->all();
    }

    private static function empty(): array
    {
        return [
            'summary' => [
                'count' => 0,
                'by_reason' => [],
                'detail_state' => 'no_gaps',
                'recorded_subjects_total' => 0,
                'missing_detail_count' => 0,
                'structural_count' => 0,
                'operational_count' => 0,
                'transient_count' => 0,
                'legacy_mode' => false,
                'requires_regeneration' => false,
            ],
            'buckets' => [],
        ];
    }

    /**
     * @return array<string, int>
     */
    private static function normalizeCounts(mixed $value): array
    {
        if (! is_array($value)) {
            return [];
        }

        $normalized = [];

        foreach ($value as $reason => $count) {
            if (! is_string($reason) || trim($reason) === '' || ! is_numeric($count)) {
                continue;
            }

            $intCount = (int) $count;

            if ($intCount <= 0) {
                continue;
            }

            $normalized[trim($reason)] = $intCount;
        }

        arsort($normalized);

        return $normalized;
    }

    /**
     * @return array{
     *     subjects: array<string, list<array<string, mixed>>>,
     *     legacy_mode: bool
     * }
     */
    private static function normalizeSubjects(mixed $value): array
    {
        if ($value === null) {
            return [
                'subjects' => [],
                'legacy_mode' => false,
            ];
        }

        if (! is_array($value)) {
            return [
                'subjects' => [],
                'legacy_mode' => true,
            ];
        }

        if (! array_is_list($value)) {
            return [
                'subjects' => [],
                'legacy_mode' => true,
            ];
        }

        $subjects = [];

        foreach ($value as $item) {
            $normalized = self::normalizeStructuredSubject($item);

            if ($normalized === null) {
                return [
                    'subjects' => [],
                    'legacy_mode' => true,
                ];
            }

            $subjects[$normalized['reason_code']][] = $normalized;
        }

        foreach ($subjects as &$bucket) {
            usort($bucket, static function (array $left, array $right): int {
                return [$left['policy_type'], $left['subject_key'], $left['resolution_outcome']]
                    <=> [$right['policy_type'], $right['subject_key'], $right['resolution_outcome']];
            });
        }
        unset($bucket);

        ksort($subjects);

        return [
            'subjects' => $subjects,
            'legacy_mode' => false,
        ];
    }

    /**
     * @return array<string, mixed>|null
     */
    private static function normalizeStructuredSubject(mixed $value): ?array
    {
        if (! is_array($value)) {
            return null;
        }

        $policyType = self::stringOrNull($value['policy_type'] ?? null);
        $subjectKey = self::stringOrNull($value['subject_key'] ?? null);
        $subjectClass = self::stringOrNull($value['subject_class'] ?? null);
        $resolutionPath = self::stringOrNull($value['resolution_path'] ?? null);
        $resolutionOutcome = self::stringOrNull($value['resolution_outcome'] ?? null);
        $reasonCode = self::stringOrNull($value['reason_code'] ?? null);
        $operatorActionCategory = self::stringOrNull($value['operator_action_category'] ?? null);

        if ($policyType === null
            || $subjectKey === null
            || $subjectClass === null
            || $resolutionPath === null
            || $resolutionOutcome === null
            || $reasonCode === null
            || $operatorActionCategory === null) {
            return null;
        }

        if (! SubjectClass::tryFrom($subjectClass) instanceof SubjectClass
            || ! ResolutionPath::tryFrom($resolutionPath) instanceof ResolutionPath
            || ! ResolutionOutcome::tryFrom($resolutionOutcome) instanceof ResolutionOutcome
            || ! OperatorActionCategory::tryFrom($operatorActionCategory) instanceof OperatorActionCategory) {
            return null;
        }

        $sourceModelExpected = self::stringOrNull($value['source_model_expected'] ?? null);
        $sourceModelExpected = in_array($sourceModelExpected, ['policy', 'inventory', 'derived'], true) ? $sourceModelExpected : null;

        $sourceModelFound = self::stringOrNull($value['source_model_found'] ?? null);
        $sourceModelFound = in_array($sourceModelFound, ['policy', 'inventory', 'derived'], true) ? $sourceModelFound : null;

        return [
            'policy_type' => $policyType,
            'subject_external_id' => self::stringOrNull($value['subject_external_id'] ?? null),
            'subject_key' => $subjectKey,
            'subject_class' => $subjectClass,
            'resolution_path' => $resolutionPath,
            'resolution_outcome' => $resolutionOutcome,
            'reason_code' => $reasonCode,
            'operator_action_category' => $operatorActionCategory,
            'structural' => self::boolOrFalse($value['structural'] ?? null),
            'retryable' => self::boolOrFalse($value['retryable'] ?? null),
            'source_model_expected' => $sourceModelExpected,
            'source_model_found' => $sourceModelFound,
            'legacy_reason_code' => self::stringOrNull($value['legacy_reason_code'] ?? null),
        ];
    }

    /**
     * @param  array<string, int>  $byReason
     * @param  array<string, list<array<string, mixed>>>  $subjects
     * @return list<string>
     */
    private static function orderedReasons(array $byReason, array $subjects): array
    {
        $reasons = array_keys($byReason);

        foreach (array_keys($subjects) as $reason) {
            if (! in_array($reason, $reasons, true)) {
                $reasons[] = $reason;
            }
        }

        return $reasons;
    }

    /**
     * @param  array<string, int>  $byReason
     * @param  array<string, list<array<string, mixed>>>  $subjects
     */
    private static function normalizeTotalCount(mixed $count, array $byReason, array $subjects): int
    {
        if (is_numeric($count)) {
            $intCount = (int) $count;

            if ($intCount >= 0) {
                return $intCount;
            }
        }

        $byReasonCount = array_sum($byReason);

        if ($byReasonCount > 0) {
            return $byReasonCount;
        }

        return array_sum(array_map(
            static fn (array $rows): int => count($rows),
            $subjects,
        ));
    }

    /**
     * @param  array{subjects: array<string, list<array<string, mixed>>>, legacy_mode: bool}  $subjects
     */
    private static function detailState(int $count, array $subjects): string
    {
        if ($count <= 0) {
            return 'no_gaps';
        }

        if ($subjects['legacy_mode']) {
            return 'legacy_broad_reason';
        }

        return $subjects['subjects'] !== [] ? 'structured_details_recorded' : 'details_not_recorded';
    }

    private static function bucketDetailState(string $detailState, int $recordedCount): string
    {
        if ($detailState === 'legacy_broad_reason') {
            return 'legacy_broad_reason';
        }

        if ($recordedCount > 0) {
            return 'structured_details_recorded';
        }

        return 'details_not_recorded';
    }

    /**
     * @param  array<string, mixed>  $subject
     * @return array<string, mixed>
     */
    private static function projectSubjectRow(array $subject): array
    {
        $reasonCode = (string) $subject['reason_code'];
        $subjectClass = (string) $subject['subject_class'];
        $resolutionOutcome = (string) $subject['resolution_outcome'];
        $operatorActionCategory = (string) $subject['operator_action_category'];
        $policyType = (string) ($subject['policy_type'] ?? '');

        return array_merge($subject, [
            'reason_label' => self::reasonLabel($reasonCode),
            'governed_subject' => self::subjectDescriptor($policyType),
            'governed_subject_label' => self::governedSubjectLabel($policyType),
            'subject_class_label' => self::subjectClassLabel($subjectClass),
            'resolution_outcome_label' => self::resolutionOutcomeLabel($resolutionOutcome),
            'operator_action_category_label' => self::operatorActionCategoryLabel($operatorActionCategory),
            'search_text' => Str::lower(trim(implode(' ', array_filter([
                $reasonCode,
                self::reasonLabel($reasonCode),
                $policyType,
                self::governedSubjectLabel($policyType),
                (string) ($subject['subject_key'] ?? ''),
                $subjectClass,
                self::subjectClassLabel($subjectClass),
                (string) ($subject['resolution_path'] ?? ''),
                $resolutionOutcome,
                self::resolutionOutcomeLabel($resolutionOutcome),
                $operatorActionCategory,
                self::operatorActionCategoryLabel($operatorActionCategory),
                (string) ($subject['subject_external_id'] ?? ''),
            ])))),
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    private static function subjectDescriptor(string $policyType): array
    {
        static $cache = [];

        if (array_key_exists($policyType, $cache)) {
            return $cache[$policyType];
        }

        $result = app(PlatformSubjectDescriptorNormalizer::class)->fromArray([
            'policy_type' => $policyType,
        ], 'baseline_compare');

        return $cache[$policyType] = $result->descriptor->toArray();
    }

    private static function governedSubjectLabel(string $policyType): string
    {
        return (string) (data_get(self::subjectDescriptor($policyType), 'display_label') ?: $policyType);
    }

    private static function stringOrNull(mixed $value): ?string
    {
        if (! is_string($value)) {
            return null;
        }

        $trimmed = trim($value);

        return $trimmed !== '' ? $trimmed : null;
    }

    private static function intOrNull(mixed $value): ?int
    {
        return is_numeric($value) ? (int) $value : null;
    }

    private static function boolOrFalse(mixed $value): bool
    {
        if (is_bool($value)) {
            return $value;
        }

        if (is_int($value) || is_float($value) || is_string($value)) {
            return filter_var($value, FILTER_VALIDATE_BOOL);
        }

        return false;
    }
}
