"""内置函数工具类"""

import random
import string
import uuid
import time
import re
from datetime import datetime, timedelta
from typing import Any, Optional, List


class BuiltInFunction:
    """内置函数工具类

    提供测试中常用的工具函数。
    """

    # ==================== 日期时间函数 ====================

    @staticmethod
    def today(fmt: str = '%Y-%m-%d', offset: int = 0) -> str:
        """获取今天日期

        Args:
            fmt: 日期格式
            offset: 天数偏移

        Returns:
            str: 格式化的日期
        """
        date = datetime.now() + timedelta(days=offset)
        return date.strftime(fmt)

    @staticmethod
    def now(fmt: str = '%Y-%m-%d %H:%M:%S') -> str:
        """获取当前时间

        Args:
            fmt: 时间格式

        Returns:
            str: 格式化的时间
        """
        return datetime.now().strftime(fmt)

    @staticmethod
    def timestamp(unit: str = 'ms') -> int:
        """获取时间戳

        Args:
            unit: 单位 (s, ms)

        Returns:
            int: 时间戳
        """
        ts = time.time()
        if unit == 'ms':
            return int(ts * 1000)
        return int(ts)

    @staticmethod
    def date_add(
        date_str: str,
        days: int = 0,
        hours: int = 0,
        minutes: int = 0,
        fmt: str = '%Y-%m-%d'
    ) -> str:
        """日期加减

        Args:
            date_str: 日期字符串
            days: 天数
            hours: 小时
            minutes: 分钟
            fmt: 日期格式

        Returns:
            str: 计算后的日期
        """
        date = datetime.strptime(date_str, fmt)
        date += timedelta(days=days, hours=hours, minutes=minutes)
        return date.strftime(fmt)

    @staticmethod
    def date_diff(date1: str, date2: str, fmt: str = '%Y-%m-%d') -> int:
        """计算日期差

        Args:
            date1: 日期1
            date2: 日期2
            fmt: 日期格式

        Returns:
            int: 相差天数
        """
        d1 = datetime.strptime(date1, fmt)
        d2 = datetime.strptime(date2, fmt)
        return (d1 - d2).days

    # ==================== 随机数函数 ====================

    @staticmethod
    def random_int(min_val: int = 0, max_val: int = 100) -> int:
        """生成随机整数

        Args:
            min_val: 最小值
            max_val: 最大值

        Returns:
            int: 随机整数
        """
        return random.randint(min_val, max_val)

    @staticmethod
    def random_float(min_val: float = 0, max_val: float = 1.0, precision: int = 2) -> float:
        """生成随机浮点数

        Args:
            min_val: 最小值
            max_val: 最大值
            precision: 小数位数

        Returns:
            float: 随机浮点数
        """
        return round(random.uniform(min_val, max_val), precision)

    @staticmethod
    def random_string(length: int = 8, chars: str = 'alphanumeric') -> str:
        """生成随机字符串

        Args:
            length: 长度
            chars: 字符类型

        Returns:
            str: 随机字符串
        """
        char_map = {
            'alpha': string.ascii_letters,
            'numeric': string.digits,
            'alphanumeric': string.ascii_letters + string.digits,
            'lower': string.ascii_lowercase,
            'upper': string.ascii_uppercase,
            'hex': string.hexdigits.lower(),
        }
        charset = char_map.get(chars, string.ascii_letters + string.digits)
        return ''.join(random.choices(charset, k=length))

    @staticmethod
    def random_phone(prefix: str = '1') -> str:
        """生成随机手机号

        Args:
            prefix: 号码前缀

        Returns:
            str: 随机手机号
        """
        prefixes = ['13', '14', '15', '16', '17', '18', '19']
        phone_prefix = random.choice(prefixes) if prefix == '1' else prefix
        return phone_prefix + ''.join([str(random.randint(0, 9)) for _ in range(9)])

    @staticmethod
    def random_email(domain: str = 'test.com') -> str:
        """生成随机邮箱

        Args:
            domain: 邮箱域名

        Returns:
            str: 随机邮箱
        """
        username = BuiltInFunction.random_string(8, 'lower')
        return f"{username}@{domain}"

    @staticmethod
    def random_name(gender: str = 'random') -> str:
        """生成随机中文姓名

        Args:
            gender: 性别 (male, female, random)

        Returns:
            str: 随机姓名
        """
        surnames = ['张', '王', '李', '赵', '陈', '刘', '杨', '黄', '周', '吴']
        male_names = ['伟', '强', '磊', '军', '洋', '勇', '杰', '涛', '明', '超']
        female_names = ['芳', '娟', '敏', '静', '丽', '娜', '秀', '玲', '艳', '红']

        surname = random.choice(surnames)

        if gender == 'male':
            name = random.choice(male_names)
        elif gender == 'female':
            name = random.choice(female_names)
        else:
            name = random.choice(male_names + female_names)

        # 随机添加双字名
        if random.random() > 0.5:
            name += random.choice(male_names + female_names)

        return surname + name

    @staticmethod
    def random_id_card() -> str:
        """生成随机身份证号

        Returns:
            str: 随机身份证号 (模拟，非真实)
        """
        # 地区码
        area_code = random.choice(['110101', '310101', '440101', '330101', '320101'])

        # 出生日期
        year = random.randint(1970, 2000)
        month = random.randint(1, 12)
        day = random.randint(1, 28)
        birth = f'{year}{month:02d}{day:02d}'

        # 顺序码
        seq = f'{random.randint(0, 999):03d}'

        # 校验码 (简化)
        check = random.choice('0123456789X')

        return area_code + birth + seq + check

    @staticmethod
    def uuid4() -> str:
        """生成 UUID

        Returns:
            str: UUID 字符串
        """
        return str(uuid.uuid4())

    @staticmethod
    def uuid_short() -> str:
        """生成短 UUID (去掉横线)

        Returns:
            str: 短 UUID
        """
        return uuid.uuid4().hex

    # ==================== 字符串函数 ====================

    @staticmethod
    def substring(text: str, start: int, end: int = None) -> str:
        """截取子字符串

        Args:
            text: 原字符串
            start: 起始位置
            end: 结束位置

        Returns:
            str: 子字符串
        """
        return text[start:end]

    @staticmethod
    def replace(text: str, old: str, new: str) -> str:
        """替换字符串

        Args:
            text: 原字符串
            old: 被替换的内容
            new: 新内容

        Returns:
            str: 替换后的字符串
        """
        return text.replace(old, new)

    @staticmethod
    def regex_match(text: str, pattern: str) -> Optional[str]:
        """正则匹配

        Args:
            text: 原字符串
            pattern: 正则表达式

        Returns:
            str: 匹配的内容
        """
        match = re.search(pattern, text)
        return match.group(0) if match else None

    @staticmethod
    def regex_find_all(text: str, pattern: str) -> List[str]:
        """正则查找所有

        Args:
            text: 原字符串
            pattern: 正则表达式

        Returns:
            List[str]: 所有匹配
        """
        return re.findall(pattern, text)

    @staticmethod
    def format_string(template: str, **kwargs) -> str:
        """格式化字符串

        Args:
            template: 模板字符串
            **kwargs: 替换参数

        Returns:
            str: 格式化后的字符串
        """
        return template.format(**kwargs)

    # ==================== 数学函数 ====================

    @staticmethod
    def abs_value(num: float) -> float:
        """绝对值"""
        return abs(num)

    @staticmethod
    def round_value(num: float, precision: int = 0) -> float:
        """四舍五入"""
        return round(num, precision)

    @staticmethod
    def floor(num: float) -> int:
        """向下取整"""
        import math
        return math.floor(num)

    @staticmethod
    def ceil(num: float) -> int:
        """向上取整"""
        import math
        return math.ceil(num)

    @staticmethod
    def max_value(*args) -> Any:
        """最大值"""
        return max(args)

    @staticmethod
    def min_value(*args) -> Any:
        """最小值"""
        return min(args)

    # ==================== 类型转换 ====================

    @staticmethod
    def to_int(value: Any) -> int:
        """转换为整数"""
        return int(value)

    @staticmethod
    def to_float(value: Any) -> float:
        """转换为浮点数"""
        return float(value)

    @staticmethod
    def to_string(value: Any) -> str:
        """转换为字符串"""
        return str(value)

    @staticmethod
    def to_bool(value: Any) -> bool:
        """转换为布尔值"""
        if isinstance(value, str):
            return value.lower() in ('true', '1', 'yes', 'on')
        return bool(value)
