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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.modules.martial.mapper.*;
import org.springblade.modules.martial.pojo.dto.*;
import org.springblade.modules.martial.pojo.entity.*;
import org.springblade.modules.martial.service.*;
import org.springframework.stereotype.Service;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class ScheduleArrangeServiceImpl implements IScheduleArrangeService {

    private final MartialScheduleGroupMapper scheduleGroupMapper;
    private final MartialScheduleMapper scheduleMapper;
    private final MartialScheduleAthleteMapper scheduleAthleteMapper;
    private final IMartialProjectService projectService;
    private final IMartialVenueService venueService;
    private final MartialScheduleDetailMapper scheduleDetailMapper;
    private final MartialScheduleParticipantMapper scheduleParticipantMapper;
    private final MartialAthleteMapper athleteMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
	public boolean saveDraftSchedule(SaveScheduleDraftDTO dto) {
		if (dto.getCompetitionGroups() == null || dto.getCompetitionGroups().isEmpty()) {
			return false;
		}

		for (CompetitionGroupDTO groupDTO : dto.getCompetitionGroups()) {
			// 1. 更新或创建编排明细
			Long groupId = groupDTO.getId();
			Long realGroupId = groupId;

			// Handle negative ID (draft data from auto-arrange)
			if (groupId != null && groupId < 0) {
				Long projectId = null;
				if (groupDTO.getCode() != null && groupDTO.getCode().contains("-P")) {
					try {
						String suffix = groupDTO.getCode().substring(groupDTO.getCode().lastIndexOf("-P") + 2);
						projectId = Long.parseLong(suffix);
					} catch (Exception e) {
						log.warn("Failed to parse projectId from code: {}", groupDTO.getCode());
					}
				}

				MartialScheduleGroup existingGroup = null;
				if (projectId != null) {
					existingGroup = scheduleGroupMapper.selectOne(
						new QueryWrapper<MartialScheduleGroup>()
							.eq("competition_id", dto.getCompetitionId())
							.eq("project_id", projectId)
							.eq("is_deleted", 0)
							.last("LIMIT 1")
					);
				}

				// Determine project type from DTO
				Integer projectType = null;
				if ("集体".equals(groupDTO.getType())) {
					projectType = 2;
				} else if ("单人".equals(groupDTO.getType())) {
					projectType = 1;
				}
				
				// Calculate participant/team counts
				int participantCount = groupDTO.getParticipants() != null ? groupDTO.getParticipants().size() : 0;
				
				if (existingGroup != null) {
					realGroupId = existingGroup.getId();
					existingGroup.setGroupName(groupDTO.getTitle());
					existingGroup.setProjectType(projectType);
					existingGroup.setTotalParticipants(participantCount);
					existingGroup.setTotalTeams(participantCount);
					existingGroup.setCategory(groupDTO.getCode());
					scheduleGroupMapper.updateById(existingGroup);
				} else {
					MartialScheduleGroup newGroup = new MartialScheduleGroup();
					newGroup.setCompetitionId(Long.valueOf(dto.getCompetitionId()));
					newGroup.setProjectId(projectId);
					newGroup.setGroupName(groupDTO.getTitle());
					newGroup.setProjectType(projectType);
					newGroup.setTotalParticipants(participantCount);
					newGroup.setTotalTeams(participantCount);
					newGroup.setCategory(groupDTO.getCode());
					scheduleGroupMapper.insert(newGroup);
					realGroupId = newGroup.getId();
				}
			}

			MartialScheduleDetail detail = scheduleDetailMapper.selectOne(
				new QueryWrapper<MartialScheduleDetail>()
					.eq("schedule_group_id", realGroupId)
					.eq("is_deleted", 0)
					.last("LIMIT 1")
			);

			if (detail == null) {
				detail = new MartialScheduleDetail();
				detail.setScheduleGroupId(realGroupId);
				detail.setCompetitionId(dto.getCompetitionId());
			}

			detail.setVenueId(groupDTO.getVenueId());
			detail.setVenueName(groupDTO.getVenueName());
			detail.setTimeSlot(groupDTO.getTimeSlot());

			// 设置时间段(上午/下午)
			if (groupDTO.getTimeSlot() != null && groupDTO.getTimeSlot().contains("上午")) {
				detail.setTimePeriod("morning");
			} else if (groupDTO.getTimeSlot() != null && groupDTO.getTimeSlot().contains("下午")) {
				detail.setTimePeriod("afternoon");
			} else {
				detail.setTimePeriod("morning"); // 默认上午
			}

			// 解析日期
			if (groupDTO.getTimeSlot() != null && groupDTO.getTimeSlot().contains("年")) {
				try {
					String dateStr = groupDTO.getTimeSlot().split(" ")[0];
					dateStr = dateStr.replace("年", "-").replace("月", "-").replace("日", "");
					detail.setScheduleDate(LocalDate.parse(dateStr));
				} catch (Exception e) {
					// 日期解析失败，使用当天日期
					detail.setScheduleDate(LocalDate.now());
				}
			}

			// 如果日期仍为空，设置默认日期
			if (detail.getScheduleDate() == null) {
				detail.setScheduleDate(LocalDate.now());
			}

			if (detail.getId() == null) {
				scheduleDetailMapper.insert(detail);
			} else {
				scheduleDetailMapper.updateById(detail);
			}

			// 1.5 同步更新项目的venue_id，保持数据一致性
			if (groupDTO.getVenueId() != null) {
				MartialScheduleGroup group = scheduleGroupMapper.selectById(realGroupId);
				if (group != null && group.getProjectId() != null) {
					MartialProject project = projectService.getById(group.getProjectId());
					if (project != null) {
						project.setVenueId(groupDTO.getVenueId());
						projectService.updateById(project);
					}
				}
			}

			// 2. 更新参赛者信息
			if (groupDTO.getParticipants() != null) {
				for (ParticipantDTO participantDTO : groupDTO.getParticipants()) {
					// Query by participant_id (registration ID) and schedule_group_id, not by primary key
					MartialScheduleParticipant participant = scheduleParticipantMapper.selectOne(
						new QueryWrapper<MartialScheduleParticipant>()
							.eq("participant_id", participantDTO.getId())
							.eq("schedule_group_id", realGroupId)
							.eq("is_deleted", 0)
							.last("LIMIT 1")
					);
					if (participant != null) {
						participant.setCheckInStatus(participantDTO.getStatus());
						participant.setPerformanceOrder(participantDTO.getSortOrder());
						participant.setScheduleStatus("draft");
						scheduleParticipantMapper.updateById(participant);
					} else {
						// Create new participant record if not exists
						MartialScheduleParticipant newParticipant = new MartialScheduleParticipant();
						newParticipant.setScheduleGroupId(realGroupId);
						newParticipant.setScheduleDetailId(detail.getId()); // Set schedule_detail_id
						newParticipant.setParticipantId(Long.valueOf(participantDTO.getId()));
						newParticipant.setOrganization(participantDTO.getSchoolUnit());
						newParticipant.setCheckInStatus(participantDTO.getStatus());
						newParticipant.setPerformanceOrder(participantDTO.getSortOrder());
						newParticipant.setScheduleStatus("draft");
						scheduleParticipantMapper.insert(newParticipant);
					}
				}
			}
		}

		return true;
	}

    @Override
    @Transactional(rollbackFor = Exception.class)
	public boolean saveAndLockSchedule(Long competitionId) {
		log.info("=== saveAndLockSchedule 开始 === competitionId: {}", competitionId);
		// 1. 查询所有分组
		List<MartialScheduleGroup> groups = scheduleGroupMapper.selectList(
			new QueryWrapper<MartialScheduleGroup>()
				.eq("competition_id", competitionId)
				.eq("is_deleted", 0)
		);

		if (groups.isEmpty()) {
			// 没有分组数据，视为成功（可能是初始状态，尚未进行自动编排）
			return true;
		}

		// 2. 获取所有分组ID
		List<Long> groupIds = groups.stream().map(MartialScheduleGroup::getId).collect(Collectors.toList());

		// 3. 更新所有参赛者的编排状态为completed
		List<MartialScheduleParticipant> participants = scheduleParticipantMapper.selectList(
			new QueryWrapper<MartialScheduleParticipant>()
				.in("schedule_group_id", groupIds)
				.eq("is_deleted", 0)
		);

		// 按分组和出场顺序分配选手编号
		Map<Long, Integer> groupCounters = new HashMap<>();
		participants.sort((a, b) -> {
			int groupCompare = a.getScheduleGroupId().compareTo(b.getScheduleGroupId());
			if (groupCompare != 0) return groupCompare;
			return Integer.compare(a.getPerformanceOrder() != null ? a.getPerformanceOrder() : 0, 
			                       b.getPerformanceOrder() != null ? b.getPerformanceOrder() : 0);
		});
		
		for (MartialScheduleParticipant participant : participants) {
			participant.setScheduleStatus("completed");
			scheduleParticipantMapper.updateById(participant);
			
			// 分配选手编号
			if (participant.getParticipantId() != null) {
				Long groupId = participant.getScheduleGroupId();
				int counter = groupCounters.getOrDefault(groupId, 0) + 1;
				groupCounters.put(groupId, counter);
				
				// 更新选手编号 (格式: 分组序号-出场序号)
				MartialAthlete athlete = athleteMapper.selectById(participant.getParticipantId());
				if (athlete != null && (athlete.getPlayerNo() == null || athlete.getPlayerNo().isEmpty())) {
					athlete.setPlayerNo(String.format("%03d", counter));
					athleteMapper.updateById(athlete);
				}
			}
		}

		return true;
	}

    @Override
    @Transactional(rollbackFor = Exception.class)
	public boolean moveScheduleGroup(org.springblade.modules.martial.pojo.dto.MoveScheduleGroupDTO dto) {
		// 1. 查询分组信息
		MartialScheduleGroup group = scheduleGroupMapper.selectById(dto.getGroupId());
		if (group == null) {
			throw new RuntimeException("分组不存在");
		}

		// 2. 查询该分组的详情记录
		List<MartialScheduleDetail> details = scheduleDetailMapper.selectList(
			new QueryWrapper<MartialScheduleDetail>()
				.eq("schedule_group_id", dto.getGroupId())
				.eq("is_deleted", 0)
		);

		if (details.isEmpty()) {
			throw new RuntimeException("分组详情不存在");
		}

		// 3. 查询目标场地信息
		MartialVenue targetVenue = venueService.getById(dto.getTargetVenueId());
		if (targetVenue == null) {
			throw new RuntimeException("目标场地不存在");
		}

		// 4. 根据时间段索引计算日期和时间
		// 假设: 0=第1天上午, 1=第1天下午, 2=第2天上午, 3=第2天下午...
		// 需要从赛事信息中获取起始日期
		int dayOffset = dto.getTargetTimeSlotIndex() / 2; // 每天2个时段
		boolean isAfternoon = dto.getTargetTimeSlotIndex() % 2 == 1;
		String timeSlot = isAfternoon ? "13:30" : "08:30";

		// 获取赛事起始日期(从第一个detail中获取)
		LocalDate baseDate = details.get(0).getScheduleDate();
		if (baseDate == null) {
			throw new RuntimeException("无法确定赛事起始日期");
		}

		// 计算目标日期(从起始日期开始,加上dayOffset天的偏移)
		// 如果当前detail的日期早于base date,需要调整
		LocalDate minDate = details.stream()
			.map(MartialScheduleDetail::getScheduleDate)
			.filter(Objects::nonNull)
			.min(LocalDate::compareTo)
			.orElse(baseDate);

		LocalDate targetDate = minDate.plusDays(dayOffset);

		// 5. 更新所有detail记录
		for (MartialScheduleDetail detail : details) {
			detail.setVenueId(dto.getTargetVenueId());
			detail.setVenueName(targetVenue.getVenueName());
			detail.setScheduleDate(targetDate);
			detail.setTimeSlot(timeSlot);
			detail.setTimeSlotIndex(dto.getTargetTimeSlotIndex());
			scheduleDetailMapper.updateById(detail);
		}

		return true;
	}
}
