<?php

namespace WPSN\Modules\ImportExport;

defined('ABSPATH') || exit;

/**
 * Builds compact import diff copy for Import Assist cards and Tasks Hub rows.
 */
final class ImportAssistDiffPresenter
{
    private ImportAssistWarningGrouper $warningGrouper;

    public function __construct(?ImportAssistWarningGrouper $warningGrouper = null)
    {
        $this->warningGrouper = $warningGrouper ?? new ImportAssistWarningGrouper();
    }

    /**
     * @param array<string,mixed> $entry
     * @return array<string,mixed>
     */
    public function build(array $entry): array
    {
        $summary = isset($entry['summary']) && is_array($entry['summary']) ? $entry['summary'] : [];
        $items = isset($entry['items']) && is_array($entry['items']) ? $entry['items'] : [];

        $found = max(0, (int) ($summary['found'] ?? 0));
        $applied = max(0, (int) ($summary['applied'] ?? 0));
        $manual = max(0, (int) ($summary['manual'] ?? 0));
        $skipped = max(0, (int) ($summary['skipped'] ?? 0));
        $notMapped = max(0, (int) ($summary['not_mapped'] ?? 0));
        $warnings = max(0, (int) ($summary['warnings'] ?? 0));

        $compact = sprintf(
            __('Found %1$d → Applied %2$d → Manual %3$d', 'wp-seo-next'),
            $found,
            $applied,
            $manual
        );

        $suffix = [];
        if ($skipped > 0) {
            $suffix[] = sprintf(__('Skipped %d', 'wp-seo-next'), $skipped);
        }
        if ($notMapped > 0) {
            $suffix[] = sprintf(__('Not mapped %d', 'wp-seo-next'), $notMapped);
        }
        if ($warnings > 0) {
            $suffix[] = sprintf(__('Warnings %d', 'wp-seo-next'), $warnings);
        }
        if (!empty($suffix)) {
            $compact .= ' · ' . implode(' · ', $suffix);
        }

        $appliedItems = $this->normalizeStringList($items['applied'] ?? []);
        $manualItems = $this->normalizeStringList($items['manual_actions'] ?? []);
        $notMappedItems = $this->normalizeStringList($items['not_mapped'] ?? []);
        $warningItems = $this->normalizeStringList($items['warnings'] ?? []);
        $sourceFoundItems = $this->normalizeStringList($items['source_found'] ?? []);
        $warningGroups = $this->warningGrouper->group($entry);
        $warningSummary = $this->warningGrouper->summary($warningGroups);

        $focusParts = [];
        if (!empty($appliedItems)) {
            $focusParts[] = sprintf(
                __('Applied: %s', 'wp-seo-next'),
                $this->sampleList($appliedItems, 2)
            );
        }
        if (!empty($manualItems)) {
            $focusParts[] = sprintf(
                __('Manual: %s', 'wp-seo-next'),
                $this->sampleList($manualItems, 2)
            );
        } elseif (!empty($notMappedItems)) {
            $focusParts[] = sprintf(
                __('Gaps: %s', 'wp-seo-next'),
                $this->sampleList($notMappedItems, 2)
            );
        }
        if ($warningSummary !== '') {
            $focusParts[] = sprintf(
                __('Warnings: %s', 'wp-seo-next'),
                $warningSummary
            );
        } elseif (!empty($warningItems)) {
            $focusParts[] = sprintf(
                __('Warnings: %s', 'wp-seo-next'),
                $this->sampleList($warningItems, 1)
            );
        }

        return [
            'compact' => $compact,
            'focus' => implode(' · ', array_filter($focusParts, static function ($value): bool {
                return is_string($value) && trim($value) !== '';
            })),
            'counts' => [
                'found' => $found,
                'applied' => $applied,
                'manual' => $manual,
                'skipped' => $skipped,
                'not_mapped' => $notMapped,
                'warnings' => $warnings,
            ],
            'samples' => [
                'source_found' => array_slice($sourceFoundItems, 0, 3),
                'applied' => array_slice($appliedItems, 0, 3),
                'manual_actions' => array_slice($manualItems, 0, 3),
                'not_mapped' => array_slice($notMappedItems, 0, 3),
                'warnings' => array_slice($warningItems, 0, 2),
            ],
            'warning_summary' => $warningSummary,
            'warning_groups' => $warningGroups,
        ];
    }

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

        $out = [];
        foreach ($items as $item) {
            if (!is_scalar($item)) {
                continue;
            }
            $value = trim((string) $item);
            if ($value === '') {
                continue;
            }
            $out[] = $value;
        }

        return array_values(array_unique($out));
    }

    /**
     * @param array<int,string> $items
     */
    private function sampleList(array $items, int $limit): string
    {
        $limit = max(1, $limit);
        $items = array_slice(array_values($items), 0, $limit + 1);
        $overflow = count($items) > $limit;
        if ($overflow) {
            $items = array_slice($items, 0, $limit);
        }

        $text = implode(' · ', $items);
        if ($overflow) {
            $text .= ' · …';
        }

        return $text;
    }
}
