package com.ruoyi.web.modules.technology.service.impl;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.technology.domain.BizPracticalTraining;
import com.ruoyi.web.modules.technology.domain.BizPracticalTrainingMember;
import com.ruoyi.web.modules.technology.domain.PracticalTrainingMyEnrollDetailVo;
import com.ruoyi.web.modules.technology.domain.PracticalTrainingMyEnrollListVo;
import com.ruoyi.web.modules.technology.mapper.BizPracticalTrainingMapper;
import com.ruoyi.web.modules.technology.mapper.BizPracticalTrainingMemberMapper;
import com.ruoyi.web.modules.technology.service.IBizPracticalTrainingAppService;
import com.ruoyi.web.modules.technology.support.PracticalTrainingRules;
import com.ruoyi.web.modules.technology.support.PracticalTrainingStatusSupport;

/**
 * 移动端实战业务培训：我的报名、报名、取消报名。
 */
@Service
public class BizPracticalTrainingAppServiceImpl implements IBizPracticalTrainingAppService
{
    @Autowired
    private BizPracticalTrainingMapper bizPracticalTrainingMapper;

    @Autowired
    private BizPracticalTrainingMemberMapper bizPracticalTrainingMemberMapper;

    @Autowired
    private PracticalTrainingStatusSupport practicalTrainingStatusSupport;

    @Override
    public List<PracticalTrainingMyEnrollListVo> selectMyEnrollList(Long sysUserId)
    {
        if (sysUserId == null)
        {
            return Collections.emptyList();
        }
        List<PracticalTrainingMyEnrollListVo> list = bizPracticalTrainingMemberMapper.selectMyActiveEnrollList(sysUserId);
        if (list == null || list.isEmpty())
        {
            return list != null ? list : Collections.emptyList();
        }
        Date now = new Date();
        for (PracticalTrainingMyEnrollListVo item : list)
        {
            applyRefreshedStatusToListItem(item, now);
        }
        return list;
    }

