import requests
import base64
import logging

logger = logging.getLogger(__name__)

class ForgeClient:
    def __init__(self, url="http://127.0.0.1:7860", timeout=120):
        self.url = url.rstrip("/")
        self.timeout = timeout
        self.api_base = f"{self.url}/sdapi/v1"

    def check_status(self):
        try:
            r = requests.get(f"{self.url}/sdapi/v1/options", timeout=10)
            return r.status_code == 200
        except requests.ConnectionError:
            return False

    def get_options(self):
        r = requests.get(f"{self.api_base}/options", timeout=self.timeout)
        r.raise_for_status()
        return r.json()

    def set_options(self, options):
        r = requests.post(f"{self.api_base}/options", json=options, timeout=self.timeout)
        r.raise_for_status()
        return r.json()

    def txt2img(self, prompt, negative_prompt="", width=832, height=1216,
                steps=28, cfg_scale=6.0, sampler_name="DPM++ 2M Karras",
                batch_size=1, seed=-1, clip_skip=2, **kwargs):
        payload = {
            "prompt": prompt,
            "negative_prompt": negative_prompt,
            "width": width,
            "height": height,
            "steps": steps,
            "cfg_scale": cfg_scale,
            "sampler_name": sampler_name,
            "batch_size": batch_size,
            "seed": seed,
            "clip_skip": clip_skip,
            "restore_faces": False,
            "tiling": False,
            "enable_hr": False,
        }
        payload.update(kwargs)

        logger.info(f"Enviando a Forge: {len(prompt)} chars, {width}x{height}, steps={steps}")
        r = requests.post(f"{self.api_base}/txt2img", json=payload, timeout=self.timeout)
        r.raise_for_status()
        data = r.json()

        images = []
        for img_b64 in data.get("images", []):
            images.append(base64.b64decode(img_b64))

        info = data.get("info", "{}")
        if isinstance(info, str):
            import json
            try:
                info = json.loads(info)
            except json.JSONDecodeError:
                info = {"raw": info}

        seed = info.get("seed", -1)
        logger.info(f"Forge respondió: {len(images)} imágenes, seed={seed}")

        return images, info

    def save_image(self, image_bytes, filepath):
        with open(filepath, "wb") as f:
            f.write(image_bytes)
        logger.info(f"Imagen guardada: {filepath}")
        return filepath


class VisionClient:
    def __init__(self, url="https://oai.endpoints.kepler.ai.cloud.ovh.net/v1",
                 model="Qwen/Qwen2.5-VL-72B-Instruct", timeout=30):
        self.url = url.rstrip("/")
        self.model = model
        self.timeout = timeout

    def analyze(self, image_b64, prompt=None):
        if prompt is None:
            prompt = (
                "Analiza detalladamente esta ilustración anime de forma puramente técnica y anatómica.\n"
                "Busca errores críticos: más de 5 dedos en una mano, ojos bizcos o pupilas derretidas, "
                "extremidades flotantes o clones deformes en reflejos/espejos.\n"
                "Responde ESTRICTAMENTE con una sola palabra: 'APROBADO' si el cuerpo es correcto, "
                "o 'RECHAZADO' si detectas mutaciones corporales graves."
            )

        payload = {
            "model": self.model,
            "messages": [
                {
                    "role": "user",
                    "content": [
                        {"type": "text", "text": prompt},
                        {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_b64}"}}
                    ]
                }
            ],
            "temperature": 0.1,
            "max_tokens": 100
        }

        try:
            logger.info("Enviando a OVHcloud Vision (Qwen2.5-VL)...")
            r = requests.post(f"{self.url}/chat/completions", json=payload, timeout=self.timeout)
            r.raise_for_status()
            result = r.json()["choices"][0]["message"]["content"].strip()
            logger.info(f"Veredicto crítico: {result}")
            return result
        except Exception as e:
            logger.warning(f"Error en crítico visual: {e}. Aprobando por defecto.")
            return "APROBADO"

    def is_approved(self, verdict):
        return "APROBADO" in verdict.upper()

    def get_rejection_reason(self, verdict):
        if self.is_approved(verdict):
            return None
        return verdict.replace("RECHAZADO:", "").strip()