package com.lesingle.creation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lesingle.creation.common.enums.RegistrationStateEnum;
import com.lesingle.creation.common.enums.ContestStateEnum;
import com.lesingle.creation.dto.registration.*;
import com.lesingle.creation.entity.*;
import com.lesingle.creation.common.exception.BusinessException;
import com.lesingle.creation.mapper.*;
import com.lesingle.creation.service.ContestRegistrationService;
import com.lesingle.creation.vo.registration.RegistrationStatsVO;
import com.lesingle.creation.vo.registration.RegistrationVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 竞赛报名服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ContestRegistrationServiceImpl implements ContestRegistrationService {

    private final ContestRegistrationMapper registrationMapper;
    private final ContestMapper contestMapper;
    private final UserMapper userMapper;
    private final ContestTeamMapper teamMapper;
    private final ContestTeamMemberMapper teamMemberMapper;
    private final ContestWorkMapper workMapper;
    private final ContestRegistrationTeacherMapper teacherMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RegistrationVO create(CreateRegistrationDTO dto, Long tenantId, Long creatorId) {
        // 验证活动是否存在
        Contest contest = contestMapper.selectById(dto.getContestId());
        if (contest == null) {
            throw new BusinessException("活动不存在");
        }

        // 检查活动是否已发布
        if (!ContestStateEnum.PUBLISHED.getCode().equals(contest.getContestState())) {
            throw new BusinessException("活动未发布，无法报名");
        }

        // 检查报名时间
        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(contest.getRegisterStartTime()) || now.isAfter(contest.getRegisterEndTime())) {
            throw new BusinessException("不在报名时间范围内");
        }

        // 验证用户是否存在
        User user = userMapper.selectById(dto.getUserId());
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 检查用户是否已报名（个人参与）
        if ("individual".equals(dto.getRegistrationType())) {
            ContestRegistration existing = registrationMapper.selectOne(new LambdaQueryWrapper<ContestRegistration>()
                    .eq(ContestRegistration::getContestId, dto.getContestId())
                    .eq(ContestRegistration::getUserId, dto.getUserId())
                    .eq(ContestRegistration::getRegistrationType, "individual")
                    .eq(ContestRegistration::getDeleted, 0));
            if (existing != null) {
                throw new BusinessException("您已报名该活动");
            }
        }

        // 团队参与验证
        if ("team".equals(dto.getRegistrationType())) {
            if (dto.getTeamId() == null) {
                throw new BusinessException("团队参与必须指定团队 ID");
            }

            ContestTeam team = teamMapper.selectById(dto.getTeamId());
            if (team == null) {
                throw new BusinessException("团队不存在");
            }

            if (!team.getTenantId().equals(tenantId)) {
                throw new BusinessException("团队不属于当前租户");
            }

            if (!team.getContestId().equals(dto.getContestId())) {
                throw new BusinessException("团队不属于该活动");
            }

            // 检查用户是否是团队成员
            List<ContestTeamMember> members = teamMemberMapper.selectList(new LambdaQueryWrapper<ContestTeamMember>()
                    .eq(ContestTeamMember::getTeamId, dto.getTeamId())
                    .eq(ContestTeamMember::getUserId, dto.getUserId()));
            if (members.isEmpty()) {
                throw new BusinessException("您不是该团队成员");
            }
        }

        // 获取用户账号信息快照
        String accountNo = user.getUsername();
        String accountName = user.getNickname();

        // 检查当前登录用户是否是老师，如果是则设置为指导老师（registrant）
        Long registrantId = dto.getUserId();
        if (creatorId != null) {
            User creator = userMapper.selectById(creatorId);
            if (creator != null) {
                // TODO: 检查创建者是否是老师（需要查询 teacher 表）
                // 这里简化处理，假设有 teacher 标识
                registrantId = creatorId;
            }
        }

        // 创建报名记录
        ContestRegistration registration = new ContestRegistration();
        registration.setContestId(dto.getContestId());
        registration.setTenantId(tenantId);
        registration.setRegistrationType(dto.getRegistrationType());
        registration.setTeamId(dto.getTeamId());
        if (dto.getTeamId() != null) {
            ContestTeam team = teamMapper.selectById(dto.getTeamId());
            if (team != null) {
                registration.setTeamName(team.getTeamName());
            }
        }
        registration.setUserId(dto.getUserId());
        registration.setAccountNo(accountNo);
        registration.setAccountName(accountName);
        registration.setRegistrationState(RegistrationStateEnum.PENDING.getCode());
        registration.setRegistrationTime(LocalDateTime.now());
        registration.setRegistrant(registrantId);
        if (creatorId != null) {
            registration.setCreateBy(creatorId.toString());
        }

        registrationMapper.insert(registration);

        // 如果创建者是老师，自动添加为默认指导老师
        if (creatorId != null) {
            try {
                ContestRegistrationTeacher teacher = new ContestRegistrationTeacher();
                teacher.setRegistrationId(registration.getId());
                teacher.setTenantId(tenantId);
                teacher.setUserId(creatorId);
                teacher.setIsDefault(true);
                teacherMapper.insert(teacher);
            } catch (Exception e) {
                log.warn("创建默认指导老师失败：{}", e.getMessage());
            }
        }

        log.info("创建报名成功，ID={}, 活动 ID={}, 用户 ID={}", registration.getId(), dto.getContestId(), dto.getUserId());

        return convertToVO(registration);
    }

    @Override
    public RegistrationStatsVO getStats(Long contestId) {
        LambdaQueryWrapper<ContestRegistration> baseWrapper = new LambdaQueryWrapper<ContestRegistration>()
                .eq(ContestRegistration::getDeleted, 0);
        if (contestId != null) {
            baseWrapper.eq(ContestRegistration::getContestId, contestId);
        }

        long total = registrationMapper.selectCount(baseWrapper);
        long pending = registrationMapper.selectCount(new LambdaQueryWrapper<ContestRegistration>()
                .eq(ContestRegistration::getRegistrationState, "pending")
                .eq(ContestRegistration::getDeleted, 0)
                .eq(contestId != null, ContestRegistration::getContestId, contestId));
        long passed = registrationMapper.selectCount(new LambdaQueryWrapper<ContestRegistration>()
                .eq(ContestRegistration::getRegistrationState, "passed")
                .eq(ContestRegistration::getDeleted, 0)
                .eq(contestId != null, ContestRegistration::getContestId, contestId));
        long rejected = registrationMapper.selectCount(new LambdaQueryWrapper<ContestRegistration>()
                .eq(ContestRegistration::getRegistrationState, "rejected")
                .eq(ContestRegistration::getDeleted, 0)
                .eq(contestId != null, ContestRegistration::getContestId, contestId));

        RegistrationStatsVO vo = new RegistrationStatsVO();
        vo.setTotal((int) total);
        vo.setPending((int) pending);
        vo.setPassed((int) passed);
        vo.setRejected((int) rejected);
        return vo;
    }

    @Override
    public Page<RegistrationVO> pageQuery(RegistrationQueryDTO queryDTO, Long tenantId) {
        Page<ContestRegistration> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());

        LambdaQueryWrapper<ContestRegistration> wrapper = new LambdaQueryWrapper<ContestRegistration>()
                .eq(ContestRegistration::getDeleted, 0)
                .eq(queryDTO.getContestId() != null, ContestRegistration::getContestId, queryDTO.getContestId())
                .eq(queryDTO.getRegistrationState() != null, ContestRegistration::getRegistrationState, queryDTO.getRegistrationState())
                .eq(queryDTO.getRegistrationType() != null, ContestRegistration::getRegistrationType, queryDTO.getRegistrationType())
                .eq(queryDTO.getUserId() != null, ContestRegistration::getUserId, queryDTO.getUserId())
                .like(queryDTO.getKeyword() != null, ContestRegistration::getAccountName, queryDTO.getKeyword())
                .orderByDesc(ContestRegistration::getRegistrationTime);

        // TODO: 租户隔离（非超管只能看自己租户的）
        if (tenantId != null) {
            // 检查是否是超管租户
            Tenant tenant = new Tenant(); // 简化处理
            if (tenant.getIsSuper() == null || tenant.getIsSuper() == 0) {
                wrapper.eq(ContestRegistration::getTenantId, tenantId);
            }
        }

        Page<ContestRegistration> resultPage = registrationMapper.page(page, wrapper);

        List<RegistrationVO> voList = resultPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        Page<RegistrationVO> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public RegistrationVO getDetail(Long id, Long tenantId) {
        ContestRegistration registration = registrationMapper.selectById(id);
        if (registration == null || !registration.getTenantId().equals(tenantId)) {
            throw new BusinessException("报名记录不存在");
        }
        return convertToVO(registration);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RegistrationVO review(Long id, ReviewRegistrationDTO dto, Long operatorId, Long tenantId) {
        ContestRegistration registration = registrationMapper.selectById(id);
        if (registration == null) {
            throw new BusinessException("报名记录不存在");
        }

        if (!RegistrationStateEnum.PENDING.getCode().equals(registration.getRegistrationState())) {
            throw new BusinessException("只能审核待审核状态的报名");
        }

        registration.setRegistrationState(dto.getRegistrationState());
        registration.setReason(dto.getReason());
        registration.setOperator(operatorId);
        registration.setOperationDate(LocalDateTime.now());
        registration.setUpdateBy(operatorId.toString());

        registrationMapper.updateById(registration);
        log.info("审核报名成功，ID={}, 状态={}", id, dto.getRegistrationState());

        return convertToVO(registration);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id, Long tenantId) {
        ContestRegistration registration = registrationMapper.selectById(id);
        if (registration == null) {
            throw new BusinessException("报名记录不存在");
        }

        // 检查是否有作品
        Long workCount = workMapper.selectCount(new LambdaQueryWrapper<ContestWork>()
                .eq(ContestWork::getRegistrationId, id)
                .eq(ContestWork::getDeleted, 0));
        if (workCount > 0) {
            throw new BusinessException("该报名已有作品，无法删除");
        }

        registrationMapper.deleteById(id);
        log.info("删除报名成功，ID={}", id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RegistrationVO addTeacher(Long registrationId, Long teacherUserId, Long tenantId, Long creatorId) {
        ContestRegistration registration = registrationMapper.selectById(registrationId);
        if (registration == null || !registration.getTenantId().equals(tenantId)) {
            throw new BusinessException("报名记录不存在");
        }

        // 验证用户是否是老师
        User teacher = userMapper.selectById(teacherUserId);
        if (teacher == null) {
            throw new BusinessException("用户不存在");
        }

        // 检查是否已经添加过
        ContestRegistrationTeacher existing = teacherMapper.selectOne(new LambdaQueryWrapper<ContestRegistrationTeacher>()
                .eq(ContestRegistrationTeacher::getRegistrationId, registrationId)
                .eq(ContestRegistrationTeacher::getUserId, teacherUserId));
        if (existing != null) {
            throw new BusinessException("该老师已经添加过了");
        }

        // 添加指导老师
        ContestRegistrationTeacher teacherRel = new ContestRegistrationTeacher();
        teacherRel.setRegistrationId(registrationId);
        teacherRel.setTenantId(tenantId);
        teacherRel.setUserId(teacherUserId);
        teacherRel.setIsDefault(false);

        teacherMapper.insert(teacherRel);
        log.info("添加指导老师成功，报名 ID={}, 老师 ID={}", registrationId, teacherUserId);

        return convertToVO(registration);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTeacher(Long registrationId, Long teacherUserId, Long tenantId) {
        ContestRegistrationTeacher teacher = teacherMapper.selectOne(new LambdaQueryWrapper<ContestRegistrationTeacher>()
                .eq(ContestRegistrationTeacher::getRegistrationId, registrationId)
                .eq(ContestRegistrationTeacher::getUserId, teacherUserId));

        if (teacher == null) {
            throw new BusinessException("指导老师记录不存在");
        }

        if (teacher.getIsDefault()) {
            throw new BusinessException("默认指导老师不能移除");
        }

        teacherMapper.deleteById(teacher.getId());
        log.info("移除指导老师成功，报名 ID={}, 老师 ID={}", registrationId, teacherUserId);
    }

    @Override
    public RegistrationVO getMyRegistration(Long contestId, Long userId) {
        // 1. 先查询个人参与报名
        ContestRegistration individualReg = registrationMapper.selectOne(new LambdaQueryWrapper<ContestRegistration>()
                .eq(ContestRegistration::getContestId, contestId)
                .eq(ContestRegistration::getUserId, userId)
                .eq(ContestRegistration::getRegistrationType, "individual")
                .eq(ContestRegistration::getRegistrationState, "passed")
                .eq(ContestRegistration::getDeleted, 0));

        if (individualReg != null) {
            return convertToVO(individualReg);
        }

        // 2. 查询用户所属的团队
        List<ContestTeamMember> teamMemberships = teamMemberMapper.selectList(new LambdaQueryWrapper<ContestTeamMember>()
                .eq(ContestTeamMember::getUserId, userId));

        if (teamMemberships.isEmpty()) {
            return null;
        }

        List<Long> validTeamIds = teamMemberships.stream()
                .map(ContestTeamMember::getTeamId)
                .collect(Collectors.toList());

        // 3. 通过团队 ID 查询团队报名记录
        ContestRegistration teamReg = registrationMapper.selectOne(new LambdaQueryWrapper<ContestRegistration>()
                .eq(ContestRegistration::getContestId, contestId)
                .in(ContestRegistration::getTeamId, validTeamIds)
                .eq(ContestRegistration::getRegistrationType, "team")
                .eq(ContestRegistration::getRegistrationState, "passed")
                .eq(ContestRegistration::getDeleted, 0));

        if (teamReg != null) {
            return convertToVO(teamReg);
        }

        return null;
    }

    // ========== 转换方法 ==========

    private RegistrationVO convertToVO(ContestRegistration registration) {
        RegistrationVO vo = new RegistrationVO();
        vo.setId(registration.getId());
        vo.setContestId(registration.getContestId());
        vo.setTenantId(registration.getTenantId());
        vo.setRegistrationType(registration.getRegistrationType());
        vo.setTeamId(registration.getTeamId());
        vo.setTeamName(registration.getTeamName());
        vo.setUserId(registration.getUserId());
        vo.setAccountNo(registration.getAccountNo());
        vo.setAccountName(registration.getAccountName());
        vo.setRegistrationState(registration.getRegistrationState());
        vo.setRegistrationTime(registration.getRegistrationTime());
        vo.setReason(registration.getReason());
        vo.setOperator(registration.getOperator());
        vo.setOperationDate(registration.getOperationDate());
        vo.setRegistrant(registration.getRegistrant());

        // 查询作品数量
        Long workCount = workMapper.selectCount(new LambdaQueryWrapper<ContestWork>()
                .eq(ContestWork::getRegistrationId, registration.getId())
                .eq(ContestWork::getDeleted, 0));
        RegistrationVO.WorkCount workCountObj = new RegistrationVO.WorkCount();
        workCountObj.setWorks(workCount.intValue());
        vo.setWorkCount(workCountObj);

        return vo;
    }
}
