<?php

declare(strict_types=1);

namespace SeoScope\Services;

/**
 * Builds LLM payload for Quick Win → IQQI tab (top opportunities + portfolio summary).
 */
final class SeoAiIqqiPayloadService
{
    public const SCHEMA_VERSION = 1;

    public const MAX_OPPORTUNITIES = 25;

    /**
     * @param list<array<string, mixed>> $rows From {@see \SeoScope\Repositories\GscQuickWinRepository::listIqqi()}
     * @param array{
     *   preset:string,
     *   device:string,
     *   country:string,
     *   range_start:string,
     *   range_end:string,
     *   iqqi_min_impr:int,
     *   iqqi_pos_min:float,
     *   iqqi_pos_max:float,
     *   total_opportunities:int,
     * } $meta
     *
     * @return array{ready:bool, payload:array<string,mixed>}
     */
    public function build(array $rows, array $meta): array
    {
        $total = max(0, (int) ($meta['total_opportunities'] ?? 0));
        $normalized = [];
        foreach ($rows as $row) {
            if (!is_array($row)) {
                continue;
            }
            $q = trim((string) ($row['query'] ?? ''));
            if ($q === '') {
                continue;
            }
            $impr = max(0, (int) ($row['impressions'] ?? 0));
            $clicks = max(0, (int) ($row['clicks'] ?? 0));
            $ctr = (float) ($row['ctr'] ?? 0);
            $pos = (float) ($row['position'] ?? 0);
            $ctrExpected = (float) ($row['ctr_expected'] ?? 0);
            $ctrGap = (float) ($row['ctr_gap'] ?? 0);
            $score = (float) ($row['score'] ?? 0);
            $normalized[] = [
                'query' => $q,
                'impressions' => $impr,
                'clicks' => $clicks,
                'ctr' => round($ctr, 6),
                'position' => round($pos, 4),
                'ctr_expected' => round($ctrExpected, 6),
                'ctr_gap' => round($ctrGap, 6),
                'score' => round($score, 4),
            ];
            if (count($normalized) >= self::MAX_OPPORTUNITIES) {
                break;
            }
        }

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

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

        $payload = [
            'schema_version' => self::SCHEMA_VERSION,
            'context' => 'quick_win_iqqi',
            'filters' => [
                'preset' => (string) ($meta['preset'] ?? 'last_28_days'),
                'device' => (string) ($meta['device'] ?? 'all'),
                'country' => (string) ($meta['country'] ?? 'all'),
            ],
            'period' => [
                'start' => (string) ($meta['range_start'] ?? ''),
                'end' => (string) ($meta['range_end'] ?? ''),
            ],
            'thresholds' => [
                'min_impressions' => (int) ($meta['iqqi_min_impr'] ?? 0),
                'position_min' => (float) ($meta['iqqi_pos_min'] ?? 0),
                'position_max' => (float) ($meta['iqqi_pos_max'] ?? 0),
            ],
            'portfolio' => [
                'total_opportunities' => $total,
                'rows_sent_to_model' => $n,
                'sum_impressions_top' => $sumImpr,
                'sum_clicks_top' => $sumClicks,
                'weighted_avg_position_top' => $sumImpr > 0 ? round($sumPosWeighted / $sumImpr, 4) : null,
                'avg_ctr_gap_top' => $n > 0 ? round($sumGap / $n, 6) : null,
            ],
            'opportunities' => $normalized,
            'model_notes' => [
                'iqqi_meaning' => 'IQQI score ≈ impressions × (10 − position) × CTR gap for queries near top with CTR below benchmark.',
                'constraints' => 'Interpret only listed queries and portfolio fields. Do not discuss landing URLs (not provided).',
            ],
        ];

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