package org.springblade.modules.martial.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.martial.pojo.entity.MartialAthlete;
import org.springblade.modules.martial.pojo.entity.MartialCompetition;
import org.springblade.modules.martial.pojo.entity.MartialProject;
import org.springblade.modules.martial.pojo.entity.MartialRegistrationOrder;
import org.springblade.modules.martial.pojo.entity.MartialTeam;
import org.springblade.modules.martial.pojo.entity.MartialTeamMember;
import org.springblade.modules.martial.pojo.dto.RegistrationSubmitDTO;
import org.springblade.modules.martial.pojo.vo.MartialRegistrationOrderVO;
import org.springblade.modules.martial.pojo.vo.OrganizationStatsVO;
import org.springblade.modules.martial.service.IMartialAthleteService;
import org.springblade.modules.martial.service.IMartialCompetitionService;
import org.springblade.modules.martial.service.IMartialProjectService;
import org.springblade.modules.martial.service.IMartialRegistrationOrderService;
import org.springblade.modules.martial.service.IMartialTeamService;
import org.springblade.modules.martial.mapper.MartialTeamMemberMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

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

@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/martial/registrationOrder")
@Tag(name = "报名订单管理", description = "报名订单接口")
public class MartialRegistrationOrderController extends BladeController {

	private final IMartialRegistrationOrderService registrationOrderService;
	private final IMartialAthleteService athleteService;
	private final IMartialTeamService teamService;
	private final IMartialCompetitionService competitionService;
	private final IMartialProjectService projectService;
	private final MartialTeamMemberMapper teamMemberMapper;

	@GetMapping("/detail")
	@Operation(summary = "详情", description = "传入ID")
	public R detail(@RequestParam Long id) {
		return R.data(registrationOrderService.getDetailWithRelations(id));
	}

	@GetMapping("/list")
	@Operation(summary = "分页列表", description = "分页查询当前用户的报名记录")
	public R<IPage<MartialRegistrationOrderVO>> list(MartialRegistrationOrder registrationOrder, Query query) {
		Long userId = AuthUtil.getUserId();
		Integer status = registrationOrder.getStatus();
		
		IPage<MartialRegistrationOrderVO> pages = registrationOrderService.getListWithRelations(
				userId, status, query.getCurrent(), query.getSize());
		
		return R.data(pages);
	}

