import unittest
from types import SimpleNamespace
from unittest.mock import patch

from weibo_image_rescue import main as main_module


def _args(**overrides):
    base = {
        "update_cdn": False,
        "f": None,
        "image_url": "https://wx1.sinaimg.cn/mw690/a.jpg",
        "force_update": False,
        "q": "l,m",
        "output_dir": "./images/",
        "workers": 20,
        "timeout": 10.0,
    }
    base.update(overrides)
    return SimpleNamespace(**base)


class TestMain(unittest.TestCase):
    def test_main_update_cdn_only(self):
        args = _args(update_cdn=True)
        with patch(
            "weibo_image_rescue.main.parse_args", return_value=args
        ) as mock_parse, patch(
            "weibo_image_rescue.main.update_cdn_info"
        ) as mock_update, patch(
            "weibo_image_rescue.main.load_cdn_info"
        ) as mock_load, patch(
            "weibo_image_rescue.main.rescue"
        ) as mock_rescue:
            main_module.main(["-u"])

        mock_parse.assert_called_once_with(["-u"])
        mock_update.assert_called_once()
        mock_load.assert_not_called()
        mock_rescue.assert_not_called()

    def test_main_force_mode_uses_f_url_and_updates_cdn(self):
        args = _args(
            f="https://wx2.sinaimg.cn/mw690/f.jpg",
            image_url=None,
            q="l, m,,o",
            output_dir="/tmp/out",
            workers=7,
            timeout=3.5,
        )
        with patch("weibo_image_rescue.main.parse_args", return_value=args), patch(
            "weibo_image_rescue.main.update_cdn_info"
        ) as mock_update, patch(
            "weibo_image_rescue.main.load_cdn_info", return_value=["1.1.1.1"]
        ) as mock_load, patch(
            "weibo_image_rescue.main.generate_urls_of_all_qualities",
            return_value=["u1", "u2"],
        ) as mock_generate, patch(
            "weibo_image_rescue.main.rescue"
        ) as mock_rescue:
            main_module.main(["-f", args.f])

        mock_update.assert_called_once()
        mock_load.assert_called_once()
        mock_generate.assert_called_once_with(args.f, ["l", "m", "o"])
        mock_rescue.assert_called_once_with(
            ["u1", "u2"],
            ["1.1.1.1"],
            "/tmp/out",
            workers=7,
            timeout=3.5,
        )

    def test_main_force_update_with_positional_url(self):
        args = _args(force_update=True, f=None, image_url="https://wx3.sinaimg.cn/mw690/z.jpg")
        with patch("weibo_image_rescue.main.parse_args", return_value=args), patch(
            "weibo_image_rescue.main.update_cdn_info"
        ) as mock_update, patch(
            "weibo_image_rescue.main.load_cdn_info", return_value=[]
        ), patch(
            "weibo_image_rescue.main.generate_urls_of_all_qualities", return_value=["u"]
        ), patch("weibo_image_rescue.main.rescue"):
            main_module.main(["--force-update", args.image_url])

        mock_update.assert_called_once()

    def test_main_requires_image_url(self):
        args = _args(f=None, image_url=None, force_update=False)
        with patch("weibo_image_rescue.main.parse_args", return_value=args), patch(
            "weibo_image_rescue.main.print"
        ) as mock_print, patch(
            "weibo_image_rescue.main.load_cdn_info"
        ) as mock_load, patch(
            "weibo_image_rescue.main.rescue"
        ) as mock_rescue:
            main_module.main([])

        mock_print.assert_called_once_with("Image URL is required.")
        mock_load.assert_not_called()
        mock_rescue.assert_not_called()


if __name__ == "__main__":
    unittest.main()
