<?php

declare(strict_types=1);

namespace SeoScope\Services;

/**
 * Extracts and validates the three SEO assistant text fields from raw model output.
 */
final class SeoAiStructuredInsightParser
{
    public const MAX_EXECUTIVE_SUMMARY = 560;

    public const MAX_SEO_INTERPRETATION = 2400;

    public const MAX_PRIORITY_RECOMMENDATION = 480;

    /**
     * @return array{ok:bool, executive_summary?:string, seo_interpretation?:string, priority_recommendation?:string, error?:string}
     */
    public static function parse(string $rawModelText): array
    {
        $rawModelText = trim($rawModelText);
        if ($rawModelText === '') {
            return ['ok' => false, 'error' => 'empty'];
        }

        $json = self::isolateJsonObject($rawModelText);
        try {
            $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
        } catch (\JsonException) {
            return ['ok' => false, 'error' => 'json'];
        }

        if (!is_array($data)) {
            return ['ok' => false, 'error' => 'shape'];
        }

        foreach (['executive_summary', 'seo_interpretation', 'priority_recommendation'] as $key) {
            if (!array_key_exists($key, $data)) {
                return ['ok' => false, 'error' => 'missing_' . $key];
            }
            if (!is_string($data[$key]) || trim($data[$key]) === '') {
                return ['ok' => false, 'error' => 'empty_' . $key];
            }
        }

        $summary = self::clampField((string) $data['executive_summary'], self::MAX_EXECUTIVE_SUMMARY);
        $interpretation = self::clampField((string) $data['seo_interpretation'], self::MAX_SEO_INTERPRETATION);
        $action = self::clampField((string) $data['priority_recommendation'], self::MAX_PRIORITY_RECOMMENDATION);

        if ($summary === '' || $interpretation === '' || $action === '') {
            return ['ok' => false, 'error' => 'blank_after_trim'];
        }

        return [
            'ok' => true,
            'executive_summary' => $summary,
            'seo_interpretation' => $interpretation,
            'priority_recommendation' => $action,
        ];
    }

    private static function isolateJsonObject(string $raw): string
    {
        $t = trim($raw);
        if (preg_match('/^```(?:json)?\s*([\s\S]*?)\s*```/iu', $t, $m)) {
            $t = trim((string) $m[1]);
        }

        if ($t !== '' && $t[0] === '{') {
            return $t;
        }

        $start = strpos($t, '{');
        $end = strrpos($t, '}');
        if ($start !== false && $end !== false && $end > $start) {
            return substr($t, $start, $end - $start + 1);
        }

        return $t;
    }

    private static function clampField(string $value, int $maxChars): string
    {
        $value = trim(preg_replace('/\s+/u', ' ', $value) ?? $value);
        if (mb_strlen($value) <= $maxChars) {
            return $value;
        }

        return rtrim(mb_substr($value, 0, max(1, $maxChars - 1))) . '…';
    }
}
