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.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.modules.martial.pojo.dto.BatchGenerateInviteDTO;
import org.springblade.modules.martial.pojo.dto.GenerateInviteDTO;
import org.springblade.modules.martial.pojo.entity.MartialJudge;
import org.springblade.modules.martial.pojo.entity.MartialJudgeInvite;
import org.springblade.modules.martial.mapper.MartialJudgeInviteMapper;
import org.springblade.modules.martial.pojo.vo.MartialJudgeInviteVO;
import org.springblade.modules.martial.service.IMartialJudgeInviteService;
import org.springblade.modules.martial.service.IMartialJudgeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * JudgeInvite 服务实现类
 *
 * @author BladeX
 */
@Slf4j
@Service
public class MartialJudgeInviteServiceImpl extends ServiceImpl<MartialJudgeInviteMapper, MartialJudgeInvite> implements IMartialJudgeInviteService {

	@Autowired
	private IMartialJudgeService martialJudgeService;

	@Override
	public IPage<MartialJudgeInviteVO> selectJudgeInvitePage(MartialJudgeInvite judgeInvite, Query query) {
		IPage<MartialJudgeInviteVO> page = Condition.getPage(query);
		return baseMapper.selectJudgeInvitePage(page, judgeInvite);
	}

	@Override
	public Map<String, Object> getInviteStatistics(Long competitionId) {
		Map<String, Object> statistics = new HashMap<>();

		LambdaQueryWrapper<MartialJudgeInvite> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(MartialJudgeInvite::getCompetitionId, competitionId);

		// 总邀请数
		long totalInvites = this.count(wrapper);
		statistics.put("totalInvites", totalInvites);

		// 待回复数量
		LambdaQueryWrapper<MartialJudgeInvite> pendingWrapper = new LambdaQueryWrapper<>();
		pendingWrapper.eq(MartialJudgeInvite::getCompetitionId, competitionId)
			.eq(MartialJudgeInvite::getInviteStatus, 0);
		long pendingCount = this.count(pendingWrapper);
		statistics.put("pendingCount", pendingCount);

		// 已接受数量
		LambdaQueryWrapper<MartialJudgeInvite> acceptedWrapper = new LambdaQueryWrapper<>();
		acceptedWrapper.eq(MartialJudgeInvite::getCompetitionId, competitionId)
			.eq(MartialJudgeInvite::getInviteStatus, 1);
		long acceptedCount = this.count(acceptedWrapper);
		statistics.put("acceptedCount", acceptedCount);

		// 已拒绝数量
		LambdaQueryWrapper<MartialJudgeInvite> rejectedWrapper = new LambdaQueryWrapper<>();
		rejectedWrapper.eq(MartialJudgeInvite::getCompetitionId, competitionId)
			.eq(MartialJudgeInvite::getInviteStatus, 2);
		long rejectedCount = this.count(rejectedWrapper);
		statistics.put("rejectedCount", rejectedCount);

		return statistics;
	}

	@Override
	public MartialJudgeInvite generateInviteCode(GenerateInviteDTO dto) {
		// 1. 检查是否已存在有效邀请码
		MartialJudgeInvite existInvite = this.getOne(
			Wrappers.<MartialJudgeInvite>lambdaQuery()
				.eq(MartialJudgeInvite::getCompetitionId, dto.getCompetitionId())
				.eq(MartialJudgeInvite::getJudgeId, dto.getJudgeId())
				.eq(MartialJudgeInvite::getStatus, 1)
				.eq(MartialJudgeInvite::getIsDeleted, 0)
				.gt(MartialJudgeInvite::getExpireTime, LocalDateTime.now())
		);

		if (existInvite != null) {
			throw new ServiceException("该评委已有有效邀请码：" + existInvite.getInviteCode());
		}

		// 2. 生成唯一邀请码
		String inviteCode = generateUniqueInviteCode();

		MartialJudge martialJudge = martialJudgeService.getById(dto.getJudgeId());

		// 3. 创建邀请记录
		MartialJudgeInvite invite = new MartialJudgeInvite();
		invite.setCompetitionId(dto.getCompetitionId());
		invite.setJudgeId(dto.getJudgeId());
		invite.setInviteCode(inviteCode);
		invite.setRole(dto.getRole());
		invite.setVenueId(dto.getVenueId());
		invite.setProjects(dto.getProjects());
		invite.setContactPhone(martialJudge.getPhone());
		invite.setContactEmail(martialJudge.getSpecialty());
		invite.setRefereeType(martialJudge.getRefereeType());
		invite.setExpireTime(LocalDateTime.now().plusDays(dto.getExpireDays()));
		invite.setIsUsed(0);
		invite.setStatus(1);

		boolean success = this.save(invite);
		if (!success) {
			throw new ServiceException("生成邀请码失败");
		}

		log.info("为评委{}生成邀请码成功：{}", dto.getJudgeId(), inviteCode);
		return invite;
	}

