#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：django_base_ai
@File    ：models_safe.py
@Author  ：congxing.wang
@Date    ：2026/02/25
@Desc    ：安全模型与加密字段。EncrypyField 存库 RSA 加密、读库解密；MaskField 用于展示脱敏（姓名/手机/身份证等）。
"""

import logging
import re
from enum import Enum

from django.db import models

from django_base_ai.utils.rsa_util import RsaUtil

logger = logging.getLogger(__name__)

# 全局 RSA 实例，用于 EncrypyField 加解密
rsa_util_obj = RsaUtil()


# 字段类型枚举
class MaskType(Enum):
    """
    掩码类型
    DEFAULT = None  # 默认掩码
    NAME = 1  # 姓名
    MOBILE = 2  # 手机
    ID_CARD = 3  # 身份证
    """

    DEFAULT = None  # 默认掩码
    NAME = 1  # 姓名
    MOBILE = 2  # 手机
    ID_CARD = 3  # 身份证
    CUSTOME = 99999  # 自定义


class MaskField:
    def __init__(
        self, value=None, mask_type=MaskType.DEFAULT, first_value: int = 0, last_value: int = 0, *args, **kwargs
    ):
        """
        根据枚举类型进行掩码
        :param value: 需要掩码的值
        :param mask_type: 更具指定类型掩码
        :param args:
        :param kwargs:
        """
        self.mask_type = mask_type
        self.value = value if value else ""
        self.first_value = first_value
        self.last_value = last_value
        self.fun_dict = {
            MaskType.DEFAULT: self.default,
            MaskType.NAME: self.name,
            MaskType.MOBILE: self.mobile,
            MaskType.ID_CARD: self.id_card,
            MaskType.CUSTOME: self.custome,
        }

    def name(self):
        # 获取姓氏的第一个字母
        first_char = self.value[0]
        # 隐藏姓氏
        desensitized_name = first_char + "*" * (len(self.value) - 1)
        return desensitized_name

    def mobile(self):
        result = re.sub(r"(\d{3})(\d{4})(\d{4})", r"\1****\3", self.value)
        return result

    def id_card(self):
        masked_card = self.value[:3] + "*" * (len(self.value) - 7) + self.value[-4:]
        return masked_card

    def custome(self):
        """
        自定义规则
        :param first_value:
        :param last_value:
        :return:
        """
        return (
            self.value[: self.first_value]
            + "*" * (len(self.value) - (self.first_value + self.last_value))
            + self.value[-self.last_value :]
        )

    def default(self):
        return self.value

    def get_value(self):
        if self.value is None or self.value == "":
            return ""
        fun = self.fun_dict.get(self.mask_type, self.default)
        return fun()


# 加密字段
class EncrypyField(models.TextField):
    def __init__(self, *args, db_collation=None, **kwargs):
        """
        :param args:
        :param db_collation:
        :param kwargs:
        """
        super().__init__(*args, **kwargs)
        self.db_collation = db_collation

    def get_db_prep_value(self, value, connection, prepared=False):
        """写入 DB 前用公钥加密。"""
        try:
            return rsa_util_obj.encrypt_by_public_key(value)
        except Exception as e:
            logger.warning("EncrypyField 加密失败: %s", e)
            return value

    def from_db_value(self, value, expression, connection):
        """从 DB 读出后用私钥解密。"""
        if value:
            try:
                value = rsa_util_obj.decrypt_by_private_key(value)
            except Exception as e:
                logger.warning("EncrypyField 解密失败: %s", e)
        return value
