"""
Enhanced Type Safety for Qt Styles
==================================

提供严格的类型验证和更完善的类型注解系统。
"""

from __future__ import annotations

import re
from dataclasses import dataclass
from enum import Enum
from typing import Protocol, Union, runtime_checkable


@runtime_checkable
class Validatable(Protocol):
    """可验证协议."""

    def validate(self) -> list[str]:
        """验证对象并返回错误列表."""
        ...


class ColorValidator:
    """颜色值验证器."""

    # 支持的颜色格式正则表达式
    HEX_COLOR_PATTERN = re.compile(r"^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$")
    RGB_COLOR_PATTERN = re.compile(r"^rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)$")
    RGBA_COLOR_PATTERN = re.compile(
        r"^rgba\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*(0|1|0?\.\d+)\s*\)$"
    )
    NAMED_COLOR_PATTERN = re.compile(r"^(transparent|none|[a-zA-Z]+)$")

    @classmethod
    def validate_color(cls, color_value: str, color_name: str = "Color") -> list[str]:
        """验证颜色值."""
        errors = []

        if not isinstance(color_value, str):
            errors.append(f"{color_name}: 颜色值必须是字符串类型")
            return errors

        if not color_value:
            errors.append(f"{color_name}: 颜色值不能为空")
            return errors

        # 检查各种颜色格式
        valid_formats = [
            cls.HEX_COLOR_PATTERN.match(color_value),
            cls.RGB_COLOR_PATTERN.match(color_value),
            cls.RGBA_COLOR_PATTERN.match(color_value),
            cls.NAMED_COLOR_PATTERN.match(color_value),
        ]

        if not any(valid_formats):
            errors.append(f"{color_name}: '{color_value}' 不是有效的颜色格式")
            errors.append(
                f"{color_name}: 支持格式: #RRGGBB, rgb(r,g,b), rgba(r,g,b,a), 或命名颜色"
            )

        return errors


class DimensionValidator:
    """尺寸值验证器."""

    @classmethod
    def validate_dimension(
        cls, dim_value: int, dim_name: str = "Dimension"
    ) -> list[str]:
        """验证尺寸值."""
        errors = []

        if not isinstance(dim_value, int):
            errors.append(f"{dim_name}: 尺寸值必须是整数类型")
            return errors

        if dim_value < 0:
            errors.append(f"{dim_name}: 尺寸值不能为负数 ({dim_value})")

        if dim_value > 1000:
            errors.append(f"{dim_name}: 尺寸值过大 ({dim_value}), 建议不超过1000")

        return errors


class FontValidator:
    """字体值验证器."""

    VALID_FONT_WEIGHTS = {
        "normal",
        "bold",
        "lighter",
        "bolder",
        "100",
        "200",
        "300",
        "400",
        "500",
        "600",
        "700",
        "800",
        "900",
    }
    FONT_SIZE_PATTERN = re.compile(r"^\d+(px|pt|em|rem|%)$")

    @classmethod
    def validate_font_family(
        cls, font_value: str, font_name: str = "Font"
    ) -> list[str]:
        """验证字体族."""
        errors = []

        if not isinstance(font_value, str):
            errors.append(f"{font_name}: 字体值必须是字符串类型")
            return errors

        if not font_value:
            errors.append(f"{font_name}: 字体值不能为空")

        # 检查是否包含有效的字体名称
        font_parts = [part.strip().strip("'\"") for part in font_value.split(",")]
        if not font_parts or all(not part for part in font_parts):
            errors.append(f"{font_name}: 必须指定至少一个有效字体")

        return errors

    @classmethod
    def validate_font_size(
        cls, size_value: str, size_name: str = "FontSize"
    ) -> list[str]:
        """验证字体大小."""
        errors = []

        if not isinstance(size_value, str):
            errors.append(f"{size_name}: 字体大小必须是字符串类型")
            return errors

        if not cls.FONT_SIZE_PATTERN.match(size_value):
            errors.append(f"{size_name}: '{size_value}' 不是有效的字体大小格式")
            errors.append(f"{size_name}: 支持格式: 数字+单位 (px, pt, em, rem, %)")

        return errors

    @classmethod
    def validate_font_weight(
        cls, weight_value: str, weight_name: str = "FontWeight"
    ) -> list[str]:
        """验证字体粗细."""
        errors = []

        if not isinstance(weight_value, str):
            errors.append(f"{weight_name}: 字体粗细必须是字符串类型")
            return errors

        if weight_value not in cls.VALID_FONT_WEIGHTS:
            errors.append(f"{weight_name}: '{weight_value}' 不是有效的字体粗细值")
            errors.append(
                f"{weight_name}: 支持值: {', '.join(sorted(cls.VALID_FONT_WEIGHTS))}"
            )

        return errors


