# pyright: reportPrivateUsage=false
"""Unit tests: image builders (img_to_img, controlnet, upscale, remove_bg, estimate)
and gen_agent message builder."""

from seaart._enums import ImageSize
from seaart._internal._builders.gen_agent import build_stream_gen_agent_message
from seaart._internal._builders.images import (
    build_controlnet_to_img_body,
    build_estimate_body,
    build_img_to_img_body,
    build_remove_bg_body,
    build_remove_bg_options_from_meta,
    build_upscale_body,
    build_upscale_hd_fix_body,
    build_upscale_options_from_meta,
)
from seaart._internal._schemas.images import Meta
from seaart.options import (
    ControlnetToImgOptions,
    EstimateOptions,
    ImgToImgOptions,
    RemoveBgOptions,
    UpscaleHdFixOptions,
    UpscaleOptions,
)
from seaart.options.gen_agent_messages import (
    GenAgentBizParamOptions,
    GenAgentReqOptions,
    ImagePartOptions,
)


# ── build_img_to_img_body ──────────────────────────────────────────────────


class TestBuildImgToImg:
    def test_basic_fields(self) -> None:
        body = build_img_to_img_body(
            model_no="m1", model_ver_no="v1", prompt="a cat",
            image_url="https://example.com/img.png", strength=0.75,
            seed_value=42, prompt_magic=None,
            image_size=ImageSize.SQUARE, num_images=1,
            free_creation=None, options=ImgToImgOptions(),
        )
        assert body.model_no == "m1"
        assert body.meta.prompt == "a cat"
        assert body.meta.init_images == ["https://example.com/img.png"]
        assert body.meta.denoising_strength == 0.75
        assert body.meta.seed == 42

    def test_speed_type_free_creation_true(self) -> None:
        body = build_img_to_img_body(
            model_no="m1", model_ver_no="v1", prompt="cat",
            image_url="https://example.com/img.png", strength=0.5,
            seed_value=1, prompt_magic=None,
            image_size=ImageSize.SQUARE, num_images=1,
            free_creation=True, options=ImgToImgOptions(),
        )
        assert body.speed_type == 3

    def test_prompt_magic_false(self) -> None:
        body = build_img_to_img_body(
            model_no="m1", model_ver_no="v1", prompt="cat",
            image_url="https://example.com/img.png", strength=0.5,
            seed_value=1, prompt_magic=False,
            image_size=ImageSize.SQUARE, num_images=1,
            free_creation=None, options=ImgToImgOptions(),
        )
        generate = body.meta.generate
        assert generate is not None
        assert generate.prompt_magic_mode == 1


# ── build_controlnet_to_img_body ───────────────────────────────────────────


class TestBuildControlnet:
    def test_basic_fields(self) -> None:
        body = build_controlnet_to_img_body(
            model_no="m1", model_ver_no="v1", prompt="cat",
            control_input_image="https://example.com/cn.png",
            weight=0.8, seed_value=42, gen_mode="quality",
            image_size=ImageSize.SQUARE, num_images=1,
            free_creation=None, prompt_magic=None,
            options=ControlnetToImgOptions(),
        )
        assert body.model_no == "m1"
        units = body.meta.controlnet_units
        assert units is not None
        assert len(units) == 1
        assert units[0].input_image == "https://example.com/cn.png"
        assert units[0].weight == 0.8

    def test_gen_mode_standard(self) -> None:
        body = build_controlnet_to_img_body(
            model_no="m1", model_ver_no="v1", prompt="cat",
            control_input_image="img", weight=1.0, seed_value=1,
            gen_mode="standard", image_size=ImageSize.SQUARE,
            num_images=1, free_creation=None, prompt_magic=None,
            options=ControlnetToImgOptions(),
        )
        generate = body.meta.generate
        assert generate is not None
        assert generate.gen_mode == 0


# ── build_upscale_body ─────────────────────────────────────────────────────


class TestBuildUpscale:
    def test_basic_fields(self) -> None:
        body = build_upscale_body(
            model_no="m1", model_ver_no="v1", prompt="enhance",
            image_url="https://example.com/img.png",
            seed_value=42, options=UpscaleOptions(),
        )
        assert body.model_no == "m1"
        assert body.meta.prompt == "enhance"
        assert body.meta.init_images == ["https://example.com/img.png"]
        assert body.meta.seed == 42


# ── build_upscale_hd_fix_body ──────────────────────────────────────────────


class TestBuildUpscaleHdFix:
    def test_basic_fields(self) -> None:
        body = build_upscale_hd_fix_body(
            image_url="https://example.com/img.png",
            upscaler_1="4x-UltraSharp", upscaling_resize=2.0,
            options=UpscaleHdFixOptions(),
        )
        assert body.action == 6
        meta = body.meta
        assert meta is not None
        hi_res_arg = meta.hi_res_arg
        assert hi_res_arg is not None
        assert hi_res_arg.image == "https://example.com/img.png"
        assert hi_res_arg.upscaler_1 == "4x-UltraSharp"
        assert hi_res_arg.upscaling_resize == 2.0


