package com.ruoyi.common.config.serializer;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.ruoyi.common.annotation.CustomSensitive;
import com.ruoyi.common.enums.SensitiveType;
import com.ruoyi.common.utils.StringUtils;

import java.io.IOException;
import java.util.Objects;

/**
 * 数据回显前端前的数据脱敏序列化实现类
 */
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {

    private SensitiveType type;
    private int prefix;
    private int suffix;

    public SensitiveSerialize() {}

    public SensitiveSerialize(SensitiveType type, int prefix, int suffix) {
        this.type = type;
        this.prefix = prefix;
        this.suffix = suffix;
    }

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers)
            throws IOException {
        if (StringUtils.isBlank(value)) {
            gen.writeString(value);
            return;
        }

        String result;
        switch (type) {
            case CHINESE_NAME:
                result = desensitizeChineseName(value);
                break;
            case ENGLISH_NAME:
                result = desensitizeEnglishName(value);
                break;
            case ID_CARD:
                result = desensitizeIdCard(value);
                break;
            case PHONE:
                result = desensitizePhone(value);
                break;
            case EMAIL:
                result = desensitizeEmail(value);
                break;
            case BANK_CARD:
                result = desensitizeBankCard(value);
                break;
            case LIVE_ADDRESS:
                result = desensitizeLiveAddress(value);
                break;
            case CUSTOM:
                result = desensitizeCustom(value, prefix, suffix);
                break;
            default:
                result = desensitizeDefault(value);
        }
        gen.writeString(result);
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
            throws JsonMappingException
    {
        CustomSensitive annotation = property.getAnnotation(CustomSensitive.class);
        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
        {
            this.type = annotation.type();
            return this;
        }
        return prov.findValueSerializer(property.getType(), property);
    }

    public String desensitizeChineseName(String name) {
        if (name.length() <= 1) return name;
        String str = "";
        for(int i = 0; i < name.length()-1; i++) {
            str = str+"*";
        }
        return str+name.charAt(name.length()-1);
    }

    public String desensitizeEnglishName(String fullName) {
        // 先 trim 再按一个或多个空格分段
        String[] parts = fullName.trim().split("\\s+");
        if (parts.length < 2) {
            return fullName.trim();          // 只有一段，保持原样
        }
        // 脱敏第一段
        String first = parts[0];
        if (first.length() == 1) {
            parts[0] = "*";                  // 单字符直接变 *
        } else {
            char last = first.charAt(first.length() - 1);
            StringBuilder sb = new StringBuilder(first.length());
            for (int i = 0; i < first.length() - 1; i++) {
                sb.append('*');
            }
            sb.append(last);
            parts[0] = sb.toString();
        }
        // 用单个空格重新拼接
        return String.join(" ", parts);
    }

    public String desensitizeIdCard(String idCard) {
        String str = "";
        for (int i = 0; i < idCard.length(); i++) {
            if(i < 1 || i > idCard.length()-2) {
                str = str+idCard.charAt(i);
            }else{
                str = str+"*";
            }

        }
        return str;
    }

    public String desensitizePhone(String phone) {
        String str = "";
        for (int i = 0; i < phone.length(); i++) {
            if(i < 3 || i > phone.length()-3) {
                str = str+phone.charAt(i);
            }else{
                str = str+"*";
            }

        }
        return str;
    }

    public String desensitizeEmail(String email) {
        int atIndex = email.indexOf("@");
        if(atIndex > -1){
            String[] strs = email.split("@");
            String str = "";
            for (int i = 0; i < strs[0].length(); i++) {
                str = str+"*";
            }
            str = str+"@"+strs[1];
            return str;
        }else{
            return email;
        }
    }

    public String desensitizeBankCard(String bankCard) {
        String str = "";
        for (int i = 0; i < bankCard.length(); i++) {
            if(i > bankCard.length()-5) {
                str = str+bankCard.charAt(i);
            }else{
                str = str+"*";
            }
        }
        return str;
    }

    public String desensitizeCustom(String value, int prefix, int suffix) {
        if (value.length() <= prefix + suffix) return value;
        String prefixStr = value.substring(0, prefix);
        String suffixStr = suffix > 0 ? value.substring(value.length() - suffix) : "";
        int maskLength = value.length() - prefix - suffix;
        String mask = StringUtils.repeat('*', maskLength);
        return prefixStr + mask + suffixStr;
    }

    public String desensitizeLiveAddress(String value) {
        int length = value.length();
        int num = 0;
        if(length >= 12){
            num = 6;
        }else{
            num = (int) Math.floor(length/2f);
        }
        value = value.substring(0,num)+"********";
        return value;
    }

    public String desensitizeDefault(String value) {
        if (value.length() <= 2){
            return value.substring(0, 1) + "*";
        };
        if(value.length() > 2 && value.length() < 9){
            return value.substring(0, 1) + "*" + value.substring(value.length() - 1);
        }
        if(value.length()%3 == 0){
            int num = value.length()/3;
            return value.substring(0, num) + "*" + value.substring(value.length() - num);
        }else{
            double num = Math.floor(value.length()/3f);
            String number = String.format("%.0f",num);
            return value.substring(0, Integer.parseInt(number)+1) + "*" + value.substring(value.length()-Integer.parseInt(number));
        }
    }

}
