"""genconfig_load_json — carga un GenerationConfig desde un archivo JSON."""

from __future__ import annotations

import json
import os
import sys

sys.path.insert(0, os.path.dirname(__file__))

from generation_config import GenerationConfig


def genconfig_load_json(path: str) -> GenerationConfig:
    """Carga y valida un GenerationConfig desde un archivo JSON en disco.

    Usa GenerationConfig.model_validate(data) si pydantic esta disponible
    (version con validacion completa de tipos y literales). En caso de
    fallback a dataclass, construye la instancia manualmente mapeando
    los campos conocidos.

    Args:
        path: Ruta al archivo JSON. Puede ser relativa o absoluta.

    Returns:
        Instancia de GenerationConfig cargada y validada.

    Raises:
        FileNotFoundError: Si el archivo no existe.
        json.JSONDecodeError: Si el contenido no es JSON valido.
        pydantic.ValidationError: Si los datos no cumplen el schema (version pydantic).
        KeyError / TypeError: Si faltan campos obligatorios (version dataclass).
    """
    abs_path = os.path.abspath(path)
    with open(abs_path, "r", encoding="utf-8") as f:
        data = json.load(f)

    # Intentar deserializacion pydantic (version canonica con validacion)
    try:
        return GenerationConfig.model_validate(data)
    except AttributeError:
        pass

    # Fallback: dataclass — construir manualmente desde el dict
    from lora_ref import LoraRef
    from model_ref import ModelRef

    model_data = data["model"]
    model = ModelRef(
        name=model_data["name"],
        model_type=model_data["model_type"],
        quantization=model_data.get("quantization", "fp16"),
        path=model_data.get("path"),
    )

    loras = [
        LoraRef(
            path=lr["path"],
            weight=lr.get("weight", 1.0),
            scale=lr.get("scale"),
        )
        for lr in data.get("loras", [])
    ]

    return GenerationConfig(
        prompt=data["prompt"],
        negative_prompt=data.get("negative_prompt"),
        seed=data["seed"],
        steps=data["steps"],
        cfg_scale=data["cfg_scale"],
        sampler=data["sampler"],
        width=data["width"],
        height=data["height"],
        model=model,
        loras=tuple(loras),
        clip_skip=data.get("clip_skip"),
    )
