package com.liquidnet.common.third.secureaccess.util;

import com.liquidnet.common.third.secureaccess.model.NiaPidParsed;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;

/**
 * PID 解析与 openId 编码，与网证官方说明一致：
 * <pre>
 * byte[] raw = Base64.getDecoder().decode(pid);
 * System.arraycopy(raw, 1, identifier, 0, 40);
 * </pre>
 * 存库 openId 取 40 字节标识的<strong>标准 Base64</strong>（56 字符，可放进 varchar(64)）。
 */
public final class NiaPidUtils {

    public static final int IDENTIFIER_BYTE_LEN = 40;
    /** 标准 Base64（含填充）固定 56 字符 */
    public static final int OPEN_ID_LEN = 56;

    private static final Decoder JDK_BASE64_DECODER = java.util.Base64.getDecoder();
    private static final Encoder JDK_BASE64_ENCODER = java.util.Base64.getEncoder();
    private static final int TIMESTAMP_LEN = 14;
    private static final int MIN_PID_LEN = 1 + IDENTIFIER_BYTE_LEN + TIMESTAMP_LEN;

    private NiaPidUtils() {
    }

    public static NiaPidParsed parse(String pidBase64) {
        if (StringUtils.isBlank(pidBase64)) {
            return null;
        }
        byte[] raw;
        try {
            raw = JDK_BASE64_DECODER.decode(pidBase64.trim());
        } catch (IllegalArgumentException ex) {
            return null;
        }
        if (raw.length < MIN_PID_LEN) {
            return null;
        }
        int version = raw[0] & 0xFF;

        byte[] identifier = new byte[IDENTIFIER_BYTE_LEN];
        System.arraycopy(raw, 1, identifier, 0, IDENTIFIER_BYTE_LEN);

        byte[] tsBytes = new byte[TIMESTAMP_LEN];
        System.arraycopy(raw, 1 + IDENTIFIER_BYTE_LEN, tsBytes, 0, TIMESTAMP_LEN);
        String timestamp = new String(tsBytes, StandardCharsets.US_ASCII);
        if (!timestamp.matches("\\d{14}")) {
            return null;
        }

        byte[] signature = new byte[raw.length - MIN_PID_LEN];
        if (signature.length > 0) {
            System.arraycopy(raw, MIN_PID_LEN, signature, 0, signature.length);
        }

        return NiaPidParsed.builder()
                .totalLen(raw.length)
                .version(version)
                .identifier(identifier)
                .timestamp(timestamp)
                .signature(signature)
                .build();
    }

    /** 40 字节标识 → 标准 Base64（56 字符） */
    public static String extractOpenId(String pid) {
        NiaPidParsed parsed = parse(pid);
        if (parsed == null || parsed.getIdentifier() == null) {
            return null;
        }
        return encodeOpenId(parsed.getIdentifier());
    }

    public static String encodeOpenId(byte[] identifier) {
        if (identifier == null || identifier.length != IDENTIFIER_BYTE_LEN) {
            return null;
        }
        return JDK_BASE64_ENCODER.encodeToString(identifier);
    }

    /** 日志排查用：40 字节标识 → 大写 hex */
    public static String toHex(byte[] identifier) {
        if (identifier == null || identifier.length != IDENTIFIER_BYTE_LEN) {
            return null;
        }
        return Hex.encodeHexString(identifier).toUpperCase();
    }

    public static byte[] toIdentifierBytes(String openId) {
        if (StringUtils.isBlank(openId)) {
            return null;
        }
        try {
            byte[] decoded = JDK_BASE64_DECODER.decode(openId.trim());
            return decoded.length == IDENTIFIER_BYTE_LEN ? decoded : null;
        } catch (IllegalArgumentException ex) {
            return null;
        }
    }

    public static boolean isValidOpenId(String openId) {
        if (StringUtils.isBlank(openId) || openId.length() != OPEN_ID_LEN) {
            return false;
        }
        return toIdentifierBytes(openId) != null;
    }

    public static String maskPid(String pid) {
        if (StringUtils.isBlank(pid)) {
            return null;
        }
        if (pid.length() <= 16) {
            return "***";
        }
        return pid.substring(0, 8) + "..." + pid.substring(pid.length() - 8);
    }
}
