<?php

declare(strict_types=1);

namespace SeoScope\Services;

/**
 * Builds LLM payload for Pages report SEO AI Assistant.
 */
final class SeoAiPagesPayloadService
{
    public const SCHEMA_VERSION = 1;

    public const MAX_PAGES = 25;

    /**
     * @param list<array<string, mixed>> $rows Top landing pages for current filters/sort
     * @param array{
     *   preset:string,
     *   device:string,
     *   country:string,
     *   range_start:string,
     *   range_end:string,
     *   search_q:string,
     *   show:string,
     *   track_category_filter:?int,
     *   compare_enabled:bool,
     *   prev_range_start:?string,
     *   prev_range_end:?string,
     *   sort:string,
     *   dir:string,
     *   total_pages:int,
     * } $meta
     *
     * @return array{ready:bool, payload:array<string,mixed>}
     */
    public function build(array $rows, array $meta): array
    {
        $total = max(0, (int) ($meta['total_pages'] ?? 0));
        $normalized = [];
        foreach ($rows as $row) {
            if (!is_array($row)) {
                continue;
            }
            $page = trim((string) ($row['page'] ?? ''));
            if ($page === '') {
                continue;
            }
            $item = [
                'page' => $page,
                'clicks' => max(0, (int) ($row['clicks'] ?? 0)),
                'impressions' => max(0, (int) ($row['impressions'] ?? 0)),
                'ctr' => round((float) ($row['ctr'] ?? 0), 6),
                'position' => round((float) ($row['position'] ?? 0), 4),
            ];
            if (isset($row['prev']) && is_array($row['prev'])) {
                $prev = $row['prev'];
                $item['previous_period'] = [
                    'clicks' => max(0, (int) ($prev['clicks'] ?? 0)),
                    'impressions' => max(0, (int) ($prev['impressions'] ?? 0)),
                    'ctr' => round((float) ($prev['ctr'] ?? 0), 6),
                    'position' => round((float) ($prev['position'] ?? 0), 4),
                ];
            }
            $normalized[] = $item;
            if (count($normalized) >= self::MAX_PAGES) {
                break;
            }
        }

        $ready = $total > 0 && $normalized !== [];

        $sumImpr = 0;
        $sumClicks = 0;
        $sumPosWeighted = 0.0;
        foreach ($normalized as $p) {
            $sumImpr += (int) $p['impressions'];
            $sumClicks += (int) $p['clicks'];
            $sumPosWeighted += (float) $p['position'] * (int) $p['impressions'];
        }

        $show = (string) ($meta['show'] ?? 'all');
        if (!in_array($show, ['all', 'tracked'], true)) {
            $show = 'all';
        }

        $payload = [
            'schema_version' => self::SCHEMA_VERSION,
            'context' => 'pages_report',
            'filters' => [
                'preset' => (string) ($meta['preset'] ?? 'last_28_days'),
                'device' => (string) ($meta['device'] ?? 'all'),
                'country' => (string) ($meta['country'] ?? 'all'),
                'show' => $show,
                'search_q' => trim((string) ($meta['search_q'] ?? '')),
                'track_category_filter' => $meta['track_category_filter'] ?? null,
            ],
            'period' => [
                'start' => (string) ($meta['range_start'] ?? ''),
                'end' => (string) ($meta['range_end'] ?? ''),
            ],
            'compare_enabled' => !empty($meta['compare_enabled']),
            'previous_period' => !empty($meta['compare_enabled']) ? [
                'start' => (string) ($meta['prev_range_start'] ?? ''),
                'end' => (string) ($meta['prev_range_end'] ?? ''),
            ] : null,
            'sort' => [
                'column' => (string) ($meta['sort'] ?? 'clicks'),
                'direction' => strtoupper((string) ($meta['dir'] ?? 'DESC')) === 'ASC' ? 'ASC' : 'DESC',
            ],
            'portfolio' => [
                'total_pages' => $total,
                'rows_sent_to_model' => count($normalized),
                'sum_impressions_top' => $sumImpr,
                'sum_clicks_top' => $sumClicks,
                'weighted_avg_position_top' => $sumImpr > 0 ? round($sumPosWeighted / $sumImpr, 4) : null,
            ],
            'pages' => $normalized,
            'model_notes' => [
                'pages_meaning' => 'Top landing page URLs for the property in the selected period, respecting report filters (All vs Tracked, search box, category). Rows follow the table sort order.',
                'constraints' => 'Interpret only listed page URLs and portfolio fields. Do not invent search queries (not provided).',
            ],
        ];

        return ['ready' => $ready, 'payload' => $payload];
    }
}