	@GetMapping("/organization-stats")
	@Operation(summary = "单位统计", description = "按单位统计运动员、项目、金额")
	public R<List<OrganizationStatsVO>> getOrganizationStats(@RequestParam Long competitionId) {
		log.info("获取单位统计: competitionId={}", competitionId);
		
		// 1. Get all athletes for this competition
		LambdaQueryWrapper<MartialAthlete> athleteWrapper = new LambdaQueryWrapper<>();
		athleteWrapper.eq(MartialAthlete::getCompetitionId, competitionId)
					  .eq(MartialAthlete::getIsDeleted, 0);
		List<MartialAthlete> athletes = athleteService.list(athleteWrapper);
		
		if (athletes.isEmpty()) {
			return R.data(new ArrayList<>());
		}
		
		// 2. Get all projects for this competition
		Set<Long> projectIds = athletes.stream()
			.map(MartialAthlete::getProjectId)
			.filter(Objects::nonNull)
			.collect(Collectors.toSet());
		
		final Map<Long, MartialProject> projectMap = new HashMap<>();
		if (!projectIds.isEmpty()) {
			List<MartialProject> projects = projectService.listByIds(projectIds);
			projectMap.putAll(projects.stream().collect(Collectors.toMap(MartialProject::getId, p -> p)));
		}
		
		// 3. Get team members for team projects
		Set<Long> teamIds = athletes.stream()
			.filter(a -> {
				MartialProject project = projectMap.get(a.getProjectId());
				return project != null && project.getType() != null && project.getType() == 2;
			})
			.map(a -> {
				// Try to get team ID from team table by team name
				LambdaQueryWrapper<MartialTeam> teamWrapper = new LambdaQueryWrapper<>();
				teamWrapper.eq(MartialTeam::getTeamName, a.getTeamName())
						   .eq(MartialTeam::getIsDeleted, 0)
						   .last("LIMIT 1");
				MartialTeam team = teamService.getOne(teamWrapper, false);
				return team != null ? team.getId() : null;
			})
			.filter(Objects::nonNull)
			.collect(Collectors.toSet());
		
		// Get team members
		Map<Long, List<MartialTeamMember>> teamMembersMap = new HashMap<>();
		if (!teamIds.isEmpty()) {
			LambdaQueryWrapper<MartialTeamMember> memberWrapper = new LambdaQueryWrapper<>();
			memberWrapper.in(MartialTeamMember::getTeamId, teamIds)
						 .eq(MartialTeamMember::getIsDeleted, 0);
			List<MartialTeamMember> members = teamMemberMapper.selectList(memberWrapper);
			teamMembersMap = members.stream().collect(Collectors.groupingBy(MartialTeamMember::getTeamId));
		}
		
		// 4. Group by organization and calculate stats
		Map<String, OrganizationStatsVO> orgStatsMap = new LinkedHashMap<>();
		
		for (MartialAthlete athlete : athletes) {
			String org = athlete.getOrganization();
			if (org == null || org.isEmpty()) {
				org = "未知单位";
			}
			
			OrganizationStatsVO stats = orgStatsMap.computeIfAbsent(org, k -> {
				OrganizationStatsVO vo = new OrganizationStatsVO();
				vo.setOrganization(k);
				vo.setAthleteCount(0);
				vo.setProjectCount(0);
				vo.setSingleProjectCount(0);
				vo.setTeamProjectCount(0);
				vo.setMaleCount(0);
				vo.setFemaleCount(0);
				vo.setTotalAmount(BigDecimal.ZERO);
				vo.setProjectAmounts(new ArrayList<>());
				return vo;
			});
			
			MartialProject project = projectMap.get(athlete.getProjectId());
			if (project == null) continue;
			
			// Check if project already counted for this org
			boolean projectExists = stats.getProjectAmounts().stream()
				.anyMatch(pa -> pa.getProjectId().equals(athlete.getProjectId()));
			
			if (!projectExists) {
				// Add project amount item
				OrganizationStatsVO.ProjectAmountItem item = new OrganizationStatsVO.ProjectAmountItem();
				item.setProjectId(project.getId());
				item.setProjectName(project.getProjectName());
				item.setProjectType(project.getType());
				item.setCount(1);
				item.setPrice(project.getPrice() != null ? project.getPrice() : BigDecimal.ZERO);
				item.setAmount(item.getPrice());
				stats.getProjectAmounts().add(item);
				
				stats.setProjectCount(stats.getProjectCount() + 1);
				if (project.getType() != null && project.getType() == 2) {
					stats.setTeamProjectCount(stats.getTeamProjectCount() + 1);
				} else {
					stats.setSingleProjectCount(stats.getSingleProjectCount() + 1);
				}
			} else {
				// Update count for existing project
				stats.getProjectAmounts().stream()
					.filter(pa -> pa.getProjectId().equals(athlete.getProjectId()))
					.findFirst()
					.ifPresent(pa -> {
						pa.setCount(pa.getCount() + 1);
						pa.setAmount(pa.getPrice().multiply(BigDecimal.valueOf(pa.getCount())));
					});
			}
		}
		
		// 5. Calculate unique athletes and gender counts per organization
		for (Map.Entry<String, OrganizationStatsVO> entry : orgStatsMap.entrySet()) {
			String org = entry.getKey();
			OrganizationStatsVO stats = entry.getValue();
			
			// Get all athletes for this org
			Set<String> uniqueIdCards = new HashSet<>();
			int maleCount = 0;
			int femaleCount = 0;
			
			for (MartialAthlete athlete : athletes) {
				String athleteOrg = athlete.getOrganization();
				if (athleteOrg == null || athleteOrg.isEmpty()) athleteOrg = "未知单位";
				if (!athleteOrg.equals(org)) continue;
				
				MartialProject project = projectMap.get(athlete.getProjectId());
				if (project == null) continue;
				
				// For individual projects, count the athlete
				if (project.getType() == null || project.getType() == 1) {
					String idCard = athlete.getIdCard();
					if (idCard != null && !idCard.isEmpty() && !uniqueIdCards.contains(idCard)) {
						uniqueIdCards.add(idCard);
						if (athlete.getGender() != null && athlete.getGender() == 1) {
							maleCount++;
						} else if (athlete.getGender() != null && athlete.getGender() == 2) {
							femaleCount++;
						}
					}
				} else {
					// For team projects, count team members
					String teamName = athlete.getTeamName();
					if (teamName != null) {
						LambdaQueryWrapper<MartialTeam> teamWrapper = new LambdaQueryWrapper<>();
						teamWrapper.eq(MartialTeam::getTeamName, teamName)
								   .eq(MartialTeam::getIsDeleted, 0)
								   .last("LIMIT 1");
						MartialTeam team = teamService.getOne(teamWrapper, false);
						if (team != null && teamMembersMap.containsKey(team.getId())) {
							for (MartialTeamMember member : teamMembersMap.get(team.getId())) {
								MartialAthlete memberAthlete = athleteService.getById(member.getAthleteId());
								if (memberAthlete != null) {
									String idCard = memberAthlete.getIdCard();
									if (idCard != null && !idCard.isEmpty() && !uniqueIdCards.contains(idCard)) {
										uniqueIdCards.add(idCard);
										if (memberAthlete.getGender() != null && memberAthlete.getGender() == 1) {
											maleCount++;
										} else if (memberAthlete.getGender() != null && memberAthlete.getGender() == 2) {
											femaleCount++;
										}
									}
								}
							}
						}
					}
				}
			}
			
			stats.setAthleteCount(uniqueIdCards.size());
			stats.setMaleCount(maleCount);
			stats.setFemaleCount(femaleCount);
			
			// Calculate total amount
			BigDecimal totalAmount = stats.getProjectAmounts().stream()
				.map(OrganizationStatsVO.ProjectAmountItem::getAmount)
				.reduce(BigDecimal.ZERO, BigDecimal::add);
			stats.setTotalAmount(totalAmount);
		}
		
		return R.data(new ArrayList<>(orgStatsMap.values()));
	}

