package com.ruoyi.ems.service.impl;


import com.huashe.common.utils.DateUtils;
import com.ruoyi.ems.domain.DeviceLedger;
import com.ruoyi.ems.mapper.DeviceLedgerMapper;
import com.ruoyi.ems.service.IDeviceLedgerService;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 设备台账Service业务层处理
 *
 * @author ruoyi
 * @date 2024-09-10
 */
@Service
public class DeviceLedgerServiceImpl implements IDeviceLedgerService {

    private static final Logger log = LoggerFactory.getLogger(DeviceLedgerServiceImpl.class);

    @Autowired
    private DeviceLedgerMapper deviceLedgerMapper;

    /**
     * 查询设备台账
     *
     * @param id 设备台账主键
     * @return 设备台账
     */
    @Override
    public DeviceLedger selectDeviceLedgerById(Long id) {
        return deviceLedgerMapper.selectDeviceLedgerById(id);
    }

    /**
     * 查询设备台账列表
     *
     * @param deviceLedger 设备台账
     * @return 设备台账
     */
    @Override
    public List<DeviceLedger> selectDeviceLedgerList(DeviceLedger deviceLedger) {
        return deviceLedgerMapper.selectDeviceLedgerList(deviceLedger);
    }

    /**
     * 新增设备台账
     * 自动生成台账编号
     *
     * @param deviceLedger 设备台账
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertDeviceLedger(DeviceLedger deviceLedger) {
        // 自动生成台账编号
        if (StringUtils.isEmpty(deviceLedger.getRecordCode())) {
            String recordCode = generateUniqueRecordCode();
            deviceLedger.setRecordCode(recordCode);
            log.info("自动生成台账编号: {}", recordCode);
        }

        // 设置创建时间
        deviceLedger.setCreateTime(DateUtils.getNowDate());

        return deviceLedgerMapper.insertDeviceLedger(deviceLedger);
    }

    /**
     * 生成唯一的台账编号
     * 如果生成的编号已存在，则重新生成
     *
     * @return 唯一的台账编号
     */
    private String generateUniqueRecordCode() {
        String recordCode;
        int maxRetries = 10;
        int retries = 0;

        do {
            recordCode = LedgerCodeGenerator.generate();
            // 检查是否已存在
            DeviceLedger query = new DeviceLedger();
            query.setRecordCode(recordCode);
            List<DeviceLedger> existing = deviceLedgerMapper.selectDeviceLedgerList(query);
            if (existing == null || existing.isEmpty()) {
                return recordCode;
            }
            retries++;
            log.warn("台账编号 {} 已存在，重新生成 (尝试 {}/{})", recordCode, retries, maxRetries);
        } while (retries < maxRetries);

        // 如果多次重试仍失败，使用时间戳作为后缀
        return recordCode + System.currentTimeMillis() % 1000;
    }

    /**
     * 修改设备台账
     *
     * @param deviceLedger 设备台账
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDeviceLedger(DeviceLedger deviceLedger) {
        deviceLedger.setUpdateTime(DateUtils.getNowDate());
        return deviceLedgerMapper.updateDeviceLedger(deviceLedger);
    }

    /**
     * 批量删除设备台账
     *
     * @param ids 需要删除的设备台账主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteDeviceLedgerByIds(Long[] ids) {
        return deviceLedgerMapper.deleteDeviceLedgerByIds(ids);
    }

    /**
     * 删除设备台账信息
     *
     * @param id 设备台账主键
     * @return 结果
     */
    @Override
    public int deleteDeviceLedgerById(Long id) {
        return deviceLedgerMapper.deleteDeviceLedgerById(id);
    }

    /**
     * 根据记录编号查询台账
     *
     * @param recordCode 记录编号
     * @return 设备台账
     */
    public DeviceLedger selectDeviceLedgerByRecordCode(String recordCode) {
        DeviceLedger query = new DeviceLedger();
        query.setRecordCode(recordCode);
        List<DeviceLedger> list = deviceLedgerMapper.selectDeviceLedgerList(query);
        return list != null && !list.isEmpty() ? list.get(0) : null;
    }

    /**
     * 根据对象类型和对象代码查询台账列表
     *
     * @param objType 对象类型
     * @param objCode 对象代码
     * @return 台账列表
     */
    public List<DeviceLedger> selectDeviceLedgerByObj(Long objType, String objCode) {
        DeviceLedger query = new DeviceLedger();
        query.setObjType(objType);
        query.setObjCode(objCode);
        return deviceLedgerMapper.selectDeviceLedgerList(query);
    }
}

class LedgerCodeGenerator {

    private static final String PREFIX = "TZ";
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");

    // 当前日期
    private static String currentDate = "";
    // 当日序号计数器
    private static final AtomicInteger counter = new AtomicInteger(0);

    /**
     * 生成台账编号
     * 线程安全的编号生成
     *
     * @return 台账编号 格式: TZ202601150001
     */
    public static synchronized String generate() {
        String today = DATE_FORMAT.format(new Date());

        // 如果日期变化，重置计数器
        if (!today.equals(currentDate)) {
            currentDate = today;
            counter.set(0);
        }

        int seq = counter.incrementAndGet();
        return String.format("%s%s%04d", PREFIX, today, seq);
    }

    /**
     * 根据指定日期生成台账编号
     *
     * @param date 日期
     * @param sequence 序号
     * @return 台账编号
     */
    public static String generate(Date date, int sequence) {
        String dateStr = DATE_FORMAT.format(date);
        return String.format("%s%s%04d", PREFIX, dateStr, sequence);
    }

    /**
     * 验证台账编号格式是否正确
     *
     * @param recordCode 台账编号
     * @return 是否有效
     */
    public static boolean isValid(String recordCode) {
        if (recordCode == null || recordCode.length() != 14) {
            return false;
        }
        if (!recordCode.startsWith(PREFIX)) {
            return false;
        }
        try {
            // 验证日期部分
            String datePart = recordCode.substring(2, 10);
            DATE_FORMAT.parse(datePart);
            // 验证序号部分
            String seqPart = recordCode.substring(10);
            Integer.parseInt(seqPart);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 从台账编号中提取日期
     *
     * @param recordCode 台账编号
     * @return 日期字符串 yyyyMMdd
     */
    public static String extractDate(String recordCode) {
        if (!isValid(recordCode)) {
            return null;
        }
        return recordCode.substring(2, 10);
    }

    /**
     * 从台账编号中提取序号
     *
     * @param recordCode 台账编号
     * @return 序号
     */
    public static Integer extractSequence(String recordCode) {
        if (!isValid(recordCode)) {
            return null;
        }
        return Integer.parseInt(recordCode.substring(10));
    }
}