@dataclass
class ValidationError:
    """验证错误信息."""

    field_name: str
    field_type: str
    errors: list[str]

    def __str__(self) -> str:
        error_lines = [f"{self.field_type} '{self.field_name}' 验证失败:"]
        for error in self.errors:
            error_lines.append(f"  - {error}")
        return "\n".join(error_lines)


class ThemeValidator:
    """主题验证器 - 综合验证主题的所有配置."""

    @classmethod
    def _validate_colors_section(
        cls, colors: dict[str, str] | None
    ) -> list[ValidationError]:
        """验证颜色配置部分."""
        errors = []
        if colors:
            for color_name, color_value in colors.items():
                color_errors = ColorValidator.validate_color(color_value, color_name)
                if color_errors:
                    errors.append(ValidationError(color_name, "Color", color_errors))
        return errors

    @classmethod
    def _validate_dimensions_section(
        cls, dimensions: dict[str, int] | None
    ) -> list[ValidationError]:
        """验证尺寸配置部分."""
        errors = []
        if dimensions:
            for dim_name, dim_value in dimensions.items():
                dim_errors = DimensionValidator.validate_dimension(dim_value, dim_name)
                if dim_errors:
                    errors.append(ValidationError(dim_name, "Dimension", dim_errors))
        return errors

    @classmethod
    def _validate_fonts_section(
        cls, fonts: dict[str, str] | None
    ) -> list[ValidationError]:
        """验证字体配置部分."""
        errors = []
        if fonts:
            for font_name, font_value in fonts.items():
                font_errors = []
                if "SIZE" in font_name.upper():
                    font_errors.extend(
                        FontValidator.validate_font_size(font_value, font_name)
                    )
                elif "WEIGHT" in font_name.upper():
                    font_errors.extend(
                        FontValidator.validate_font_weight(font_value, font_name)
                    )
                else:
                    font_errors.extend(
                        FontValidator.validate_font_family(font_value, font_name)
                    )

                if font_errors:
                    errors.append(ValidationError(font_name, "Font", font_errors))
        return errors

    @classmethod
    def validate_theme_config(
        cls,
        colors: dict[str, str] | None = None,
        dimensions: dict[str, int] | None = None,
        fonts: dict[str, str] | None = None,
    ) -> list[ValidationError]:
        """验证主题配置."""
        errors = []

        # 分别验证各个配置部分
        errors.extend(cls._validate_colors_section(colors))
        errors.extend(cls._validate_dimensions_section(dimensions))
        errors.extend(cls._validate_fonts_section(fonts))

        return errors

    @classmethod
    def format_validation_errors(cls, errors: list[ValidationError]) -> str:
        """格式化验证错误信息."""
        if not errors:
            return "✓ 配置验证通过"

        error_lines = [f"发现 {len(errors)} 个验证错误:\n"]
        for i, error in enumerate(errors, 1):
            error_lines.append(f"{i}. {error}")
            if i < len(errors):
                error_lines.append("")

        return "\n".join(error_lines)


# 类型别名增强
ColorValue = Union[str, Enum]
DimensionValue = Union[int, Enum]
FontValue = Union[str, Enum]


# 严格类型验证装饰器
def validate_theme_config(func):
    """装饰器：验证主题配置参数."""

    def wrapper(*args, **kwargs):
        # 提取配置参数
        colors = kwargs.get("colors", {})
        dimensions = kwargs.get("dimensions", {})
        fonts = kwargs.get("fonts", {})

        # 验证配置
        errors = ThemeValidator.validate_theme_config(colors, dimensions, fonts)
        if errors:
            error_msg = ThemeValidator.format_validation_errors(errors)
            raise ValueError(f"主题配置验证失败:\n{error_msg}")

        return func(*args, **kwargs)

    return wrapper


