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

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

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

@Slf4j
@Service
@RequiredArgsConstructor
public class ScheduleDispatchServiceImpl implements IScheduleDispatchService {

    private final MartialScheduleGroupMapper scheduleGroupMapper;
    private final MartialScheduleParticipantMapper scheduleParticipantMapper;
    private final MartialScheduleDetailMapper scheduleDetailMapper;

    @Override
	public org.springblade.modules.martial.pojo.vo.DispatchDataVO getDispatchData(Long competitionId, Long venueId, Integer timeSlotIndex) {
		// 1. 查询指定场地和时间段的编排明细
		List<MartialScheduleDetail> details = scheduleDetailMapper.selectList(
			new QueryWrapper<MartialScheduleDetail>()
				.eq("competition_id", competitionId)
				.eq("venue_id", venueId)
				.eq("time_slot_index", timeSlotIndex)
				.eq("is_deleted", 0)
				.orderByAsc("sort_order")
		);

		if (details.isEmpty()) {
			// 返回空数据
			org.springblade.modules.martial.pojo.vo.DispatchDataVO vo = new org.springblade.modules.martial.pojo.vo.DispatchDataVO();
			vo.setGroups(new ArrayList<>());
			return vo;
		}

		// 2. 构建返回数据
		List<org.springblade.modules.martial.pojo.vo.DispatchDataVO.DispatchGroup> groups = new ArrayList<>();

		for (MartialScheduleDetail detail : details) {
			// 查询分组信息
			MartialScheduleGroup group = scheduleGroupMapper.selectById(detail.getScheduleGroupId());
			if (group == null) {
				continue;
			}

			// 查询该明细下的所有参赛者
			List<MartialScheduleParticipant> participants = scheduleParticipantMapper.selectList(
				new QueryWrapper<MartialScheduleParticipant>()
					.eq("schedule_detail_id", detail.getId())
					.eq("is_deleted", 0)
					.orderByAsc("performance_order")
			);

			// 转换为VO
			org.springblade.modules.martial.pojo.vo.DispatchDataVO.DispatchGroup groupVO =
				new org.springblade.modules.martial.pojo.vo.DispatchDataVO.DispatchGroup();
			groupVO.setGroupId(group.getId());
			groupVO.setGroupName(group.getGroupName());
			groupVO.setDetailId(detail.getId());
			groupVO.setProjectType(group.getProjectType());

			List<org.springblade.modules.martial.pojo.vo.DispatchDataVO.DispatchParticipant> participantVOs =
				participants.stream().map(p -> {
					org.springblade.modules.martial.pojo.vo.DispatchDataVO.DispatchParticipant pVO =
						new org.springblade.modules.martial.pojo.vo.DispatchDataVO.DispatchParticipant();
					pVO.setId(p.getId());
					pVO.setParticipantId(p.getParticipantId());
					pVO.setOrganization(p.getOrganization());
					pVO.setPlayerName(p.getPlayerName());
					pVO.setProjectName(p.getProjectName());
					pVO.setCategory(p.getCategory());
					pVO.setPerformanceOrder(p.getPerformanceOrder());
					return pVO;
				}).collect(Collectors.toList());

			groupVO.setParticipants(participantVOs);
			groups.add(groupVO);
		}

		org.springblade.modules.martial.pojo.vo.DispatchDataVO result =
			new org.springblade.modules.martial.pojo.vo.DispatchDataVO();
		result.setGroups(groups);
		return result;
	}

@CacheEvict(value = "scheduleResult", allEntries = true)
    @Override
    @Transactional(rollbackFor = Exception.class)
	public boolean adjustOrder(org.springblade.modules.martial.pojo.dto.AdjustOrderDTO dto) {
		// 1. 查询当前参赛者
		MartialScheduleParticipant current = scheduleParticipantMapper.selectById(dto.getParticipantId());
		if (current == null) {
			throw new RuntimeException("参赛者不存在");
		}

		// 2. 查询同一明细下的所有参赛者
		List<MartialScheduleParticipant> participants = scheduleParticipantMapper.selectList(
			new QueryWrapper<MartialScheduleParticipant>()
				.eq("schedule_detail_id", dto.getDetailId())
				.eq("is_deleted", 0)
				.orderByAsc("performance_order")
		);

		// 3. 根据动作调整顺序
		int currentIndex = -1;
		for (int i = 0; i < participants.size(); i++) {
			if (participants.get(i).getId().equals(dto.getParticipantId())) {
				currentIndex = i;
				break;
			}
		}

		if (currentIndex == -1) {
			throw new RuntimeException("未找到参赛者");
		}

		// 4. 执行调整
		if ("move_up".equals(dto.getAction())) {
			// 上移
			if (currentIndex == 0) {
				throw new RuntimeException("已经是第一个，无法上移");
			}
			// 交换位置
			Collections.swap(participants, currentIndex, currentIndex - 1);
		} else if ("move_down".equals(dto.getAction())) {
			// 下移
			if (currentIndex == participants.size() - 1) {
				throw new RuntimeException("已经是最后一个，无法下移");
			}
			// 交换位置
			Collections.swap(participants, currentIndex, currentIndex + 1);
		} else if ("swap".equals(dto.getAction())) {
			// 交换到指定位置
			if (dto.getTargetOrder() == null || dto.getTargetOrder() < 1 || dto.getTargetOrder() > participants.size()) {
				throw new RuntimeException("目标顺序无效");
			}
			int targetIndex = dto.getTargetOrder() - 1;
			Collections.swap(participants, currentIndex, targetIndex);
		}

		// 5. 更新所有参赛者的顺序
		for (int i = 0; i < participants.size(); i++) {
			MartialScheduleParticipant p = participants.get(i);
			p.setPerformanceOrder(i + 1);
			scheduleParticipantMapper.updateById(p);
		}

		return true;
	}

    @Override
@CacheEvict(value = "scheduleResult", allEntries = true)
    @Transactional(rollbackFor = Exception.class)
	public boolean saveDispatch(org.springblade.modules.martial.pojo.dto.SaveDispatchDTO dto) {
		if (dto.getAdjustments() == null || dto.getAdjustments().isEmpty()) {
			return true;
		}

		// 批量更新所有参赛者的出场顺序
		for (org.springblade.modules.martial.pojo.dto.SaveDispatchDTO.DetailAdjustment adjustment : dto.getAdjustments()) {
			for (org.springblade.modules.martial.pojo.dto.SaveDispatchDTO.ParticipantOrder po : adjustment.getParticipants()) {
				MartialScheduleParticipant participant = scheduleParticipantMapper.selectById(po.getId());
				if (participant != null) {
					participant.setPerformanceOrder(po.getPerformanceOrder());
					scheduleParticipantMapper.updateById(participant);
				}
			}
		}

		return true;
	}
}
