package cn.iocoder.yudao.module.system.service.logger;

import cn.iocoder.yudao.module.system.dal.dataobject.logger.DatabaseOperateLogDO;
import cn.iocoder.yudao.module.system.dal.mysql.logger.DatabaseOperateLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 数据库操作日志 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
@Slf4j
public class DatabaseOperateLogServiceImpl implements DatabaseOperateLogService {

    @Resource
    private DatabaseOperateLogMapper databaseOperateLogMapper;

    @Resource
    private JdbcTemplate jdbcTemplate;

    /**
     * 缓存最近一次初始化的月份表，避免每次都执行 CREATE TABLE
     */
    private final AtomicReference<String> cachedMonthTable = new AtomicReference<>();

    @Override
    @Async
    public void createDatabaseOperateLog(DatabaseOperateLogDO dbLog) {
        try {
            // 1. 计算当月表名：system_database_operate_log_yyyyMM
            String tableName = buildMonthTableName();

            // 2. 确保当月表只初始化一次
            ensureTableExistsOncePerMonth(tableName);

            // 3. 插入当前月表
            databaseOperateLogMapper.insertLog(tableName, dbLog);
        } catch (Exception e) {
            log.error("保存数据库操作日志失败", e);
        }
    }

    /**
     * 构造当月物理表名：system_database_operate_log_yyyyMM
     */
    private String buildMonthTableName() {
        LocalDateTime now = LocalDateTime.now();
        String suffix = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
        return "system_database_operate_log_" + suffix;
    }

    /**
     * 每个月只建一次表：system_database_operate_log_yyyyMM
     */
    private void ensureTableExistsOncePerMonth(String tableName) {
        String cached = cachedMonthTable.get();
        if (tableName.equals(cached)) {
            return;
        }
        synchronized (this) {
            cached = cachedMonthTable.get();
            if (!tableName.equals(cached)) {
                String createSql = "CREATE TABLE IF NOT EXISTS " + tableName +
                        " LIKE system_database_operate_log";
                jdbcTemplate.execute(createSql);
                cachedMonthTable.set(tableName);
            }
        }
    }

}
