package org.springblade.modules.martial.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springblade.modules.martial.mapper.MartialTeamMapper;
import org.springblade.modules.martial.mapper.MartialTeamMemberMapper;
import org.springblade.modules.martial.pojo.entity.MartialAthlete;
import org.springblade.modules.martial.pojo.entity.MartialTeam;
import org.springblade.modules.martial.pojo.entity.MartialTeamMember;
import org.springblade.modules.martial.pojo.vo.MartialTeamVO;
import org.springblade.modules.martial.service.IMartialAthleteService;
import org.springblade.modules.martial.service.IMartialTeamService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springblade.core.secure.utils.AuthUtil;

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

@Service
@AllArgsConstructor
public class MartialTeamServiceImpl extends ServiceImpl<MartialTeamMapper, MartialTeam> implements IMartialTeamService {

	private final MartialTeamMemberMapper teamMemberMapper;
	private final IMartialAthleteService athleteService;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean saveTeamWithMembers(MartialTeam team, List<Long> memberIds) {
		team.setMemberCount(memberIds != null ? memberIds.size() : 0);
		team.setCreateUser(AuthUtil.getUserId());
		boolean saved = this.save(team);
		
		if (saved && memberIds != null && !memberIds.isEmpty()) {
			for (Long athleteId : memberIds) {
				MartialTeamMember member = new MartialTeamMember();
				member.setTeamId(team.getId());
				member.setAthleteId(athleteId);
				member.setCreateTime(LocalDateTime.now());
				member.setIsDeleted(0);
				member.setTenantId("000000");
				teamMemberMapper.insert(member);
			}
		}
		
		return saved;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean updateTeamWithMembers(MartialTeam team, List<Long> memberIds) {
		team.setMemberCount(memberIds != null ? memberIds.size() : 0);
		team.setUpdateUser(AuthUtil.getUserId());
		boolean updated = this.updateById(team);
		
		if (updated) {
			// Delete old members
			LambdaQueryWrapper<MartialTeamMember> deleteWrapper = new LambdaQueryWrapper<>();
			deleteWrapper.eq(MartialTeamMember::getTeamId, team.getId());
			teamMemberMapper.delete(deleteWrapper);
			
			// Insert new members
			if (memberIds != null && !memberIds.isEmpty()) {
				for (Long athleteId : memberIds) {
					MartialTeamMember member = new MartialTeamMember();
					member.setTeamId(team.getId());
					member.setAthleteId(athleteId);
					member.setCreateTime(LocalDateTime.now());
					member.setIsDeleted(0);
					member.setTenantId("000000");
					teamMemberMapper.insert(member);
				}
			}
		}
		
		return updated;
	}

	@Override
	public IPage<MartialTeamVO> getTeamList(Long createUser, Integer current, Integer size) {
		LambdaQueryWrapper<MartialTeam> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(MartialTeam::getCreateUser, createUser);
		wrapper.orderByDesc(MartialTeam::getCreateTime);
		
		IPage<MartialTeam> page = new Page<>(current, size);
		IPage<MartialTeam> teamPage = this.page(page, wrapper);
		
		IPage<MartialTeamVO> voPage = new Page<>(current, size, teamPage.getTotal());
		
		if (teamPage.getRecords().isEmpty()) {
			voPage.setRecords(new ArrayList<>());
			return voPage;
		}
		
		List<MartialTeamVO> voList = teamPage.getRecords().stream()
				.map(team -> {
					MartialTeamVO vo = new MartialTeamVO();
					BeanUtils.copyProperties(team, vo);
					// Calculate actual member count (excluding deleted athletes)
					int actualMemberCount = getActualMemberCount(team.getId());
					vo.setMemberCount(actualMemberCount);
					return vo;
				})
				.collect(Collectors.toList());
		
		voPage.setRecords(voList);
		return voPage;
	}

	/**
	 * Get actual member count excluding deleted athletes
	 */
	private int getActualMemberCount(Long teamId) {
		LambdaQueryWrapper<MartialTeamMember> memberWrapper = new LambdaQueryWrapper<>();
		memberWrapper.eq(MartialTeamMember::getTeamId, teamId);
		memberWrapper.eq(MartialTeamMember::getIsDeleted, 0);
		List<MartialTeamMember> members = teamMemberMapper.selectList(memberWrapper);
		
		if (members.isEmpty()) {
			return 0;
		}
		
		List<Long> athleteIds = members.stream()
				.map(MartialTeamMember::getAthleteId)
				.collect(Collectors.toList());
		
		LambdaQueryWrapper<MartialAthlete> athleteWrapper = new LambdaQueryWrapper<>();
		athleteWrapper.in(MartialAthlete::getId, athleteIds);
		athleteWrapper.eq(MartialAthlete::getIsDeleted, 0);
		return (int) athleteService.count(athleteWrapper);
	}

	@Override
	public MartialTeamVO getTeamDetail(Long id) {
		MartialTeam team = this.getById(id);
		if (team == null) {
			return null;
		}
		
		MartialTeamVO vo = new MartialTeamVO();
		BeanUtils.copyProperties(team, vo);
		
		// Get members
		LambdaQueryWrapper<MartialTeamMember> memberWrapper = new LambdaQueryWrapper<>();
		memberWrapper.eq(MartialTeamMember::getTeamId, id);
		memberWrapper.eq(MartialTeamMember::getIsDeleted, 0);
		List<MartialTeamMember> teamMembers = teamMemberMapper.selectList(memberWrapper);
		
		if (!teamMembers.isEmpty()) {
			List<Long> athleteIds = teamMembers.stream()
					.map(MartialTeamMember::getAthleteId)
					.collect(Collectors.toList());
			
			LambdaQueryWrapper<MartialAthlete> athleteWrapper = new LambdaQueryWrapper<>();
			athleteWrapper.in(MartialAthlete::getId, athleteIds);
			athleteWrapper.eq(MartialAthlete::getIsDeleted, 0);
			List<MartialAthlete> athletes = athleteService.list(athleteWrapper);
			Map<Long, MartialAthlete> athleteMap = athletes.stream()
					.collect(Collectors.toMap(MartialAthlete::getId, a -> a));
			
			List<MartialTeamVO.MemberInfo> members = teamMembers.stream()
					.map(tm -> {
						MartialTeamVO.MemberInfo info = new MartialTeamVO.MemberInfo();
						MartialAthlete athlete = athleteMap.get(tm.getAthleteId());
						if (athlete != null) {
							info.setId(athlete.getId());
							info.setName(athlete.getPlayerName());
							info.setIdCard(athlete.getIdCard());
							info.setGender(athlete.getGender());
						}
						return info;
					})
					.filter(info -> info.getId() != null)
					.collect(Collectors.toList());
			
			vo.setMembers(members);
		}
		
		return vo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean removeTeamWithMembers(Long id) {
		// Delete members first
		LambdaQueryWrapper<MartialTeamMember> memberWrapper = new LambdaQueryWrapper<>();
		memberWrapper.eq(MartialTeamMember::getTeamId, id);
		teamMemberMapper.delete(memberWrapper);
		
		// Delete team
		return this.removeById(id);
	}

}
