import datetime
import os
import random
import re
import time
import uuid

import requests

_ID_PATTERN = re.compile(r'^[a-zA-Z0-9_\-]{1,128}$')


def system_role(model: str) -> str:
    model = model.lower().strip()

    # o-series: o1, o3, o4-mini, etc. — require leading digit to avoid false positives
    if re.match(r"^o\d", model):
        return "developer"

    match = re.match(r"gpt-(\d+)", model)
    if match:
        try:
            if int(match.group(1)) >= 5:
                return "developer"
        except ValueError:
            pass

    return "system"

_TIMEOUT_CORTO = 30   # consultas y creación de batch
_TIMEOUT_LARGO = 120  # subida y descarga de archivos


def _validar_id(valor, nombre):
    if not _ID_PATTERN.match(str(valor)):
        raise ValueError(f"{nombre} contiene caracteres no permitidos: {valor!r}")


def formatear_linea_batch(fecha_edicto, id_fide, fuente, model, system_prompt, user_prompt, contenido, tokens=1000):
    base = f"{fuente}_{fecha_edicto}_{id_fide}_"
    extra = f"{int(time.time() * 1e6)}{random.randint(0, 9999):04d}"
    return {
        "custom_id": base + extra,
        "method": "POST",
        "url": "/v1/chat/completions",
        "body": {
            "model": model,
            "messages": [
                {
                    "role": system_role(model),
                    "content": system_prompt
                },
                {
                    "role": "user",
                    "content": user_prompt
                },
                {
                    "role": "user",
                    "content": contenido
                },
            ],
            "temperature": 0,
            "max_completion_tokens": tokens,
        },
    }


def subir_archivo(file_path, api_key):
    url = "https://api.openai.com/v1/files"
    headers = {"Authorization": f"Bearer {api_key}"}
    with open(file_path, "rb") as f:
        response = requests.post(
            url, headers=headers,
            files={"file": (os.path.basename(file_path), f)},
            data={"purpose": "batch"},
            timeout=_TIMEOUT_LARGO,
        )
    response.raise_for_status()
    return response.json()


def crear_batch(file_id, api_key, metadata=None):
    url = "https://api.openai.com/v1/batches"
    headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
    payload = {
        "input_file_id": file_id,
        "endpoint": "/v1/chat/completions",
        "completion_window": "24h",
    }
    if metadata:
        payload["metadata"] = metadata
    response = requests.post(url, headers=headers, json=payload, timeout=_TIMEOUT_CORTO)
    response.raise_for_status()
    return response.json()


def consultar_batch(batch_id, api_key):
    _validar_id(batch_id, "batch_id")
    url = f"https://api.openai.com/v1/batches/{batch_id}"
    headers = {"Authorization": f"Bearer {api_key}"}
    response = requests.get(url, headers=headers, timeout=_TIMEOUT_CORTO)
    response.raise_for_status()
    return response.json()


def descargar_output(file_id, api_key, directorio_destino):
    _validar_id(file_id, "file_id")
    os.makedirs(directorio_destino, exist_ok=True)
    fecha = datetime.datetime.now().strftime("%Y%m%d")
    random_id = uuid.uuid4().hex[:5]
    ruta = os.path.join(directorio_destino, f"output_{fecha}_{random_id}.jsonl")

    url = f"https://api.openai.com/v1/files/{file_id}/content"
    headers = {"Authorization": f"Bearer {api_key}"}
    response = requests.get(url, headers=headers, timeout=_TIMEOUT_LARGO)
    response.raise_for_status()

    with open(ruta, "wb") as f:
        f.write(response.content)
    return ruta
