package com.zsElectric.boot.common.util;

import lombok.Getter;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 基于时间戳的4位自增序列和时间戳生成器
 * 规则：同一秒内序列号自增（0001-9999），下一秒序列重置为0001
 *
 * @author: wzq
 * @date: 2025/11/12
 */
public class SequenceGenUtil {

    private static final AtomicInteger currentSequence = new AtomicInteger(0);
    private static volatile long lastSecond = -1L;
    private static final int MAX_SEQUENCE = 9999;

    // 时间格式化器（线程安全）
    private static final DateTimeFormatter TIMESTAMP_FORMATTER =
            DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    /**
     * 序列号生成结果对象
     */
    @Getter
    public static class SequenceResult {
        private final String sequence;      // 4位序列号，如 "0001"
        private final String timestamp;     // 时间戳，如 "20251112154530"

        public SequenceResult(String sequence, String timestamp) {
            this.sequence = sequence;
            this.timestamp = timestamp;
        }

        /**
         * 获取完整编号：时间戳 + 序列号
         */
        public String getFullNumber() {
            return timestamp + sequence;
        }

        @Override
        public String toString() {
            return "SequenceResult{sequence='" + sequence + "', timestamp='" + timestamp + "'}";
        }
    }

    /**
     * 生成序列号和时间戳
     * 使用synchronized确保线程安全
     */
    public static synchronized SequenceResult generate() {
        long currentSecond = getCurrentSecond();
        String currentTimestamp = formatTimestamp(currentSecond);

        // 检查是否是新的一秒
        if (currentSecond != lastSecond) {
            currentSequence.set(0);
            lastSecond = currentSecond;
        }

        // 获取下一个序列值
        int seq = currentSequence.incrementAndGet();

        // 检查序列号是否溢出
        if (seq > MAX_SEQUENCE) {
            waitForNextSecond(currentSecond);
            // 递归调用，进入新秒后重新生成
            return generate();
        }

        // 格式化为4位数字并返回结果对象
        String sequenceStr = String.format("%04d", seq);
        return new SequenceResult(sequenceStr, currentTimestamp);
    }

    /**
     * 仅生成4位序列号（保持原有功能）
     */
    public static synchronized String generateSequenceOnly() {
        return generate().getSequence();
    }

    /**
     * 生成完整编号（时间戳+序列号）
     */
    public static synchronized String generateFullNumber() {
        return generate().getFullNumber();
    }

    /**
     * 获取当前时间的秒级时间戳
     */
    private static long getCurrentSecond() {
        return System.currentTimeMillis() / 1000;
    }

    /**
     * 将秒级时间戳格式化为 yyyyMMddHHmmss
     */
    private static String formatTimestamp(long timestampInSeconds) {
        LocalDateTime dateTime = LocalDateTime.ofEpochSecond(timestampInSeconds, 0,
                java.time.ZoneOffset.UTC);
        // 调整时区为系统默认时区
        return dateTime.atZone(java.time.ZoneId.systemDefault()).format(TIMESTAMP_FORMATTER);
    }

    /**
     * 等待下一秒（当序列号溢出时调用）
     */
    private static void waitForNextSecond(long currentSecond) {
        while (getCurrentSecond() <= currentSecond) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("序列生成器等待被中断", e);
            }
        }
    }

    /**
     * 重置生成器状态（主要用于测试）
     */
    public static synchronized void reset() {
        lastSecond = -1L;
        currentSequence.set(0);
    }

    public static void main(String[] args) {
        System.out.println("=== 生成序列号和时间戳 ===");

        // 生成完整的序列结果（包含序列号和时间戳）
        SequenceGenUtil.SequenceResult result1 = SequenceGenUtil.generate();
        System.out.println("序列号: " + result1.getSequence());     // 输出: 0001
        System.out.println("时间戳: " + result1.getTimestamp());    // 输出: 20251112154530
        System.out.println("完整编号: " + result1.getFullNumber()); // 输出: 202511121545300001
        System.out.println("完整对象: " + result1.toString());

        // 同一秒内连续生成
        System.out.println("\n=== 同一秒内连续生成 ===");
        for (int i = 0; i < 3; i++) {
            SequenceGenUtil.SequenceResult result = SequenceGenUtil.generate();
            System.out.println("时间戳: " + result.getTimestamp() + ", 序列号: " + result.getSequence());
        }

        // 仅生成序列号（保持原有功能）
        System.out.println("\n=== 仅生成序列号 ===");
        String sequenceOnly = SequenceGenUtil.generateSequenceOnly();
        System.out.println("仅序列号: " + sequenceOnly);

        // 生成完整编号
        System.out.println("\n=== 生成完整编号 ===");
        String fullNumber = SequenceGenUtil.generateFullNumber();
        System.out.println("完整编号: " + fullNumber);

        // 模拟跨秒生成
        System.out.println("\n=== 模拟跨秒生成 ===");
        SequenceGenUtil.SequenceResult beforeSleep = SequenceGenUtil.generate();
        System.out.println("休眠前: " + beforeSleep.getTimestamp() + " - " + beforeSleep.getSequence());

        try {
            Thread.sleep(1000); // 等待1秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        SequenceGenUtil.SequenceResult afterSleep = SequenceGenUtil.generate();
        System.out.println("休眠后: " + afterSleep.getTimestamp() + " - " + afterSleep.getSequence());
    }
}