package com.sundot.airport.exam.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.sundot.airport.common.exception.ServiceException;
import com.sundot.airport.common.utils.SecurityUtils;
import com.sundot.airport.exam.domain.WeakModuleRule;
import com.sundot.airport.exam.dto.WeakModuleRuleDTO;
import com.sundot.airport.exam.mapper.WeakModuleRuleMapper;
import com.sundot.airport.exam.service.IWeakModuleRuleService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * <b>功能名：</b>WeakModuleRuleServiceImpl<br>
 * <b>说明：</b> 薄弱项出题规则配置Service实现 <br>
 * <b>著作权：</b> Copyright (C) 2025 SUNDOT CORPORATION<br>
 * <b>修改履历：
 *
 * @author Simon Lin
 */
@Service
public class WeakModuleRuleServiceImpl implements IWeakModuleRuleService {

    @Autowired
    private WeakModuleRuleMapper weakModuleRuleMapper;

    @Override
    public WeakModuleRule getActiveRule() {
        LambdaQueryWrapper<WeakModuleRule> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WeakModuleRule::getWmrEnableStatus, true);
        wrapper.eq(WeakModuleRule::getDelStatus, 0);
        wrapper.orderByDesc(WeakModuleRule::getCreateTime);
        wrapper.last("LIMIT 1");

        return weakModuleRuleMapper.selectOne(wrapper);
    }

    @Override
    public List<WeakModuleRule> list() {
        LambdaQueryWrapper<WeakModuleRule> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WeakModuleRule::getDelStatus, 0);
        wrapper.orderByDesc(WeakModuleRule::getCreateTime);

        return weakModuleRuleMapper.selectList(wrapper);
    }

    @Override
    public WeakModuleRule getById(Long id) {
        LambdaQueryWrapper<WeakModuleRule> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WeakModuleRule::getId, id);
        wrapper.eq(WeakModuleRule::getDelStatus, 0);

        return weakModuleRuleMapper.selectOne(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(WeakModuleRuleDTO dto) {
        // 数据校验
        validateRuleData(dto);

        WeakModuleRule rule = new WeakModuleRule();
        BeanUtils.copyProperties(dto, rule);

        // 设置业务主键
        rule.setWmrId(IdUtil.getSnowflakeNextIdStr());

        // 设置通用字段
        rule.setDelStatus(0);
        rule.setCreateTime(new Date());
        rule.setCreateUid(SecurityUtils.getUserId().toString());

        // 如果是启用状态，先禁用其他规则
        if (Boolean.TRUE.equals(dto.getWmrEnableStatus())) {
            disableAllRules();
        } else {
            rule.setWmrEnableStatus(false);
        }

        return weakModuleRuleMapper.insert(rule);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(WeakModuleRuleDTO dto) {
        if (dto.getId() == null) {
            throw new ServiceException("规则ID不能为空");
        }

        // 检查规则是否存在
        WeakModuleRule existingRule = getById(dto.getId());
        if (existingRule == null) {
            throw new ServiceException("规则不存在");
        }

        // 数据校验
        validateRuleData(dto);

        WeakModuleRule rule = new WeakModuleRule();
        BeanUtils.copyProperties(dto, rule);

        // 设置更新字段
        rule.setUpdateTime(new Date());
        rule.setUpdateUid(SecurityUtils.getUserId().toString());

        // 如果是启用状态，先禁用其他规则
        if (Boolean.TRUE.equals(dto.getWmrEnableStatus())) {
            disableAllRules();
        }

        return weakModuleRuleMapper.updateById(rule);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteById(Long id) {
        WeakModuleRule existingRule = getById(id);
        if (existingRule == null) {
            throw new ServiceException("规则不存在");
        }

        // 逻辑删除
        WeakModuleRule rule = new WeakModuleRule();
        rule.setId(id);
        rule.setDelStatus(1);
        rule.setUpdateTime(new Date());
        rule.setUpdateUid(SecurityUtils.getUserId().toString());

        return weakModuleRuleMapper.updateById(rule);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int enable(Long id) {
        WeakModuleRule existingRule = getById(id);
        if (existingRule == null) {
            throw new ServiceException("规则不存在");
        }

        // 先禁用所有规则
        disableAllRules();

        // 启用指定规则
        WeakModuleRule rule = new WeakModuleRule();
        rule.setId(id);
        rule.setWmrEnableStatus(true);
        rule.setUpdateTime(new Date());
        rule.setUpdateUid(SecurityUtils.getUserId().toString());

        return weakModuleRuleMapper.updateById(rule);
    }

    /**
     * 禁用所有规则
     */
    private void disableAllRules() {
        // 查询所有启用的规则
        LambdaQueryWrapper<WeakModuleRule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WeakModuleRule::getDelStatus, 0);
        queryWrapper.eq(WeakModuleRule::getWmrEnableStatus, true);
        List<WeakModuleRule> enabledRules = weakModuleRuleMapper.selectList(queryWrapper);

        // 逐个禁用
        if (enabledRules != null && !enabledRules.isEmpty()) {
            Date now = new Date();
            String userId = SecurityUtils.getUserId().toString();

            for (WeakModuleRule rule : enabledRules) {
                WeakModuleRule updateRule = new WeakModuleRule();
                updateRule.setId(rule.getId());
                updateRule.setWmrEnableStatus(false);
                updateRule.setUpdateTime(now);
                updateRule.setUpdateUid(userId);

                weakModuleRuleMapper.updateById(updateRule);
            }
        }
    }

    /**
     * 校验规则数据
     */
    private void validateRuleData(WeakModuleRuleDTO dto) {
        // 1. 校验权重之和是否为1
        BigDecimal weightSum = dto.getWmrWrongAnswerWeight().add(dto.getWmrCheckProblemWeight());
        if (weightSum.compareTo(BigDecimal.ONE) != 0) {
            throw new ServiceException("错题权重和巡检问题权重之和必须等于1");
        }

        // 2. 校验TOP3占比之和不能超过1
        BigDecimal ratioSum = dto.getWmrTop1Ratio()
                .add(dto.getWmrTop2Ratio())
                .add(dto.getWmrTop3Ratio());
        if (ratioSum.compareTo(BigDecimal.ONE) > 0) {
            throw new ServiceException("TOP3薄弱模块占比之和不能超过100%");
        }

        // 3. 校验占比大小关系：TOP1 >= TOP2 >= TOP3
        if (dto.getWmrTop1Ratio().compareTo(dto.getWmrTop2Ratio()) < 0) {
            throw new ServiceException("第1薄弱模块占比应该大于等于第2薄弱模块占比");
        }
        if (dto.getWmrTop2Ratio().compareTo(dto.getWmrTop3Ratio()) < 0) {
            throw new ServiceException("第2薄弱模块占比应该大于等于第3薄弱模块占比");
        }
    }
}