    @Override
    public PracticalTrainingMyEnrollDetailVo selectMyEnrollDetail(Long trainingId, Long sysUserId)
    {
        if (trainingId == null || sysUserId == null)
        {
            throw new ServiceException("参数不完整");
        }
        PracticalTrainingMyEnrollDetailVo vo = bizPracticalTrainingMemberMapper.selectMyActiveEnrollDetail(trainingId, sysUserId);
        if (vo == null)
        {
            throw new ServiceException("未找到您的报名记录");
        }
        Date now = new Date();
        BizPracticalTraining row = requirePublished(trainingId);
        practicalTrainingStatusSupport.refreshAndPersist(row, now);
        vo.setTrainingStatus(row.getTrainingStatus());
        vo.setTrainingStatusName(PracticalTrainingRules.trainingStatusName(row.getTrainingStatus()));
        vo.setActualEnrolledCount(row.getActualEnrolledCount());
        vo.setCanCancel(Boolean.valueOf(PracticalTrainingRules.canCancelEnrollment(row.getTrainingStatus())));
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int enroll(Long trainingId, Long sysUserId, String memberName, String operator)
    {
        if (trainingId == null || sysUserId == null)
        {
            throw new ServiceException("参数不完整");
        }
        if (StringUtils.isEmpty(memberName))
        {
            throw new ServiceException("成员姓名不能为空");
        }
        BizPracticalTraining row = requirePublished(trainingId);
        Date now = new Date();
        practicalTrainingStatusSupport.refreshAndPersist(row, now);
        if (!PracticalTrainingRules.TRAINING_STATUS_ENROLLING.equals(row.getTrainingStatus()))
        {
            throw new ServiceException("当前培训不可报名");
        }

        BizPracticalTrainingMember existing = bizPracticalTrainingMemberMapper.selectByTrainingIdAndUserId(trainingId, sysUserId);
        if (existing != null && existing.getEnrollStatus() != null
                && existing.getEnrollStatus() == PracticalTrainingRules.MEMBER_ENROLL_ACTIVE)
        {
            throw new ServiceException("您已报名该培训");
        }

        Integer planned = row.getPlannedHeadCount();
        int activeCount = bizPracticalTrainingMemberMapper.countActiveByTrainingId(trainingId);
        if (planned != null && activeCount >= planned)
        {
            practicalTrainingStatusSupport.refreshCountAndPersist(row, activeCount, now);
            throw new ServiceException("名额已满");
        }

        if (existing == null)
        {
            BizPracticalTrainingMember member = new BizPracticalTrainingMember();
            member.setTrainingId(trainingId);
            member.setSysUserId(sysUserId);
            member.setMemberName(memberName.trim());
            member.setEnrollStatus(PracticalTrainingRules.MEMBER_ENROLL_ACTIVE);
            member.setEnrollTime(now);
            member.setCancelTime(null);
            member.setDelFlag(PracticalTrainingRules.DEL_FLAG_NORMAL);
            member.setCreateBy(operator);
            bizPracticalTrainingMemberMapper.insertBizPracticalTrainingMember(member);
        }
        else
        {
            existing.setMemberName(memberName.trim());
            existing.setEnrollStatus(PracticalTrainingRules.MEMBER_ENROLL_ACTIVE);
            existing.setEnrollTime(now);
            existing.setCancelTime(null);
            existing.setUpdateBy(operator);
            bizPracticalTrainingMemberMapper.updateMemberEnrollStatus(existing);
        }

        int newCount = bizPracticalTrainingMemberMapper.countActiveByTrainingId(trainingId);
        practicalTrainingStatusSupport.refreshCountAndPersist(row, newCount, now);
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cancelEnroll(Long trainingId, Long sysUserId, String operator)
    {
        if (trainingId == null || sysUserId == null)
        {
            throw new ServiceException("参数不完整");
        }
        BizPracticalTrainingMember existing = bizPracticalTrainingMemberMapper.selectByTrainingIdAndUserId(trainingId, sysUserId);
        if (existing == null || existing.getEnrollStatus() == null
                || existing.getEnrollStatus() != PracticalTrainingRules.MEMBER_ENROLL_ACTIVE)
        {
            throw new ServiceException("您未报名该培训");
        }

        BizPracticalTraining row = requirePublished(trainingId);
        Date now = new Date();
        practicalTrainingStatusSupport.refreshAndPersist(row, now);
        if (!PracticalTrainingRules.canCancelEnrollment(row.getTrainingStatus()))
        {
            throw new ServiceException("报名已截止，不允许取消报名");
        }

        existing.setEnrollStatus(PracticalTrainingRules.MEMBER_ENROLL_CANCELLED);
        existing.setCancelTime(now);
        existing.setUpdateBy(operator);
        bizPracticalTrainingMemberMapper.updateMemberEnrollStatus(existing);

        int newCount = bizPracticalTrainingMemberMapper.countActiveByTrainingId(trainingId);
        practicalTrainingStatusSupport.refreshCountAndPersist(row, newCount, now);
        return 1;
    }

    private void applyRefreshedStatusToListItem(PracticalTrainingMyEnrollListVo item, Date now)
    {
        if (item == null || item.getId() == null)
        {
            return;
        }
        BizPracticalTraining row = bizPracticalTrainingMapper.selectPublishedBizPracticalTrainingById(item.getId());
        if (row == null)
        {
            return;
        }
        practicalTrainingStatusSupport.refreshAndPersist(row, now);
        item.setTrainingStatus(row.getTrainingStatus());
        item.setTrainingStatusName(PracticalTrainingRules.trainingStatusName(row.getTrainingStatus()));
        item.setActualEnrolledCount(row.getActualEnrolledCount());
    }

    private BizPracticalTraining requirePublished(Long id)
    {
        BizPracticalTraining row = bizPracticalTrainingMapper.selectPublishedBizPracticalTrainingById(id);
        if (row == null)
        {
            throw new ServiceException("培训不存在或未发布");
        }
        return row;
    }
}