	@PostMapping("/submit")
	@Operation(summary = "提交报名", description = "提交报名订单并关联选手或集体")
	@Transactional(rollbackFor = Exception.class)
	public R submit(@RequestBody RegistrationSubmitDTO dto) {
		log.info("=== 提交报名订单 ===");
		log.info("订单号: {}", dto.getOrderNo());
		log.info("赛事ID: {}", dto.getCompetitionId());
		log.info("项目IDs: {}", dto.getProjectIds());
		log.info("选手IDs: {}", dto.getAthleteIds());
		log.info("集体IDs: {}", dto.getTeamIds());
		log.info("联系电话: {}", dto.getContactPhone());
		log.info("总金额: {}", dto.getTotalAmount());
		
		// Validate competition exists and check registration/competition time
		MartialCompetition competition = competitionService.getById(dto.getCompetitionId());
		if (competition == null) {
			return R.fail("赛事不存在");
		}
		
		LocalDateTime now = LocalDateTime.now();
		
		// Check if registration time is valid
		if (competition.getRegistrationStartTime() != null && now.isBefore(competition.getRegistrationStartTime())) {
			return R.fail("报名尚未开始");
		}
		if (competition.getRegistrationEndTime() != null && now.isAfter(competition.getRegistrationEndTime())) {
			return R.fail("报名已结束");
		}
		
		// Check if competition has ended
		if (competition.getCompetitionEndTime() != null && now.isAfter(competition.getCompetitionEndTime())) {
			return R.fail("比赛已结束，无法报名");
		}
		
		// Create order entity
		MartialRegistrationOrder order = new MartialRegistrationOrder();
		order.setOrderNo(dto.getOrderNo());
		order.setCompetitionId(dto.getCompetitionId());
		order.setContactPhone(dto.getContactPhone());
		order.setTotalAmount(dto.getTotalAmount());
		order.setUserId(AuthUtil.getUserId());
		order.setUserName(AuthUtil.getUserName());
		
		// Parse IDs
		List<Long> athleteIds = Func.toLongList(dto.getAthleteIds());
		List<Long> teamIds = Func.toLongList(dto.getTeamIds());
		List<Long> projectIds = Func.toLongList(dto.getProjectIds());
		
		// Validate gender restriction for each project
		for (Long projectId : projectIds) {
			MartialProject project = projectService.getById(projectId);
			if (project == null) {
				continue;
			}
			
			String category = project.getCategory();
			if (category == null) {
				continue;
			}
			
			// For individual registration, check athlete gender
			if (teamIds.isEmpty() && !athleteIds.isEmpty()) {
				for (Long athleteId : athleteIds) {
					MartialAthlete athlete = athleteService.getById(athleteId);
					if (athlete == null) {
						continue;
					}
					
					Integer gender = athlete.getGender();
					if ("1".equals(category) && gender != null && gender != 1) {
						return R.fail("项目【" + project.getProjectName() + "】为男子组，不允许女性选手报名");
					} else if ("2".equals(category) && gender != null && gender != 2) {
						return R.fail("项目【" + project.getProjectName() + "】为女子组，不允许男性选手报名");
					}
				}
			}
			
			// For team registration, check team members gender
			if (!teamIds.isEmpty()) {
				for (Long teamId : teamIds) {
					MartialTeam team = teamService.getById(teamId);
					if (team == null) {
						continue;
					}
					
					// Query team members
					LambdaQueryWrapper<MartialTeamMember> memberWrapper = new LambdaQueryWrapper<>();
					memberWrapper.eq(MartialTeamMember::getTeamId, teamId)
								 .eq(MartialTeamMember::getIsDeleted, 0);
					List<MartialTeamMember> members = teamMemberMapper.selectList(memberWrapper);
					
					for (MartialTeamMember member : members) {
						MartialAthlete memberAthlete = athleteService.getById(member.getAthleteId());
						if (memberAthlete == null) {
							continue;
						}
						
						Integer gender = memberAthlete.getGender();
						if ("1".equals(category) && gender != null && gender != 1) {
							return R.fail("项目【" + project.getProjectName() + "】为男子组，队伍【" + team.getTeamName() + "】中存在女性成员，不允许报名");
						} else if ("2".equals(category) && gender != null && gender != 2) {
							return R.fail("项目【" + project.getProjectName() + "】为女子组，队伍【" + team.getTeamName() + "】中存在男性成员，不允许报名");
						}
					}
				}
			}
		}
		
		// Determine if this is a team registration
		boolean isTeamRegistration = !teamIds.isEmpty();
		
		if (isTeamRegistration) {
			order.setTotalParticipants(teamIds.size());
		} else {
			order.setTotalParticipants(athleteIds.size());
		}
		
		// Save order
		boolean saved = registrationOrderService.save(order);
		if (!saved) {
			return R.fail("创建订单失败");
		}
		
		Long orderId = order.getId();
		log.info("订单创建成功，订单ID: {}", orderId);
		
		if (isTeamRegistration) {
			// Handle team registration - create record for each team and each project
			for (Long teamId : teamIds) {
				MartialTeam team = teamService.getById(teamId);
				if (team == null) {
					log.warn("集体不存在: {}", teamId);
					continue;
				}
				
				// Create a record for each project
				for (Long projectId : projectIds) {
					// Check if team already registered for this project
					LambdaQueryWrapper<MartialAthlete> teamCheckWrapper = new LambdaQueryWrapper<>();
					teamCheckWrapper.eq(MartialAthlete::getCompetitionId, dto.getCompetitionId())
						.eq(MartialAthlete::getProjectId, projectId)
						.eq(MartialAthlete::getTeamName, team.getTeamName())
						.eq(MartialAthlete::getIsDeleted, 0)
						.eq(MartialAthlete::getRegistrationStatus, 1);
					MartialAthlete existingTeamRecord = athleteService.getOne(teamCheckWrapper, false);
					
					if (existingTeamRecord != null) {
						log.warn("集体重复报名，已跳过: teamName={}, projectId={}", team.getTeamName(), projectId);
						continue;
					}
					
					MartialAthlete teamAthlete = new MartialAthlete();
					teamAthlete.setOrderId(orderId);
					teamAthlete.setCompetitionId(dto.getCompetitionId());
					teamAthlete.setProjectId(projectId);
					teamAthlete.setTeamName(team.getTeamName());
					teamAthlete.setPlayerName(team.getTeamName());
					teamAthlete.setOrganization(team.getTeamName());
					teamAthlete.setRegistrationStatus(1);
					teamAthlete.setCompetitionStatus(0);
					teamAthlete.setCreateUser(AuthUtil.getUserId());
					teamAthlete.setCreateTime(new java.util.Date());
					teamAthlete.setTenantId("000000");
					teamAthlete.setIsDeleted(0);
					teamAthlete.setStatus(1);
					
					athleteService.save(teamAthlete);
					log.info("创建集体参赛记录: teamName={}, projectId={}", team.getTeamName(), projectId);
				}
			}
		} else {
			// Handle individual registration - create record for each athlete and each project
			for (Long athleteId : athleteIds) {
				MartialAthlete existingAthlete = athleteService.getById(athleteId);
				if (existingAthlete == null) {
					log.warn("选手不存在: {}", athleteId);
					continue;
				}
				
				// Create a record for each project
				for (Long projectId : projectIds) {
					// Check if record already exists for this athlete + competition + project
					LambdaQueryWrapper<MartialAthlete> checkWrapper = new LambdaQueryWrapper<>();
					checkWrapper.eq(MartialAthlete::getCompetitionId, dto.getCompetitionId())
						.eq(MartialAthlete::getProjectId, projectId)
						.eq(MartialAthlete::getIdCard, existingAthlete.getIdCard())
						.eq(MartialAthlete::getIsDeleted, 0)
						.eq(MartialAthlete::getRegistrationStatus, 1);
					MartialAthlete existingRecord = athleteService.getOne(checkWrapper, false);
					
					if (existingRecord != null) {
						// Skip duplicate registration
						log.warn("选手重复报名，已跳过: playerName={}, projectId={}", existingAthlete.getPlayerName(), projectId);
						continue;
					} else {
						// Create new record
						MartialAthlete newRecord = new MartialAthlete();
						newRecord.setOrderId(orderId);
						newRecord.setCompetitionId(dto.getCompetitionId());
						newRecord.setProjectId(projectId);
						newRecord.setPlayerName(existingAthlete.getPlayerName());
						newRecord.setGender(existingAthlete.getGender());
						newRecord.setIdCard(existingAthlete.getIdCard());
						newRecord.setIdCardType(existingAthlete.getIdCardType());
						newRecord.setBirthDate(existingAthlete.getBirthDate());
						newRecord.setAge(existingAthlete.getAge());
						newRecord.setContactPhone(existingAthlete.getContactPhone());
						newRecord.setOrganization(existingAthlete.getOrganization());
						newRecord.setTeamName(existingAthlete.getTeamName());
						newRecord.setRegistrationStatus(1);
						newRecord.setCompetitionStatus(0);
						newRecord.setCreateUser(AuthUtil.getUserId());
						newRecord.setCreateTime(new java.util.Date());
						newRecord.setTenantId("000000");
						newRecord.setIsDeleted(0);
						newRecord.setStatus(1);
						
						athleteService.save(newRecord);
						log.info("创建选手参赛记录: playerName={}, projectId={}", existingAthlete.getPlayerName(), projectId);
					}
				}
			}
		}
		
		return R.data(order);
	}

	@PostMapping("/remove")
	@Operation(summary = "删除", description = "传入ID")
	public R remove(@RequestParam String ids) {
		return R.status(registrationOrderService.removeByIds(Func.toLongList(ids)));
	}

}
