from importlib.util import module_from_spec, spec_from_file_location
from pathlib import Path

import nonebot
from PIL import Image


nonebot.init()

MODULE_PATH = Path(__file__).resolve().parents[1] / "konabot/plugins/fx_process/fx_handle.py"
SPEC = spec_from_file_location("test_fx_handle_module", MODULE_PATH)
assert SPEC is not None and SPEC.loader is not None
fx_handle = module_from_spec(SPEC)
SPEC.loader.exec_module(fx_handle)
ImageFilterImplement = fx_handle.ImageFilterImplement

INIT_MODULE_PATH = Path(__file__).resolve().parents[1] / "konabot/plugins/fx_process/__init__.py"
INIT_SPEC = spec_from_file_location("test_fx_init_module", INIT_MODULE_PATH)
assert INIT_SPEC is not None and INIT_SPEC.loader is not None
fx_init = module_from_spec(INIT_SPEC)
INIT_SPEC.loader.exec_module(fx_init)
prase_input_args = fx_init.prase_input_args


def test_apply_jpeg_damage_keeps_size_and_rgba_mode():
    image = Image.new("RGBA", (32, 24), (255, 0, 0, 128))

    result = ImageFilterImplement.apply_jpeg_damage(image, 5)

    assert result.size == image.size
    assert result.mode == "RGBA"
    assert result.getchannel("A").getextrema() == (128, 128)


def test_apply_jpeg_damage_clamps_quality_range():
    image = Image.new("RGB", (16, 16), (123, 222, 111))

    low = ImageFilterImplement.apply_jpeg_damage(image, -10)
    high = ImageFilterImplement.apply_jpeg_damage(image, 999)

    assert low.size == image.size
    assert high.size == image.size
    assert low.mode == "RGBA"
    assert high.mode == "RGBA"


def test_apply_resize_clamps_small_result_to_at_least_one_pixel():
    image = Image.new("RGBA", (10, 10), (255, 0, 0, 255))

    result = ImageFilterImplement.apply_resize(image, 0.01)

    assert result.size == (1, 1)


def test_apply_resize_negative_x_with_positive_y_only_mirrors_horizontally():
    image = Image.new("RGBA", (2, 1))
    image.putpixel((0, 0), (255, 0, 0, 255))
    image.putpixel((1, 0), (0, 0, 255, 255))

    result = ImageFilterImplement.apply_resize(image, -1, 1)

    assert result.size == (2, 1)
    assert result.getpixel((0, 0)) == (0, 0, 255, 255)
    assert result.getpixel((1, 0)) == (255, 0, 0, 255)


def test_apply_resize_negative_scale_without_y_flips_both_axes():
    image = Image.new("RGBA", (2, 2))
    image.putpixel((0, 0), (255, 0, 0, 255))
    image.putpixel((1, 0), (0, 255, 0, 255))
    image.putpixel((0, 1), (0, 0, 255, 255))
    image.putpixel((1, 1), (255, 255, 0, 255))

    result = ImageFilterImplement.apply_resize(image, -1)

    assert result.size == (2, 2)
    assert result.getpixel((0, 0)) == (255, 255, 0, 255)
    assert result.getpixel((1, 0)) == (0, 0, 255, 255)
    assert result.getpixel((0, 1)) == (0, 255, 0, 255)
    assert result.getpixel((1, 1)) == (255, 0, 0, 255)


def test_prase_input_args_parses_resize_second_argument_as_float():
    filters = prase_input_args("缩放 2 3")

    assert len(filters) == 1
    assert filters[0].name == "缩放"
    assert filters[0].args == [2.0, 3.0]


def test_apply_pixel_sort_keeps_image_mode_and_size():
    """测试 Pixel Sort 保持图像的 mode 和 size"""
    image = Image.new("RGBA", (10, 10), (255, 0, 0, 128))

    result = ImageFilterImplement.apply_pixel_sort(image)

    assert result.size == image.size
    assert result.mode == "RGBA"


def test_apply_pixel_sort_horizontal():
    """测试水平方向的 Pixel Sort"""
    # 创建一个简单的渐变图像
    image = Image.new("RGB", (5, 3))
    # 第一行：红到蓝渐变
    image.putpixel((0, 0), (255, 0, 0))
    image.putpixel((1, 0), (200, 0, 0))
    image.putpixel((2, 0), (100, 0, 0))
    image.putpixel((3, 0), (50, 0, 0))
    image.putpixel((4, 0), (0, 0, 255))
    # 填充其他行
    for y in range(1, 3):
        for x in range(5):
            image.putpixel((x, y), (128, 128, 128))

    result = ImageFilterImplement.apply_pixel_sort(
        image, direction="horizontal", auto_threshold=False, mask_threshold=10
    )

    assert result.size == image.size
    assert result.mode == "RGBA"


def test_apply_pixel_sort_vertical():
    """测试垂直方向的 Pixel Sort"""
    image = Image.new("RGB", (3, 5))
    # 第一列：绿到红渐变
    image.putpixel((0, 0), (0, 255, 0))
    image.putpixel((0, 1), (0, 200, 0))
    image.putpixel((0, 2), (0, 100, 0))
    image.putpixel((0, 3), (0, 50, 0))
    image.putpixel((0, 4), (255, 0, 0))
    # 填充其他列
    for y in range(5):
        for x in range(1, 3):
            image.putpixel((x, y), (128, 128, 128))

    result = ImageFilterImplement.apply_pixel_sort(
        image, direction="vertical", auto_threshold=False, mask_threshold=10
    )

    assert result.size == image.size
    assert result.mode == "RGBA"


def test_prase_input_args_parses_pixel_sort_arguments():
    """测试解析 Pixel Sort 参数"""
    filters = prase_input_args("像素排序 horizontal 0 false brightness 128 false 1")

    assert len(filters) == 1
    assert filters[0].name == "像素排序"
    assert filters[0].args == ["horizontal", 0.0, False, "brightness", 128.0, False, 1]
