"""ReferencePipelineOrchestrator 단위 테스트 — F24.4.1.

검증 대상:
1. run() 시그니처 (generate_reference_images_only 호환 유지)
2. facade.__init__이 ReferencePipelineOrchestrator를 `_pipeline_svc`로 주입
3. facade.generate_reference_images_only 가 orchestrator.run() 으로 위임
"""
from __future__ import annotations

import inspect
from unittest.mock import MagicMock

from app.services.reference_image_service import ReferenceImageService
from app.services.reference_pipeline_orchestrator import ReferencePipelineOrchestrator


# ──────────────────────────────────────────────────────────────────────
# 1) run() 시그니처 — 기존 generate_reference_images_only 호출자와 호환
# ──────────────────────────────────────────────────────────────────────


def test_run_signature_preserved():
    sig = inspect.signature(ReferencePipelineOrchestrator.run)
    params = sig.parameters
    assert "self" in params
    assert "episode_id" in params
    assert "ip" in params
    assert "mode" in params
    assert "skip_composite" in params
    assert params["skip_composite"].kind == inspect.Parameter.KEYWORD_ONLY
    assert params["skip_composite"].default is False
    assert params["mode"].default == "resume"
    assert params["ip"].default is None


def test_run_rejects_full_mode_early_validation():
    """mode='full' 은 feedback_never_delete_images 가드 — early ValueError.

    Quick win #1: ImageAsset 일괄 DELETE + cp.clear destructive 동작 영구 차단.
    early validation (db/episode lookup 전에) 이라 stub orchestrator 만으로 검증.
    """
    import pytest
    svc = ReferencePipelineOrchestrator.__new__(ReferencePipelineOrchestrator)
    with pytest.raises(ValueError, match="feedback_never_delete_images"):
        svc.run("e1", mode="full")


def test_run_rejects_unknown_mode_early_validation():
    """resume 외 임의 mode 도 early ValueError — whitelist 패턴."""
    import pytest
    svc = ReferencePipelineOrchestrator.__new__(ReferencePipelineOrchestrator)
    with pytest.raises(ValueError, match="unsupported"):
        svc.run("e1", mode="rebuild")


# ──────────────────────────────────────────────────────────────────────
# 2) facade wiring — ReferenceImageService.__init__ → _pipeline_svc
# ──────────────────────────────────────────────────────────────────────


def test_facade_wires_pipeline_orchestrator(monkeypatch):
    """facade가 실제 ReferencePipelineOrchestrator를 `_pipeline_svc`로 주입."""
    captured = {}

    class _Spy(ReferencePipelineOrchestrator):
        def __init__(self, *args, **kwargs):
            captured["args"] = args
            captured["kwargs"] = kwargs
            super().__init__(*args, **kwargs)

    monkeypatch.setattr(
        "app.services.reference_image_service.ReferencePipelineOrchestrator",
        _Spy,
    )

    db = MagicMock()
    svc = ReferenceImageService(db=db, project_id="p1", actor_id="u1")

    assert isinstance(svc._pipeline_svc, _Spy)
    assert isinstance(svc._pipeline_svc, ReferencePipelineOrchestrator)
    # activity_logger는 facade에서 생성된 인스턴스를 그대로 주입
    assert captured["kwargs"]["project_id"] == "p1"
    assert captured["kwargs"]["actor_id"] == "u1"
    assert captured["kwargs"]["activity_logger"] is svc._logger


# ──────────────────────────────────────────────────────────────────────
# 3) facade.generate_reference_images_only → orchestrator.run 위임
# ──────────────────────────────────────────────────────────────────────


def test_generate_reference_images_only_delegates(monkeypatch):
    """facade.generate_reference_images_only(...) → _pipeline_svc.run(...) 그대로 전달.

    mode='resume' 만 valid (#1 Quick win — feedback_never_delete_images 적용).
    facade 는 transparent — mode 전달 검증.
    """
    svc = ReferenceImageService.__new__(ReferenceImageService)
    svc._pipeline_svc = MagicMock()
    svc._pipeline_svc.run.return_value = {"reference_count": 3}

    result = svc.generate_reference_images_only(
        "e1", ip="127.0.0.1", mode="resume", skip_composite=True,
    )

    assert result == {"reference_count": 3}
    svc._pipeline_svc.run.assert_called_once_with(
        "e1", ip="127.0.0.1", mode="resume", skip_composite=True,
    )


def test_generate_base_references_delegates_with_skip_true(monkeypatch):
    """facade.generate_base_references → orchestrator.run(skip_composite=True)."""
    svc = ReferenceImageService.__new__(ReferenceImageService)
    svc._pipeline_svc = MagicMock()
    svc._pipeline_svc.run.return_value = {}

    svc.generate_base_references("e1", mode="resume", ip="127.0.0.1")

    svc._pipeline_svc.run.assert_called_once_with(
        "e1", ip="127.0.0.1", mode="resume", skip_composite=True,
    )


def test_generate_composites_delegates_with_skip_false(monkeypatch):
    """facade.generate_composites → orchestrator.run(skip_composite=False)."""
    svc = ReferenceImageService.__new__(ReferenceImageService)
    svc._pipeline_svc = MagicMock()
    svc._pipeline_svc.run.return_value = {}

    svc.generate_composites("e1", mode="resume")

    svc._pipeline_svc.run.assert_called_once_with(
        "e1", ip=None, mode="resume", skip_composite=False,
    )
