"""Exporters — where evaluation records get sent."""
from __future__ import annotations

import json
import sys
import urllib.request
import urllib.error
from abc import ABC, abstractmethod
from typing import Optional

from art._record import EvaluationRecord


# ANSI colour codes (disabled on non-TTY)
def _ansi(code: str) -> str:
    return code if sys.stdout.isatty() else ""


_RESET = _ansi("\033[0m")
_BOLD = _ansi("\033[1m")
_GREEN = _ansi("\033[32m")
_YELLOW = _ansi("\033[33m")
_RED = _ansi("\033[31m")
_CYAN = _ansi("\033[36m")
_DIM = _ansi("\033[2m")


def _score_color(score: float, inverted: bool = False) -> str:
    effective = (100 - score) if inverted else score
    if effective >= 80:
        return _GREEN
    if effective >= 60:
        return _YELLOW
    return _RED


class BaseExporter(ABC):
    @abstractmethod
    def export(self, record: EvaluationRecord) -> None: ...


class ConsoleExporter(BaseExporter):
    """Prints a coloured one-line summary (+ indicators if any) to stdout."""

    def export(self, record: EvaluationRecord) -> None:
        hal_color = _score_color(record.hallucination_score, inverted=True)
        conf_color = _score_color(record.confidence_score)

        trace_part = f" | trace:{record.trace_id[:8]}…[{record.step_index}]" if record.trace_id else ""

        cost = record.estimated_cost_usd
        cost_str = f"${cost:.6f}" if cost < 0.001 else f"${cost:.4f}"

        print(
            f"{_BOLD}[ART]{_RESET} "
            f"{_CYAN}{record.model}{_RESET} | "
            f"confidence:{conf_color}{record.confidence_score:.0f}{_RESET} "
            f"hallucination:{hal_color}{record.hallucination_score:.0f}{_RESET} "
            f"coherence:{record.coherence_score:.0f} "
            f"instruction:{record.instruction_following_score:.0f} | "
            f"{cost_str} | "
            f"{record.latency_ms}ms"
            f"{trace_part}"
        )
        for indicator in record.all_indicators:
            print(f"  {_YELLOW}⚠{_RESET} {_DIM}{indicator}{_RESET}")


class ARTCloudExporter(BaseExporter):
    """POSTs evaluation records to the ART backend. Never raises — failures are silent."""

    def __init__(self, base_url: str, api_key: Optional[str] = None) -> None:
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key

    def export(self, record: EvaluationRecord) -> None:
        payload = {
            "prompt": record.prompt,
            "response": record.response,
            "model": record.model,
            "pipeline_name": record.pipeline,
            "latency_ms": record.latency_ms,
            "prompt_tokens": record.prompt_tokens,
            "completion_tokens": record.completion_tokens,
            "source": record.source,
        }
        data = json.dumps(payload).encode()
        req = urllib.request.Request(
            f"{self.base_url}/proxy/evaluate",
            data=data,
            headers={"Content-Type": "application/json"},
            method="POST",
        )
        if self.api_key:
            req.add_header("Authorization", f"Bearer {self.api_key}")
        try:
            with urllib.request.urlopen(req, timeout=5):
                pass
        except Exception:
            pass  # Never let export failures affect the user's application


def make_exporter(config) -> BaseExporter:
    if config.export_to == "art_cloud":
        return ARTCloudExporter(config.art_cloud_url, config.api_key if hasattr(config, "api_key") else None)
    return ConsoleExporter()