	@Override
	public String generateUniqueInviteCode() {
		String inviteCode;
		int maxRetry = 10;
		int retry = 0;

		do {
			// 生成6位随机字符串（大写字母+数字）
			inviteCode = UUID.randomUUID().toString()
				.replaceAll("-", "")
				.substring(0, 6)
				.toUpperCase();

			// 检查是否重复
			long count = this.count(
				Wrappers.<MartialJudgeInvite>lambdaQuery()
					.eq(MartialJudgeInvite::getInviteCode, inviteCode)
					.eq(MartialJudgeInvite::getIsDeleted, 0)
			);

			if (count == 0) {
				return inviteCode;
			}

			retry++;
		} while (retry < maxRetry);

		throw new ServiceException("生成邀请码失败，请重试");
	}

	@Override
	public List<MartialJudgeInvite> batchGenerateInviteCode(BatchGenerateInviteDTO dto) {
		List<MartialJudgeInvite> invites = new ArrayList<>();
		List<String> failedJudges = new ArrayList<>();

		for (Long judgeId : dto.getJudgeIds()) {
			try {
				// 查询裁判信息，根据refereeType自动设置角色
				MartialJudge judge = martialJudgeService.getById(judgeId);
				String role = dto.getRole(); // 默认使用传入的角色
				if (judge != null && judge.getRefereeType() != null) {
					// refereeType=1 为主裁判，设置为chief_judge
					role = judge.getRefereeType() == 1 ? "chief_judge" : "judge";
				}

				GenerateInviteDTO generateDto = new GenerateInviteDTO();
				generateDto.setCompetitionId(dto.getCompetitionId());
				generateDto.setJudgeId(judgeId);
				generateDto.setRole(role);
				generateDto.setExpireDays(dto.getExpireDays());
				generateDto.setVenueId(dto.getVenueId());
				generateDto.setProjects(dto.getProjects());

				MartialJudgeInvite invite = generateInviteCode(generateDto);
				invites.add(invite);
				
				log.info("为评委{}生成邀请码，角色：{}", judgeId, role);
			} catch (Exception e) {
				log.warn("为评委{}生成邀请码失败：{}", judgeId, e.getMessage());
				failedJudges.add(judgeId.toString());
			}
		}

		if (!failedJudges.isEmpty()) {
			log.info("批量生成完成，失败的评委ID：{}", String.join(",", failedJudges));
		}

		return invites;
	}

	@Override
	public MartialJudgeInvite regenerateInviteCode(Long inviteId) {
		// 1. 查询原邀请记录
		MartialJudgeInvite oldInvite = this.getById(inviteId);
		if (oldInvite == null) {
			throw new ServiceException("邀请记录不存在");
		}

		// 2. 禁用旧邀请码
		oldInvite.setStatus(0);
		this.updateById(oldInvite);

		// 3. 生成新邀请码
		GenerateInviteDTO dto = new GenerateInviteDTO();
		dto.setCompetitionId(oldInvite.getCompetitionId());
		dto.setJudgeId(oldInvite.getJudgeId());
		dto.setRole(oldInvite.getRole());
		dto.setVenueId(oldInvite.getVenueId());
		dto.setProjects(oldInvite.getProjects());

		log.info("重新生成邀请码，旧邀请码：{}，评委ID：{}", oldInvite.getInviteCode(), oldInvite.getJudgeId());
		return generateInviteCode(dto);
	}

}
