"""FikoYT InstantID Face Apply — SDXL için InstantX/InstantID identity injection.

ComfyUI_InstantID node'una sarmalayıcı. InstantX/InstantID + antelopev2 auto-download.
"""
import os

_INSTANTID_APPLY = None
_INSTANTID_FACE_LOADER = None
try:
    from custom_nodes.ComfyUI_InstantID import InstantID as _instantid_mod  # type: ignore
    _INSTANTID_APPLY = getattr(_instantid_mod, "ApplyInstantID", None)
    _INSTANTID_FACE_LOADER = getattr(_instantid_mod, "InstantIDFaceAnalysis", None)
except Exception:
    try:
        import ComfyUI_InstantID  # type: ignore  # noqa: F401
    except Exception:
        pass

from ..core import ensure_model, get_models_dir


INSTANTID_MODELS = [
    {"repo": "InstantX/InstantID", "file": "ip-adapter.bin", "subdir": "instantid"},
    {"repo": "InstantX/InstantID", "file": "ControlNetModel/config.json",        "subdir": "controlnet/InstantID"},
    {"repo": "InstantX/InstantID", "file": "ControlNetModel/diffusion_pytorch_model.safetensors", "subdir": "controlnet/InstantID"},
]

ANTELOPEV2_FILES = [
    "1k3d68.onnx", "2d106det.onnx", "genderage.onnx", "glintr100.onnx", "scrfd_10g_bnkps.onnx",
]


def _download_all(auto_download: bool) -> None:
    if not auto_download:
        return
    for m in INSTANTID_MODELS:
        target = os.path.join(get_models_dir(m["subdir"]), os.path.basename(m["file"]))
        if not os.path.isfile(target):
            ensure_model(m["repo"], m["file"], m["subdir"])
    for f in ANTELOPEV2_FILES:
        target = os.path.join(get_models_dir("insightface/models/antelopev2"), f)
        if not os.path.isfile(target):
            ensure_model("DIAMONIK7777/antelopev2", f, "insightface/models/antelopev2")


class FikoYTInstantID:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "model": ("MODEL",),
                "positive": ("CONDITIONING",),
                "negative": ("CONDITIONING",),
                "face_image": ("IMAGE",),
                "weight":   ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.05}),
                "start_at": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
                "end_at":   ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
                "auto_download": ("BOOLEAN", {"default": True}),
            }
        }

    RETURN_TYPES = ("MODEL", "CONDITIONING", "CONDITIONING")
    RETURN_NAMES = ("MODEL", "positive", "negative")
    FUNCTION = "apply"
    CATEGORY = "FikoYT/image"

    def apply(self, model, positive, negative, face_image, weight, start_at, end_at, auto_download):
        _download_all(auto_download)

        if _INSTANTID_APPLY is None:
            raise RuntimeError(
                "ComfyUI_InstantID node bulunamadı. "
                "https://github.com/cubiq/ComfyUI_InstantID yükleyin."
            )

        try:
            instance = _INSTANTID_APPLY()
            if hasattr(instance, "apply_instantid"):
                out = instance.apply_instantid(
                    instantid=None, insightface=None, control_net=None,
                    image=face_image, model=model,
                    positive=positive, negative=negative,
                    weight=weight, start_at=start_at, end_at=end_at,
                )
            else:
                raise AttributeError("ApplyInstantID API'si tanınmıyor.")
        except Exception as e:
            raise RuntimeError(
                f"InstantID uygulanamadı: {e}\n"
                "ComfyUI_InstantID node'unu doğrudan kullanmayı deneyin "
                "(InstantID Face Analysis + Load InstantID + Apply InstantID zinciri)."
            )

        if isinstance(out, tuple) and len(out) >= 3:
            return (out[0], out[1], out[2])
        return (model, positive, negative)


NODE_CLASS_MAPPINGS = {"FikoYTInstantID": FikoYTInstantID}
NODE_DISPLAY_NAME_MAPPINGS = {"FikoYTInstantID": "FikoYT • InstantID Face Apply"}
