#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Test error module

- Author: Rex Zhou <879582094@qq.com>
- Created Time: 2025/5/27 14:58
- Copyright: Copyright © 2025 Rex Zhou. All rights reserved.
"""

from logging import DEBUG, basicConfig
from os import getenv
from pathlib import Path

from dotenv import load_dotenv
from pytest import raises
from yaml import safe_load

# pylint: disable=import-error
from src.pywgb import FileBot
from src.pywgb import ImageBot
from src.pywgb import MarkdownBot
from src.pywgb import NewsBot
from src.pywgb import TextBot
from src.pywgb import VoiceBot
from src.pywgb import TextCardBot
from src.pywgb import NewsCardBot
from tests.test_main import env_file, errors_file, TEST_VALID_ARTICLES

basicConfig(level=DEBUG, format="%(levelname)s %(name)s %(lineno)d %(message)s")
load_dotenv(env_file, override=True)


def test_overheat() -> None:
    """
    Test overheat function
    :return:
    """
    bot = TextBot(getenv("VALID_KEY"))
    bot.send("This message was delayed by overheat", test="overheat")


def test_request_exception() -> None:
    """
    Test request exception
    :return:
    """
    bot = TextBot(getenv("VALID_KEY"))
    with raises(ConnectionRefusedError) as exception_info:
        bot.send("This message WON'T be sent, cause by request error",
                 test="request_error")
    assert "Unable to initiate API request correctly" in str(
        exception_info.value)
    with raises(IOError) as exception_info:
        bot.send("This message WON'T be sent, cause by API error",
                 test="api_error")
    assert "Request failed, please refer to the official manual" in str(
        exception_info.value)


def test_verify_text_error() -> None:
    """
    Test TEXT verification error.
    :return:
    """
    bot = TextBot(getenv("VALID_KEY"))
    with raises(ValueError) as error:
        bot.send()
    assert "The msg parameter is required" in str(error.value)
    err_msg = "parameter should be a list of strings"
    tests = [
        [123],
        (123,),
    ]
    for test in tests:
        with raises(ValueError) as error:
            bot.send("This message won't be sent, cause verify error.",
                     mentioned_mobile_list=test)
        assert err_msg in str(error.value)


def test_verify_markdown_error() -> None:
    """
    Test MARKDOWN verification error.
    :return:
    """
    bot = MarkdownBot(getenv("VALID_KEY"))
    with raises(ValueError) as error:
        bot.send()
    assert "The msg parameter is required" in str(error.value)
    with raises(ValueError) as error:
        # pylint: disable=protected-access
        bot._color("This will raise an exception", "red")
    assert "Invalid _color" in str(error.value)


def test_verify_news_error() -> None:
    """
    Test News verification error.
    :return:
    """
    bot = NewsBot(getenv("VALID_KEY"))
    # Test empty articles
    with raises(ValueError) as exception_info:
        bot.send()
    assert "The articles parameter is required" in str(exception_info.value)
    with raises(ValueError) as exception_info:
        bot.send(articles=[])
    assert "The articles parameter is empty" in str(exception_info.value)
    # Test oversize articles
    with raises(ValueError) as exception_info:
        articles = [TEST_VALID_ARTICLES[0] for _ in range(9)]
        bot.send(articles=articles)
    assert "Too many articles." in str(exception_info.value)
    # Test data error and parameter error
    tests = {
        "article_data_error": "data is not a dict",
        "article_parameter_error": "lack required parameter",
    }
    for code, msg in tests.items():
        with raises(ValueError) as exception_info:
            bot.send(articles=TEST_VALID_ARTICLES, test=code)
        assert msg in str(exception_info.value)


def test_verify_image_error() -> None:
    """
    Test image verification error.
    :return:
    """
    bot = ImageBot(getenv("VALID_KEY"))
    with raises(ValueError) as exception_info:
        bot.send()
    assert "The file_path parameter is required" in str(exception_info.value)
    file = Path(__file__).with_name("test.png")
    mapper = {
        "wrong_format_image": "Just support image type: jpg or png",
        "oversize_image": "The image is too large, more than 2M",
    }
    for code, msg in mapper.items():
        with raises(ValueError) as exception_info:
            bot.send(file_path=file, test=code)
        assert msg in str(exception_info.value)


def test_verify_file_error() -> None:
    """
    Test verify file error.
    :return:
    """
    bot = FileBot(getenv("VALID_KEY"))
    # Test lack file
    with raises(ValueError) as exception_info:
        bot.send()
    assert "The file_path parameter is required" in str(exception_info.value)
    # Test empty file
    with raises(ValueError) as exception_info:
        bot.send(file_path=None)
    assert "The file_path parameter is required" in str(exception_info.value)
    # Test invalid file
    with raises(ValueError) as exception_info:
        bot.send(file_path="234234234.txt")
    assert "The file_path parameter not exists" in str(exception_info.value)
    # Test oversize file
    file = Path(__file__).with_name("test.png")
    with raises(ValueError) as exception_info:
        bot.send(file_path=file, test="oversize_file")
    assert "The file size is out of range" in str(exception_info.value)


def test_verify_voice_error() -> None:
    """
    Test voice verification error.
    :return:
    """
    bot = VoiceBot(getenv("VALID_KEY"))
    # Test lack file
    with raises(ValueError) as exception_info:
        bot.send()
    assert "The file_path parameter is required" in str(exception_info.value)
    # Test invalid file format
    file = Path(__file__).with_name("test.png")
    with raises(ValueError) as exception_info:
        bot.send(file_path=file, test="wrong_format_voice")
    assert "Just support voice type: amr" in str(exception_info.value)
    # Test overlong and oversize voice
    file = Path(__file__).with_name("test.amr")
    tests = {
        "oversize_voice": "The voice size is out of range",
        "overlong_voice": "The voice duration is longer than 60s",
    }
    for code, msg in tests.items():
        with raises(ValueError) as exception_info:
            bot.send(file_path=file, test=code)
        assert msg in str(exception_info.value)


def test_verify_text_card_error() -> None:
    """
    Test Text Card verification error.
    :return:
    """
    bot = TextCardBot(getenv("VALID_KEY"))
    with open(errors_file, "r", encoding="utf-8") as _:
        tests = safe_load(_)
    for err_msg, kwargs in tests["text"].items():
        with raises(ValueError) as error:
            bot.send(**kwargs)
        assert err_msg in str(error.value)


def test_verify_news_card_error() -> None:
    """
    Test News Card verification error.
    :return:
    """
    bot = NewsCardBot(getenv("VALID_KEY"))
    with open(errors_file, "r", encoding="utf-8") as _:
        tests = safe_load(_)
    for err_msg, kwargs in tests["news"].items():
        with raises(ValueError) as error:
            bot.send(**kwargs)
        assert err_msg in str(error.value)
