package com.lesingle.modules.biz.contest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lesingle.common.enums.ErrorCode;
import com.lesingle.common.exception.BusinessException;
import com.lesingle.modules.biz.contest.dto.CreateTeamDto;
import com.lesingle.modules.biz.contest.entity.BizContestTeam;
import com.lesingle.modules.biz.contest.entity.BizContestTeamMember;
import com.lesingle.modules.biz.contest.mapper.ContestTeamMapper;
import com.lesingle.modules.biz.contest.mapper.ContestTeamMemberMapper;
import com.lesingle.modules.biz.contest.service.IContestTeamService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class ContestTeamServiceImpl extends ServiceImpl<ContestTeamMapper, BizContestTeam>
        implements IContestTeamService {

    private final ContestTeamMapper contestTeamMapper;
    private final ContestTeamMemberMapper contestTeamMemberMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> createTeam(CreateTeamDto dto, Long tenantId, Long creatorId) {
        log.info("开始创建团队，活动ID：{}，团队名称：{}", dto.getContestId(), dto.getTeamName());

        BizContestTeam team = new BizContestTeam();
        team.setTenantId(tenantId);
        team.setContestId(dto.getContestId());
        team.setTeamName(dto.getTeamName());
        team.setLeaderUserId(dto.getLeaderId());
        team.setMaxMembers(dto.getMaxMembers());
        team.setCreator(creatorId != null ? creatorId.intValue() : null);

        save(team);
        log.info("团队创建成功，ID：{}", team.getId());

        // 添加队长为成员
        addMemberInternal(team.getId(), dto.getLeaderId(), "leader", tenantId, creatorId);

        // 添加其他成员
        if (dto.getMemberIds() != null) {
            for (Long memberId : dto.getMemberIds()) {
                if (!memberId.equals(dto.getLeaderId())) {
                    addMemberInternal(team.getId(), memberId, "member", tenantId, creatorId);
                }
            }
        }

        // 添加指导老师
        if (dto.getTeacherIds() != null) {
            for (Long teacherId : dto.getTeacherIds()) {
                addMemberInternal(team.getId(), teacherId, "mentor", tenantId, creatorId);
            }
        }

        log.info("团队成员添加完成，团队ID：{}", team.getId());
        return teamToMap(team, getMemberList(team.getId()));
    }

    @Override
    public List<Map<String, Object>> findByContest(Long contestId, Long tenantId) {
        log.info("查询活动团队列表，活动ID：{}", contestId);

        LambdaQueryWrapper<BizContestTeam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BizContestTeam::getContestId, contestId);
        if (tenantId != null) {
            wrapper.eq(BizContestTeam::getTenantId, tenantId);
        }
        wrapper.orderByDesc(BizContestTeam::getCreateTime);

        List<BizContestTeam> teams = list(wrapper);

        return teams.stream()
                .map(team -> teamToMap(team, getMemberList(team.getId())))
                .collect(Collectors.toList());
    }

    @Override
    public Map<String, Object> findDetail(Long id) {
        log.info("查询团队详情，ID：{}", id);

        BizContestTeam team = getById(id);
        if (team == null) {
            throw BusinessException.of(ErrorCode.NOT_FOUND, "团队不存在");
        }

        return teamToMap(team, getMemberList(id));
    }

    @Override
    public BizContestTeam updateTeam(Long id, CreateTeamDto dto) {
        log.info("更新团队，ID：{}", id);

        BizContestTeam team = getById(id);
        if (team == null) {
            throw BusinessException.of(ErrorCode.NOT_FOUND, "团队不存在");
        }

        if (StringUtils.hasText(dto.getTeamName())) {
            team.setTeamName(dto.getTeamName());
        }
        if (dto.getLeaderId() != null) {
            team.setLeaderUserId(dto.getLeaderId());
        }
        if (dto.getMaxMembers() != null) {
            team.setMaxMembers(dto.getMaxMembers());
        }

        updateById(team);
        log.info("团队更新成功，ID：{}", id);
        return team;
    }

    @Override
    public void addMember(Long teamId, Long userId, String role, Long tenantId) {
        log.info("添加团队成员，团队ID：{}，用户ID：{}，角色：{}", teamId, userId, role);

        // 检查重复
        LambdaQueryWrapper<BizContestTeamMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BizContestTeamMember::getTeamId, teamId);
        wrapper.eq(BizContestTeamMember::getUserId, userId);
        Long existCount = contestTeamMemberMapper.selectCount(wrapper);
        if (existCount > 0) {
            throw BusinessException.of(ErrorCode.CONFLICT, "该用户已在团队中");
        }

        addMemberInternal(teamId, userId, role, tenantId, null);
        log.info("团队成员添加成功，团队ID：{}，用户ID：{}", teamId, userId);
    }

    @Override
    public void removeMember(Long teamId, Long userId) {
        log.info("移除团队成员，团队ID：{}，用户ID：{}", teamId, userId);

        LambdaQueryWrapper<BizContestTeamMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BizContestTeamMember::getTeamId, teamId);
        wrapper.eq(BizContestTeamMember::getUserId, userId);
        contestTeamMemberMapper.delete(wrapper);

        log.info("团队成员移除成功，团队ID：{}，用户ID：{}", teamId, userId);
    }

    @Override
    public void removeTeam(Long id) {
        log.info("删除团队，ID：{}", id);

        // 删除团队成员
        LambdaQueryWrapper<BizContestTeamMember> memberWrapper = new LambdaQueryWrapper<>();
        memberWrapper.eq(BizContestTeamMember::getTeamId, id);
        contestTeamMemberMapper.delete(memberWrapper);

        removeById(id);
        log.info("团队删除成功，ID：{}", id);
    }

    // ====== 私有辅助方法 ======

    private void addMemberInternal(Long teamId, Long userId, String role, Long tenantId, Long creatorId) {
        BizContestTeamMember member = new BizContestTeamMember();
        member.setTeamId(teamId);
        member.setTenantId(tenantId);
        member.setUserId(userId);
        member.setRole(role);
        member.setCreator(creatorId != null ? creatorId.intValue() : null);
        member.setCreateTime(LocalDateTime.now());
        contestTeamMemberMapper.insert(member);
    }

    private List<BizContestTeamMember> getMemberList(Long teamId) {
        LambdaQueryWrapper<BizContestTeamMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BizContestTeamMember::getTeamId, teamId);
        wrapper.orderByAsc(BizContestTeamMember::getCreateTime);
        return contestTeamMemberMapper.selectList(wrapper);
    }

    private Map<String, Object> teamToMap(BizContestTeam entity, List<BizContestTeamMember> members) {
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("id", entity.getId());
        map.put("tenantId", entity.getTenantId());
        map.put("contestId", entity.getContestId());
        map.put("teamName", entity.getTeamName());
        map.put("leaderUserId", entity.getLeaderUserId());
        map.put("maxMembers", entity.getMaxMembers());
        map.put("createTime", entity.getCreateTime());

        if (members != null) {
            List<Map<String, Object>> memberList = members.stream()
                    .map(m -> {
                        Map<String, Object> mMap = new LinkedHashMap<>();
                        mMap.put("id", m.getId());
                        mMap.put("teamId", m.getTeamId());
                        mMap.put("userId", m.getUserId());
                        mMap.put("role", m.getRole());
                        mMap.put("createTime", m.getCreateTime());
                        return mMap;
                    })
                    .collect(Collectors.toList());
            map.put("members", memberList);
            map.put("memberCount", memberList.size());
        }

        return map;
    }
}
