package com.usky.vpp.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.usky.common.core.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;

import java.util.regex.Pattern;

/**
 * VPP 字段校验工具类
 *
 * @author fyc
 * @email yuchuan.fu@chinausky.com
 * @date 2026/7/4
 */
public final class VppFieldValidator {

    /**
     * templateCode 校验正则：仅允许大写英文字母，长度 1~5
     */
    private static final Pattern TEMPLATE_CODE_PATTERN = Pattern.compile("^[A-Z]{1,5}$");

    /**
     * 中国大陆手机号正则：1 开头，第二位 3-9，共 11 位数字
     */
    private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");

    /**
     * 邮箱正则
     */
    private static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    /** JSON 字符串最大长度：64KB，防止大 JSON DoS 攻击 */
    private static final int JSON_MAX_LENGTH = 65536;

    private VppFieldValidator() {
        // 工具类禁止实例化
    }

    /**
     * 校验并规范化模板编码 templateCode：
     * <ul>
     *   <li>不允许为空白</li>
     *   <li>最大长度不超过 5 个字符</li>
     *   <li>仅允许大写英文字母（A-Z）</li>
     * </ul>
     *
     * @param templateCode 原始模板编码
     * @throws BusinessException 校验不通过时抛出
     */
    public static void validateTemplateCode(String templateCode) {
        if (StringUtils.isBlank(templateCode)) {
            throw new BusinessException("模板编码不能为空！");
        }
        if (!TEMPLATE_CODE_PATTERN.matcher(templateCode).matches()) {
            throw new BusinessException("模板编码格式错误：仅允许大写英文字母(A-Z)，且长度不超过5个字符！");
        }
    }

    /**
     * 校验 JSON 格式字符串的合法性：
     * <ul>
     *   <li>null 或空字符串：视为合法，返回 null</li>
     *   <li>非空时：长度 ≤ 64KB，且必须为合法的 JSON 对象（{...}）</li>
     *   <li>数组（[...]）、原始值（字符串/数字/布尔/null）均不通过</li>
     * </ul>
     *
     * @param json      待校验的 JSON 字符串
     * @param fieldName 字段名称（用于错误提示）
     * @return 规范化后的值：null → null；合法 JSON 对象 → 原值
     * @throws BusinessException 超出长度限制或 JSON 格式不合法时抛出
     */
    public static String validateJson(String json, String fieldName) {
        if (json == null || json.trim().isEmpty()) {
            return null;
        }
        if (json.length() > JSON_MAX_LENGTH) {
            throw new BusinessException(fieldName + "内容过大，最大支持64KB！");
        }
        try {
            JsonNode node = OBJECT_MAPPER.readTree(json);
            if (!node.isObject()) {
                throw new BusinessException(fieldName + "格式错误：必须是JSON对象({})格式，不允许数组或原始值！");
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            throw new BusinessException(fieldName + "格式错误：不是合法的JSON格式，请检查！");
        }
        return json;
    }

    /**
     * 根据模板编码生成合同编号，格式：{templateCode}-{13位毫秒时间戳}
     * <p>示例：templateCode=CG → CG-1783154814855</p>
     *
     * @param templateCode 模板编码
     * @return 合同编号
     */
    public static String generateContractNo(String templateCode) {
        return templateCode + "-" + System.currentTimeMillis();
    }

    /**
     * 校验中国大陆手机号：
     * <ul>
     *   <li>不允许为空</li>
     *   <li>1 开头，第二位 3-9，共 11 位数字</li>
     * </ul>
     *
     * @param phone 手机号码
     * @throws BusinessException 校验不通过时抛出
     */
    public static void validatePhone(String phone) {
        if (StringUtils.isBlank(phone)) {
            throw new BusinessException("手机号码不能为空！");
        }
        if (!PHONE_PATTERN.matcher(phone.trim()).matches()) {
            throw new BusinessException("手机号码格式不正确！");
        }
    }

    /**
     * 校验邮箱格式：
     * <ul>
     *   <li>不允许为空</li>
     *   <li>必须符合基本邮箱格式</li>
     * </ul>
     *
     * @param email 邮箱地址
     * @throws BusinessException 校验不通过时抛出
     */
    public static void validateEmail(String email) {
        if (StringUtils.isBlank(email)) {
            throw new BusinessException("邮箱不能为空！");
        }
        if (!EMAIL_PATTERN.matcher(email.trim()).matches()) {
            throw new BusinessException("邮箱格式不正确！");
        }
    }
}
