<?php

declare(strict_types=1);

namespace App\Support\Ui\EnterpriseDetail;

final class EnterpriseDetailSectionFactory
{
    /**
     * @param  array{label: string, color?: string, icon?: ?string, iconColor?: ?string}|null  $badge
     * @param  'default'|'danger'|'success'|'warning'|null  $tone  Optional color tone for the card border/value
     * @param  bool  $mono  Whether the value should be rendered in monospace font (e.g. hashes, IDs)
     * @return array{label: string, value: string, hint?: ?string, badge?: ?array{label: string, color?: string, icon?: ?string, iconColor?: ?string}, tone?: string, mono?: bool}
     */
    public function keyFact(string $label, mixed $value, ?string $hint = null, ?array $badge = null, ?string $tone = null, bool $mono = false): array
    {
        $displayValue = match (true) {
            is_bool($value) => $value ? 'Yes' : 'No',
            $value === null => '—',
            is_scalar($value) => trim((string) $value) !== '' ? (string) $value : '—',
            default => '—',
        };

        return array_filter([
            'label' => $label,
            'value' => $displayValue,
            'hint' => $hint,
            'badge' => $badge,
            'tone' => $tone,
            'mono' => $mono ?: null,
        ], static fn (mixed $item): bool => $item !== null);
    }

    /**
     * @return array{label: string, color?: string, icon?: ?string, iconColor?: ?string}
     */
    public function statusBadge(string $label, string $color = 'gray', ?string $icon = null, ?string $iconColor = null): array
    {
        return array_filter([
            'label' => $label,
            'color' => $color,
            'icon' => $icon,
            'iconColor' => $iconColor,
        ], static fn (mixed $item): bool => $item !== null);
    }

    /**
     * @return array{title: string, description?: ?string, icon?: ?string}
     */
    public function emptyState(string $title, ?string $description = null, ?string $icon = null): array
    {
        return array_filter([
            'title' => $title,
            'description' => $description,
            'icon' => $icon,
        ], static fn (mixed $item): bool => $item !== null);
    }

    /**
     * @param  list<array<string, mixed>>  $facts
     * @param  array{
     *      label?: string,
     *      text: string,
     *      source: string,
     *      secondaryGuidance?: list<array{label: string, text: string, source: string}>
     * }  $primaryNextStep
     * @param  array{
     *      summaryLine?: ?string,
     *      primaryFacts?: list<array<string, mixed>>,
     *      diagnosticFacts?: list<array<string, mixed>>
     * }|null  $compactCounts
     * @return array{
     *      title: string,
     *      description?: ?string,
     *      facts: list<array<string, mixed>>,
     *      primaryNextStep: array{
     *          label?: string,
     *          text: string,
     *          source: string,
     *          secondaryGuidance?: list<array{label: string, text: string, source: string}>
     *      },
     *      compactCounts?: array{
     *          summaryLine?: ?string,
     *          primaryFacts?: list<array<string, mixed>>,
     *          diagnosticFacts?: list<array<string, mixed>>
     *      },
     *      attentionNote?: ?string
     * }
     */
    public function decisionZone(
        array $facts,
        array $primaryNextStep,
        ?string $description = null,
        ?array $compactCounts = null,
        ?string $attentionNote = null,
        string $title = 'Decision',
    ): array {
        return array_filter([
            'title' => $title,
            'description' => $description,
            'facts' => array_values($facts),
            'primaryNextStep' => $primaryNextStep,
            'compactCounts' => $compactCounts,
            'attentionNote' => $attentionNote,
        ], static fn (mixed $item): bool => $item !== null);
    }

    /**
     * @param  list<array{label: string, text: string, source: string}>  $secondaryGuidance
     * @return array{
     *      label: string,
     *      text: string,
     *      source: string,
     *      secondaryGuidance: list<array{label: string, text: string, source: string}>
     * }
     */
    public function primaryNextStep(string $text, string $source, array $secondaryGuidance = [], string $label = 'Primary next step'): array
    {
        return [
            'label' => $label,
            'text' => $text,
            'source' => $source,
            'secondaryGuidance' => array_values($secondaryGuidance),
        ];
    }

