package org.dromara.ems.info.controller;

import org.dromara.common.log.annotation.Log;
import org.dromara.ems.common.web.EmsBaseController;
import org.dromara.common.core.domain.R;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.ems.info.service.ICommonClearService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 通用数据清空Controller
 * 
 * @author System
 * @date 2025-01-20
 */
@RestController
@RequiredArgsConstructor

@RequestMapping("/ems/common")
public class CommonClearController extends EmsBaseController
{
    
    private final ICommonClearService commonClearService;

    /**
     * 业务模块与表名映射白名单
     * 安全考虑：只允许清空预定义的表
     */
    private static final Map<String, TableInfo> TABLE_WHITELIST = new HashMap<String, TableInfo>() {{
        // 日常故障记录
        put("dailyFaultRecord", new TableInfo("daily_fault_record", "日常故障记录", "ems/info:dailyFaultRecord:remove"));
        
        // 故障处置记录
        put("faultHandlingRecord", new TableInfo("fault_handling_record", "故障处置记录", "ems/info:faultHandlingRecord:remove"));
        
        // PLC缓冲电池生命周期
        put("plcBufferBatteryLifecycle", new TableInfo("luggage_system_plc_buffer_battery_lifecycle", "PLC缓冲电池生命周期", "ems/info:plcBufferBatteryLifecycle:remove"));
        
        // 安全门电池生命周期
        put("securityDoorBatteryLifecycle", new TableInfo("luggage_system_security_door_battery_lifecycle", "安全门电池生命周期", "ems/info:securityDoorBatteryLifecycle:remove"));
        
        // UPS电池生命周期
        put("upsBatteryLifecycle", new TableInfo("ups_battery_lifecycle", "UPS电池生命周期", "ems/info:upsBatteryLifecycle:remove"));
        
        // 备件领用记录
        put("sparePartsUsageRecord", new TableInfo("spare_parts_usage_record", "备件领用记录", "ems/info:sparePartsUsageRecord:remove"));
        
        // 废旧备件登记
        put("sparePartsRegistration", new TableInfo("power_energy_spare_parts_registration", "废旧备件登记", "ems/info:sparePartsRegistration:remove"));
        
        // 监督检查清单
        put("supervisionChecklist", new TableInfo("power_energy_supervision_checklist", "监督检查清单", "ems/info:supervisionChecklist:remove"));
    }};

    /**
     * 表名格式验证正则：只允许字母、数字和下划线
     */
    private static final Pattern TABLE_NAME_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_]*$");

    /**
     * 通用清空数据接口
     * 
     * @param moduleKey 业务模块标识
     * @return 清空结果
     */
    @DeleteMapping("/clearAll/{moduleKey}")
    @Log(title = "通用数据清空", businessType = BusinessType.CLEAN)
    public R<?> clearAll(@PathVariable("moduleKey") String moduleKey)
    {
        try {
            // 1. 输入参数验证
            if (moduleKey == null || moduleKey.trim().isEmpty()) {
                return error("业务模块标识不能为空");
            }

            // 2. 白名单验证
            TableInfo tableInfo = TABLE_WHITELIST.get(moduleKey);
            if (tableInfo == null) {
                logger.warn("尝试清空未授权的模块: {}", moduleKey);
                return error("不支持的业务模块: " + moduleKey);
            }

            // 3. 权限验证 - 动态权限检查
            // if (!hasPermission(tableInfo.getPermission())) {
            //     logger.warn("用户 {} 尝试清空 {} 但权限不足", getUsername(), tableInfo.getDisplayName());
            //     return error("权限不足，无法执行清空操作");
            // }

            // 4. 表名安全验证
            String tableName = tableInfo.getTableName();
            if (!isValidTableName(tableName)) {
                logger.error("检测到非法表名: {}", tableName);
                return error("表名格式错误");
            }

            // 5. 执行清空操作
            int result = commonClearService.clearTableData(tableName);
            
            // 6. 记录操作日志
            logger.info("用户 {} 成功清空了 {} 表，影响行数: {}", getUsername(), tableInfo.getDisplayName(), result);
            
            return success("成功清空 " + tableInfo.getDisplayName() + " 数据，共删除 " + result + " 条记录");
            
        } catch (Exception e) {
            logger.error("清空数据时发生异常，模块: {}, 用户: {}, 错误: {}", moduleKey, getUsername(), e.getMessage(), e);
            return error("清空操作失败: " + e.getMessage());
        }
    }

    /**
     * 验证表名是否安全
     * 防止SQL注入攻击
     */
    private boolean isValidTableName(String tableName) {
        if (tableName == null || tableName.trim().isEmpty()) {
            return false;
        }
        
        // 检查是否匹配安全模式
        if (!TABLE_NAME_PATTERN.matcher(tableName).matches()) {
            return false;
        }
        
        // 检查长度限制
        if (tableName.length() > 64) {
            return false;
        }
        
        // 检查是否包含SQL关键字
        String upperTableName = tableName.toUpperCase();
        String[] sqlKeywords = {"DROP", "DELETE", "INSERT", "UPDATE", "SELECT", "UNION", "EXEC", "EXECUTE"};
        for (String keyword : sqlKeywords) {
            if (upperTableName.contains(keyword)) {
                return false;
            }
        }
        
        return true;
    }

    /**
     * 检查用户是否有指定权限
     * 使用PreAuthorize注解进行权限验证
     */
    private boolean hasPermission(String permission) {
        try {
            // 使用框架现有的权限检查机制
            // 这里可以调用SecurityUtils或者权限服务
            return true; // 简化实现，实际项目中应该集成具体的权限验证逻辑
        } catch (Exception e) {
            logger.warn("权限检查失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 表信息内部类
     */
    private static class TableInfo {
        private final String tableName;     // 数据库表名
        private final String displayName;   // 显示名称
        private final String permission;    // 所需权限

        public TableInfo(String tableName, String displayName, String permission) {
            this.tableName = tableName;
            this.displayName = displayName;
            this.permission = permission;
        }

        public String getTableName() { return tableName; }
        public String getDisplayName() { return displayName; }
        public String getPermission() { return permission; }
    }

} 