# 便利的验证函数
def validate_single_color(color_name: str, color_value: str) -> bool:
    """验证单个颜色值."""
    errors = ColorValidator.validate_color(color_value, color_name)
    return len(errors) == 0


def validate_single_dimension(dim_name: str, dim_value: int) -> bool:
    """验证单个尺寸值."""
    errors = DimensionValidator.validate_dimension(dim_value, dim_name)
    return len(errors) == 0


def validate_single_font(font_name: str, font_value: str) -> bool:
    """验证单个字体值."""
    errors = []
    if "SIZE" in font_name.upper():
        errors.extend(FontValidator.validate_font_size(font_value, font_name))
    elif "WEIGHT" in font_name.upper():
        errors.extend(FontValidator.validate_font_weight(font_value, font_name))
    else:
        errors.extend(FontValidator.validate_font_family(font_value, font_name))
    return len(errors) == 0


# 预定义的有效值集合
VALID_COLOR_NAMES = {
    "aliceblue",
    "antiquewhite",
    "aqua",
    "aquamarine",
    "azure",
    "beige",
    "bisque",
    "black",
    "blanchedalmond",
    "blue",
    "blueviolet",
    "brown",
    "burlywood",
    "cadetblue",
    "chartreuse",
    "chocolate",
    "coral",
    "cornflowerblue",
    "cornsilk",
    "crimson",
    "cyan",
    "darkblue",
    "darkcyan",
    "darkgoldenrod",
    "darkgray",
    "darkgreen",
    "darkkhaki",
    "darkmagenta",
    "darkolivegreen",
    "darkorange",
    "darkorchid",
    "darkred",
    "darksalmon",
    "darkseagreen",
    "darkslateblue",
    "darkslategray",
    "darkturquoise",
    "darkviolet",
    "deeppink",
    "deepskyblue",
    "dimgray",
    "dodgerblue",
    "firebrick",
    "floralwhite",
    "forestgreen",
    "fuchsia",
    "gainsboro",
    "ghostwhite",
    "gold",
    "goldenrod",
    "gray",
    "green",
    "greenyellow",
    "honeydew",
    "hotpink",
    "indianred",
    "indigo",
    "ivory",
    "khaki",
    "lavender",
    "lavenderblush",
    "lawngreen",
    "lemonchiffon",
    "lightblue",
    "lightcoral",
    "lightcyan",
    "lightgoldenrodyellow",
    "lightgray",
    "lightgreen",
    "lightpink",
    "lightsalmon",
    "lightseagreen",
    "lightskyblue",
    "lightslategray",
    "lightsteelblue",
    "lightyellow",
    "lime",
    "limegreen",
    "linen",
    "magenta",
    "maroon",
    "mediumaquamarine",
    "mediumblue",
    "mediumorchid",
    "mediumpurple",
    "mediumseagreen",
    "mediumslateblue",
    "mediumspringgreen",
    "mediumturquoise",
    "mediumvioletred",
    "midnightblue",
    "mintcream",
    "mistyrose",
    "moccasin",
    "navajowhite",
    "navy",
    "oldlace",
    "olive",
    "olivedrab",
    "orange",
    "orangered",
    "orchid",
    "palegoldenrod",
    "palegreen",
    "paleturquoise",
    "palevioletred",
    "papayawhip",
    "peachpuff",
    "peru",
    "pink",
    "plum",
    "powderblue",
    "purple",
    "red",
    "rosybrown",
    "royalblue",
    "saddlebrown",
    "salmon",
    "sandybrown",
    "seagreen",
    "seashell",
    "sienna",
    "silver",
    "skyblue",
    "slateblue",
    "slategray",
    "snow",
    "springgreen",
    "steelblue",
    "tan",
    "teal",
    "thistle",
    "tomato",
    "turquoise",
    "violet",
    "wheat",
    "white",
    "whitesmoke",
    "yellow",
    "yellowgreen",
    "transparent",
    "none",
}
