<?php
namespace EasyChat\Library\Support;








final class OfficialGroundingPolicy {
    public function normalize($value): array {
        $value = is_array($value) ? $value : [];
        $sources = [];
        $seen_ids = [];
        foreach (array_slice(is_array($value['sources'] ?? null) ? $value['sources'] : [], 0, 4) as $source) {
            if (!is_array($source)) continue;
            $source_id = (string)($source['id'] ?? '');
            if (preg_match('/^S[1-4]$/D', $source_id) !== 1 || isset($seen_ids[$source_id])) continue;
            $url = trim((string)($source['url'] ?? ''));
            $parts = parse_url($url);
            if (
                !$parts
                || strtolower((string)($parts['scheme'] ?? '')) !== 'https'
                || strtolower((string)($parts['host'] ?? '')) !== 'docs.easychat24.ru'
                || isset($parts['user'])
                || isset($parts['pass'])
                || (isset($parts['port']) && (int)$parts['port'] !== 443)
                || isset($parts['query'])
            ) {
                continue;
            }
            $sources[] = [
                'id' => $source_id,
                'title' => $this->limit((string)($source['title'] ?? 'Документация EasyChat'), 160),
                'url' => $url,
                'section' => $this->limit((string)($source['section'] ?? ''), 160),
                'locale' => (string)($source['locale'] ?? '') === 'en' ? 'en' : 'ru',
            ];
            $seen_ids[$source_id] = true;
        }
        $status = in_array((string)($value['status'] ?? ''), ['grounded', 'clarify', 'handoff', 'unavailable'], true)
            ? (string)$value['status']
            : 'unavailable';
        return [
            'status' => $status,
            'confidence' => max(0, min(1, (float)($value['confidence'] ?? 0))),
            'sources' => $status === 'grounded' || $status === 'clarify' ? $sources : [],
            'clarification' => $this->limit((string)($value['clarification'] ?? ''), 360),
            'reason' => preg_replace('/[^a-z0-9_:-]/i', '', (string)($value['reason'] ?? '')),
        ];
    }

    public function answer(string $model_answer, array $grounding, string $locale): string {
        return $this->finalize($model_answer, $grounding, $locale)['answer'];
    }

     
    public function finalize(string $model_answer, array $grounding, string $locale): array {
        $locale = $locale === 'en' ? 'en' : 'ru';
        if (($grounding['status'] ?? '') === 'clarify') {
            $clarification = trim((string)($grounding['clarification'] ?? ''));
            return ['answer' => $clarification !== '' ? $clarification : ($locale === 'en'
                ? 'What exactly would you like to configure, or what is not working?'
                : 'Что именно вы хотите настроить или что сейчас не работает?'), 'grounding' => $grounding];
        }
        if (($grounding['status'] ?? '') === 'grounded' && empty($grounding['sources'])) {
            $grounding['status'] = 'handoff';
            $grounding['reason'] = 'verified_sources_missing';
            return ['answer' => $this->unverifiedAnswer($locale), 'grounding' => $grounding];
        }
        if (($grounding['status'] ?? '') !== 'grounded') {
            return ['answer' => $this->unverifiedAnswer($locale), 'grounding' => $grounding];
        }
        $allowed = [];
        foreach ($grounding['sources'] as $source) {
            if (preg_match('/^S[1-4]$/D', (string)($source['id'] ?? ''))) {
                $allowed[(string)$source['id']] = true;
            }
        }
        $has_valid_citation = false;
        $has_model_url = preg_match('/https?:\/\//i', $model_answer) === 1;
        $answer = preg_replace_callback('/\[(S\d{1,2})\]/', function ($match) use ($allowed, &$has_valid_citation) {
            if (isset($allowed[$match[1]])) {
                $has_valid_citation = true;
                return '[' . $match[1] . ']';
            }
            return '';
        }, $model_answer);
         
         
        $answer = preg_replace('/\[([^\]]+)\]\(https?:\/\/[^)\s]+\)/i', '$1', (string)$answer);
        $answer = preg_replace('/https?:\/\/[^\s<>()]+/i', '', (string)$answer);
        $answer = trim($this->limit((string)$answer, 8000));
        if ($has_model_url && !$has_valid_citation) {
            $grounding['status'] = 'handoff';
            $grounding['reason'] = 'model_url_not_allowed';
            $grounding['sources'] = [];
            return ['answer' => $locale === 'en'
                ? 'I could not produce an answer with verified EasyChat documentation links. Please try again or contact support.'
                : 'Не удалось сформировать ответ с проверенными ссылками на документацию EasyChat. Повторите вопрос или обратитесь в поддержку.', 'grounding' => $grounding];
        }
        if ($answer === '') {
            $grounding['status'] = 'handoff';
            $grounding['reason'] = 'grounded_answer_empty';
            $grounding['sources'] = [];
            return ['answer' => $locale === 'en'
                ? 'I could not produce an answer from the verified EasyChat documentation. Please try again or contact support.'
                : 'Не удалось сформировать ответ по проверенной документации EasyChat. Повторите вопрос или обратитесь в поддержку.', 'grounding' => $grounding];
        }
         
         
         
        if (!$has_valid_citation) {
            $grounding['reason'] = 'verified_sources_without_inline_marker';
            $grounding['confidence'] = min(0.85, (float)($grounding['confidence'] ?? 0));
        }
         
         
         
        $answer = \EasyChat\Library\MessageTextRenderer::withoutCitationMarkers($answer);
        return ['answer' => $answer, 'grounding' => $grounding];
    }

    private function unverifiedAnswer(string $locale): string {
        return $locale === 'en'
            ? 'I could not find a verified answer in the EasyChat documentation. Please contact support so we do not guess.'
            : 'В документации EasyChat не нашлось подтверждённого ответа. Лучше подключить поддержку, чтобы не угадывать.';
    }

    private function limit(string $value, int $length): string {
        $value = trim($value);
        return mb_substr($value, 0, $length, 'UTF-8');
    }
}