    /**
     * @param  list<array<string, mixed>>  $primaryFacts
     * @param  list<array<string, mixed>>  $diagnosticFacts
     * @return array{
     *      summaryLine?: ?string,
     *      primaryFacts: list<array<string, mixed>>,
     *      diagnosticFacts: list<array<string, mixed>>
     * }
     */
    public function countPresentation(?string $summaryLine = null, array $primaryFacts = [], array $diagnosticFacts = []): array
    {
        return [
            'summaryLine' => $summaryLine,
            'primaryFacts' => array_values($primaryFacts),
            'diagnosticFacts' => array_values($diagnosticFacts),
        ];
    }

    /**
     * @param  list<array<string, mixed>>  $items
     */
    public function factsSection(
        string $id,
        string $kind,
        string $title,
        array $items,
        ?array $emptyState = null,
        ?PageActionData $action = null,
        ?string $description = null,
        bool $visible = true,
        bool $collapsible = false,
        bool $collapsed = false,
    ): DetailSectionData {
        return new DetailSectionData(
            id: $id,
            kind: $kind,
            title: $title,
            items: $items,
            emptyState: $emptyState,
            action: $action,
            visible: $visible,
            description: $description,
            collapsible: $collapsible,
            collapsed: $collapsed,
        );
    }

    /**
     * @param  array<string, mixed>  $viewData
     */
    public function viewSection(
        string $id,
        string $kind,
        string $title,
        string $view,
        array $viewData = [],
        ?array $emptyState = null,
        ?PageActionData $action = null,
        ?string $description = null,
        bool $visible = true,
        bool $collapsible = false,
        bool $collapsed = false,
    ): DetailSectionData {
        return new DetailSectionData(
            id: $id,
            kind: $kind,
            title: $title,
            emptyState: $emptyState,
            action: $action,
            visible: $visible,
            description: $description,
            view: $view,
            viewData: $viewData,
            collapsible: $collapsible,
            collapsed: $collapsed,
        );
    }

    /**
     * @param  list<array<string, mixed>>  $items
     */
    public function supportingFactsCard(
        string $kind,
        string $title,
        array $items,
        ?PageActionData $action = null,
        ?string $description = null,
        bool $visible = true,
        ?array $emptyState = null,
    ): SupportingCardData {
        return new SupportingCardData(
            kind: $kind,
            title: $title,
            items: $items,
            visible: $visible,
            action: $action,
            description: $description,
            emptyState: $emptyState,
        );
    }

    /**
     * @param  array<string, mixed>  $viewData
     */
    public function supportingViewCard(
        string $kind,
        string $title,
        string $view,
        array $viewData = [],
        ?PageActionData $action = null,
        ?string $description = null,
        bool $visible = true,
        ?array $emptyState = null,
    ): SupportingCardData {
        return new SupportingCardData(
            kind: $kind,
            title: $title,
            visible: $visible,
            action: $action,
            description: $description,
            view: $view,
            viewData: $viewData,
            emptyState: $emptyState,
        );
    }

    /**
     * @param  list<array<string, mixed>>  $entries
     * @param  array<string, mixed>  $viewData
     */
    public function technicalDetail(
        string $title,
        array $entries = [],
        ?string $description = null,
        ?string $view = null,
        array $viewData = [],
        ?array $emptyState = null,
        bool $visible = true,
        bool $collapsible = true,
        bool $collapsed = true,
        string $variant = 'technical',
    ): TechnicalDetailData {
        return new TechnicalDetailData(
            title: $title,
            entries: $entries,
            collapsible: $collapsible,
            collapsed: $collapsed,
            visible: $visible,
            description: $description,
            view: $view,
            viewData: $viewData,
            emptyState: $emptyState,
            variant: $variant,
        );
    }
}
