"""genconfig_save_json — persiste un GenerationConfig como JSON en disco."""

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_save_json(cfg: GenerationConfig, path: str) -> str:
    """Serializa un GenerationConfig a JSON y lo escribe en disco.

    Usa model_dump_json(indent=2) si GenerationConfig es instancia de
    pydantic.BaseModel (version con validacion). En caso de fallback a
    dataclass, serializa con json.dumps usando un encoder que convierte
    dataclasses a dict recursivamente.

    Crea los directorios padre si no existen (equivalente a mkdir -p).

    Args:
        cfg: Instancia de GenerationConfig a serializar.
        path: Ruta de destino del archivo JSON. Puede ser relativa o absoluta.

    Returns:
        Path absoluto del archivo escrito.

    Raises:
        OSError: Si no se puede crear el directorio o escribir el archivo.
    """
    abs_path = os.path.abspath(path)
    parent = os.path.dirname(abs_path)
    if parent:
        os.makedirs(parent, exist_ok=True)

    # Intentar serializacion pydantic (version canonica)
    try:
        json_str = cfg.model_dump_json(indent=2)
    except AttributeError:
        # Fallback: dataclass — serializar manualmente
        import dataclasses

        def _to_dict(obj: object) -> object:
            if dataclasses.is_dataclass(obj) and not isinstance(obj, type):
                return {k: _to_dict(v) for k, v in dataclasses.asdict(obj).items()}
            if isinstance(obj, (list, tuple)):
                return [_to_dict(i) for i in obj]
            return obj

        json_str = json.dumps(_to_dict(cfg), indent=2)

    with open(abs_path, "w", encoding="utf-8") as f:
        f.write(json_str)

    return abs_path
