import logging
from typing import List, Optional, Tuple
from urllib.parse import quote

import requests
from open_webui.env import ENABLE_FORWARD_USER_INFO_HEADERS, REQUESTS_VERIFY
from open_webui.retrieval.models.base_reranker import BaseReranker
from open_webui.utils.headers import include_user_info_headers

log = logging.getLogger(__name__)


class ExternalReranker(BaseReranker):
    def __init__(
        self,
        api_key: str,
        url: str = 'http://localhost:8080/v1/rerank',
        model: str = 'reranker',
        timeout: Optional[int] = None,
    ):
        self.api_key = api_key
        self.url = url
        self.model = model
        self.timeout = timeout

    def predict(self, sentences: List[Tuple[str, str]], user=None) -> Optional[List[float]]:
        query = sentences[0][0]
        docs = [i[1] for i in sentences]

        payload = {
            'model': self.model,
            'query': query,
            'documents': docs,
            'top_n': len(docs),
        }

        try:
            log.info(f'ExternalReranker:predict:model {self.model}')
            log.info(f'ExternalReranker:predict:query {query}')

            headers = {
                'Content-Type': 'application/json',
                'Authorization': f'Bearer {self.api_key}',
            }

            if ENABLE_FORWARD_USER_INFO_HEADERS and user:
                headers = include_user_info_headers(headers, user)

            r = requests.post(
                f'{self.url}',
                headers=headers,
                json=payload,
                timeout=self.timeout,
                verify=REQUESTS_VERIFY,
            )

            r.raise_for_status()
            data = r.json()

            if 'results' in data:
                sorted_results = sorted(data['results'], key=lambda x: x['index'])
                return [result['relevance_score'] for result in sorted_results]
            else:
                log.error('No results found in external reranking response')
                return None

        except Exception as e:
            log.exception(f'Error in external reranking: {e}')
            return None