# ── build_remove_bg_body ──────────────────────────────────────────────────


class TestBuildRemoveBg:
    def test_basic_fields(self) -> None:
        body = build_remove_bg_body(
            image_url="https://example.com/img.png",
            options=RemoveBgOptions(),
        )
        assert body.action == 7
        meta = body.meta
        assert meta is not None
        remove_bg = meta.remove_background
        assert remove_bg is not None
        assert remove_bg.uri == "https://example.com/img.png"


# ── build_estimate_body ────────────────────────────────────────────────────


class TestBuildEstimate:
    def test_basic_fields(self) -> None:
        body = build_estimate_body(
            model_no="m1", model_ver_no="v1", prompt="cat",
            image_url=None, seed_value=42, options=EstimateOptions(),
        )
        assert body.model_no == "m1"
        assert body.meta.prompt == "cat"
        assert body.meta.seed == 42
        lab_base = body.meta.lab_base
        assert lab_base is not None
        assert lab_base.conds == []

    def test_with_image_url(self) -> None:
        body = build_estimate_body(
            model_no="m1", model_ver_no="v1", prompt="cat",
            image_url="https://example.com/img.png",
            seed_value=42, options=EstimateOptions(),
        )
        lab_base = body.meta.lab_base
        assert lab_base is not None
        conds = lab_base.conds
        assert conds is not None
        assert len(conds) == 1
        assert conds[0].image == "https://example.com/img.png"


# ── build_upscale_options_from_meta ────────────────────────────────────────


class TestBuildUpscaleOptionsFromMeta:
    def test_copies_meta_values(self) -> None:
        meta = Meta(prompt="test", width=1024, height=768, steps=30, seed=123)
        result = build_upscale_options_from_meta(meta=meta, defaults=UpscaleOptions())
        assert result.size.width == 1024
        assert result.size.height == 768
        assert result.sampling.steps == 30
        assert result.sampling.seed == 123


# ── build_remove_bg_options_from_meta ──────────────────────────────────────


class TestBuildRemoveBgOptionsFromMeta:
    def test_copies_meta_values(self) -> None:
        meta = Meta(prompt="test", width=512, height=512, steps=20, seed=99)
        result = build_remove_bg_options_from_meta(meta=meta, defaults=RemoveBgOptions())
        assert result.width == 512
        assert result.height == 512
        assert result.steps == 20
        assert result.seed == 99


# ── build_stream_gen_agent_message ─────────────────────────────────────────


class TestBuildGenAgentMessage:
    def test_text_only(self) -> None:
        body = build_stream_gen_agent_message(
            conv_id="conv-1", message="hello", start_new_topic=True, role="user",
        )
        assert body.conv_id == "conv-1"
        assert body.start_new_topic is True
        assert body.is_first_msg is True
        assert len(body.messages) == 1
        assert body.messages[0].content.parts == ["hello"]
        assert body.biz_param is None

    def test_with_parent_msg_id(self) -> None:
        body = build_stream_gen_agent_message(
            conv_id="conv-1", message="followup",
            start_new_topic=False, role="user",
            parent_msg_id="msg-prev",
        )
        assert body.parent_msg_id == "msg-prev"
        assert body.is_first_msg is False

    def test_with_images(self) -> None:
        opts = GenAgentReqOptions(
            images=[ImagePartOptions(url="https://example.com/img.png", width=512, height=512)]
        )
        body = build_stream_gen_agent_message(
            conv_id="conv-1", message="describe this",
            start_new_topic=True, role="user", options=opts,
        )
        # With images: enable_agent is True, multi_parts has image + text
        assert body.enable_agent is True
        multi_parts = body.messages[0].content.multi_parts
        assert multi_parts is not None
        assert len(multi_parts) == 2
        assert multi_parts[0].content_type == "image"
        assert multi_parts[1].content_type == "text"
        # Metadata has attachments
        metadata = body.messages[0].metadata
        assert metadata is not None
        assert len(metadata.attachments) == 1
        # biz_param auto-created
        assert body.biz_param is not None

    def test_with_biz_param(self) -> None:
        opts = GenAgentReqOptions(
            biz_param=GenAgentBizParamOptions(conv_type="creative_flow")
        )
        body = build_stream_gen_agent_message(
            conv_id="conv-1", message="hi", start_new_topic=True, role="user",
            options=opts,
        )
        biz_param = body.biz_param
        assert biz_param is not None
        assert biz_param.conv_type == "creative_flow"

    def test_empty_message(self) -> None:
        body = build_stream_gen_agent_message(
            conv_id="conv-1", message="", start_new_topic=True, role="user",
        )
        # Empty message: no text MultiPart added
        assert body.messages[0].content.parts is not None
        assert body.messages[0].content.parts == [""]
