package org.springblade.modules.martial.controller;

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.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.martial.pojo.dto.MiniAthleteScoreDTO;
import org.springblade.modules.martial.pojo.dto.MiniLoginDTO;
import org.springblade.modules.martial.pojo.dto.MiniScoreModifyDTO;
import org.springblade.modules.martial.pojo.entity.*;
import org.springblade.modules.martial.pojo.vo.MiniAthleteAdminVO;
import org.springblade.modules.martial.pojo.vo.MiniAthleteScoreVO;
import org.springblade.modules.martial.pojo.vo.MiniLoginVO;
import org.springblade.modules.martial.pojo.vo.MiniScoreDetailVO;
import com.alibaba.fastjson.JSON;
import org.springblade.modules.martial.service.*;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 小程序专用接口 控制器
 *
 * @author BladeX
 */
@RestController
@AllArgsConstructor
@RequestMapping("/mini")
@Tag(name = "小程序接口", description = "小程序评分系统专用接口")
public class MartialMiniController extends BladeController {

	private final IMartialJudgeInviteService judgeInviteService;
	private final IMartialJudgeService judgeService;
	private final IMartialCompetitionService competitionService;
	private final IMartialVenueService venueService;
	private final IMartialProjectService projectService;
	private final IMartialAthleteService athleteService;
	private final IMartialScoreService scoreService;

	/**
	 * 登录验证
	 */
	@PostMapping("/login")
	@Operation(summary = "登录验证", description = "使用比赛编码和邀请码登录")
	public R<MiniLoginVO> login(@RequestBody MiniLoginDTO dto) {
		LambdaQueryWrapper<MartialJudgeInvite> inviteQuery = new LambdaQueryWrapper<>();
		inviteQuery.eq(MartialJudgeInvite::getInviteCode, dto.getInviteCode());
		inviteQuery.eq(MartialJudgeInvite::getIsDeleted, 0);
		MartialJudgeInvite invite = judgeInviteService.getOne(inviteQuery);

		if (invite == null) {
			return R.fail("邀请码不存在");
		}

		if (invite.getExpireTime() != null && invite.getExpireTime().isBefore(LocalDateTime.now())) {
			return R.fail("邀请码已过期");
		}

		MartialCompetition competition = competitionService.getById(invite.getCompetitionId());
		if (competition == null) {
			return R.fail("比赛不存在");
		}

		if (!competition.getCompetitionCode().equals(dto.getMatchCode())) {
			return R.fail("比赛编码不匹配");
		}

		MartialJudge judge = judgeService.getById(invite.getJudgeId());
		if (judge == null) {
			return R.fail("评委信息不存在");
		}

		String token = UUID.randomUUID().toString().replace("-", "");
		invite.setAccessToken(token);
		invite.setTokenExpireTime(LocalDateTime.now().plusDays(7));
		invite.setIsUsed(1);
		invite.setUseTime(LocalDateTime.now());
		invite.setLoginIp(dto.getLoginIp());
		invite.setDeviceInfo(dto.getDeviceInfo());
		judgeInviteService.updateById(invite);

		MartialVenue venue = null;
		if (invite.getVenueId() != null) {
			venue = venueService.getById(invite.getVenueId());
		}

		List<MiniLoginVO.ProjectInfo> projects = parseProjects(invite.getProjects());

		MiniLoginVO vo = new MiniLoginVO();
		vo.setToken(token);
		vo.setUserRole("chief_judge".equals(invite.getRole()) ? "admin" : "pub");
		vo.setMatchId(competition.getId());
		vo.setMatchName(competition.getCompetitionName());
		vo.setMatchTime(competition.getCompetitionStartTime() != null ?
			competition.getCompetitionStartTime().toString() : "");
		vo.setJudgeId(judge.getId());
		vo.setJudgeName(judge.getName());
		vo.setVenueId(venue != null ? venue.getId() : null);
		vo.setVenueName(venue != null ? venue.getVenueName() : null);
		vo.setProjects(projects);

		return R.data(vo);
	}

	/**
	 * 提交评分（评委）
	 * 注意：ID字段使用String类型接收，避免JavaScript大数精度丢失问题
	 */
	@PostMapping("/score/submit")
	@Operation(summary = "提交评分", description = "评委提交对选手的评分")
	public R submitScore(@RequestBody org.springblade.modules.martial.pojo.dto.MiniScoreSubmitDTO dto) {
		MartialScore score = new MartialScore();
		
		// 将String类型的ID转换为Long，避免JavaScript大数精度丢失
		score.setAthleteId(parseLong(dto.getAthleteId()));
		score.setJudgeId(parseLong(dto.getJudgeId()));
		score.setScore(dto.getScore());
		score.setProjectId(parseLong(dto.getProjectId()));
		score.setCompetitionId(parseLong(dto.getCompetitionId()));
		score.setVenueId(parseLong(dto.getVenueId()));
		score.setScheduleId(parseLong(dto.getScheduleId()));
		score.setNote(dto.getNote());
		score.setScoreTime(LocalDateTime.now());

		if (dto.getDeductions() != null && !dto.getDeductions().isEmpty()) {
			// 将String类型的扣分项ID转换为Long
			List<Long> deductionIds = dto.getDeductions().stream()
				.map(this::parseLong)
				.filter(id -> id != null)
				.collect(Collectors.toList());
			score.setDeductionItems(com.alibaba.fastjson.JSON.toJSONString(deductionIds));
		}

		Long judgeId = parseLong(dto.getJudgeId());
		if (judgeId != null) {
			var judge = judgeService.getById(judgeId);
			if (judge != null) {
				score.setJudgeName(judge.getName());
			}
		}

		boolean success = scoreService.save(score);
		return success ? R.success("评分提交成功") : R.fail("评分提交失败");
	}

	/**
	 * 安全地将String转换为Long
	 */
	private Long parseLong(String value) {
		if (value == null || value.trim().isEmpty()) {
			return null;
		}
		try {
			return Long.parseLong(value.trim());
		} catch (NumberFormatException e) {
			return null;
		}
	}

	/**
	 * 获取选手列表（支持分页）
	 * - 普通裁判：获取所有选手，标记是否已评分
	 * - 裁判长：获取已有评分的选手列表
	 */
	@GetMapping("/score/athletes")
	@Operation(summary = "获取选手列表", description = "根据裁判类型获取选手列表（支持分页）")
	public R<IPage<org.springblade.modules.martial.pojo.vo.MiniAthleteListVO>> getAthletes(
		@RequestParam Long judgeId,
		@RequestParam Integer refereeType,
		@RequestParam(required = false) Long projectId,
		@RequestParam(required = false) Long venueId,
		@RequestParam(defaultValue = "1") Integer current,
		@RequestParam(defaultValue = "10") Integer size
	) {
		// 1. 构建选手查询条件
		LambdaQueryWrapper<MartialAthlete> athleteQuery = new LambdaQueryWrapper<>();
		athleteQuery.eq(MartialAthlete::getIsDeleted, 0);

		if (projectId != null) {
			athleteQuery.eq(MartialAthlete::getProjectId, projectId);
		}

		athleteQuery.orderByAsc(MartialAthlete::getOrderNum);

		List<MartialAthlete> athletes = athleteService.list(athleteQuery);

		// 2. 获取所有评分记录
		LambdaQueryWrapper<MartialScore> scoreQuery = new LambdaQueryWrapper<>();
		scoreQuery.eq(MartialScore::getIsDeleted, 0);
		List<MartialScore> allScores = scoreService.list(scoreQuery);

		// 按选手ID分组统计评分
		java.util.Map<Long, List<MartialScore>> scoresByAthlete = allScores.stream()
			.collect(java.util.stream.Collectors.groupingBy(MartialScore::getAthleteId));

		// 3. 根据裁判类型处理选手列表
		List<org.springblade.modules.martial.pojo.vo.MiniAthleteListVO> filteredList;

		if (refereeType == 1) {
			// 裁判长：返回已有评分的选手
			filteredList = athletes.stream()
				.filter(athlete -> {
					List<MartialScore> scores = scoresByAthlete.get(athlete.getId());
					return scores != null && !scores.isEmpty();
				})
				.map(athlete -> convertToAthleteListVO(athlete, scoresByAthlete.get(athlete.getId()), judgeId))
				.collect(java.util.stream.Collectors.toList());
		} else {
			// 普通裁判：返回所有选手，标记是否已评分
			filteredList = athletes.stream()
				.map(athlete -> convertToAthleteListVO(athlete, scoresByAthlete.get(athlete.getId()), judgeId))
				.collect(java.util.stream.Collectors.toList());
		}

		// 4. 手动分页
		int total = filteredList.size();
		int fromIndex = (current - 1) * size;
		int toIndex = Math.min(fromIndex + size, total);

		List<org.springblade.modules.martial.pojo.vo.MiniAthleteListVO> pageRecords;
		if (fromIndex >= total) {
			pageRecords = new ArrayList<>();
		} else {
			pageRecords = filteredList.subList(fromIndex, toIndex);
		}

		// 5. 构建分页结果
		IPage<org.springblade.modules.martial.pojo.vo.MiniAthleteListVO> page = new Page<>(current, size, total);
		page.setRecords(pageRecords);

		return R.data(page);
	}

	/**
	 * 获取评分详情
	 */
	@GetMapping("/score/detail/{athleteId}")
	@Operation(summary = "评分详情", description = "查看选手的所有评委评分")
	public R<MiniScoreDetailVO> getScoreDetail(@PathVariable Long athleteId) {
		MiniScoreDetailVO detail = scoreService.getScoreDetailForMini(athleteId);
		return R.data(detail);
	}

	/**
	 * 修改评分（裁判长）
	 */
	@PutMapping("/score/modify")
	@Operation(summary = "修改评分", description = "裁判长修改选手总分")
	public R modifyScore(@RequestBody MiniScoreModifyDTO dto) {
		boolean success = scoreService.modifyScoreByAdmin(dto);
		return success ? R.success("修改成功") : R.fail("修改失败");
	}

	/**
	 * 退出登录
	 */
	@PostMapping("/logout")
	@Operation(summary = "退出登录", description = "清除登录状态")
	public R logout() {
		return R.success("退出成功");
	}

	/**
	 * Token验证
	 */
	@GetMapping("/verify")
	@Operation(summary = "Token验证", description = "验证当前token是否有效")
	public R verify() {
		return R.success("Token有效");
	}

	/**
	 * 转换选手实体为VO
	 */
	private org.springblade.modules.martial.pojo.vo.MiniAthleteListVO convertToAthleteListVO(
			MartialAthlete athlete, 
			List<MartialScore> scores, 
			Long currentJudgeId) {
		org.springblade.modules.martial.pojo.vo.MiniAthleteListVO vo = new org.springblade.modules.martial.pojo.vo.MiniAthleteListVO();
		vo.setAthleteId(athlete.getId());
		vo.setName(athlete.getPlayerName());
		vo.setIdCard(athlete.getIdCard());
		vo.setNumber(athlete.getPlayerNo());
		vo.setTeam(athlete.getTeamName());
		vo.setOrderNum(athlete.getOrderNum());
		vo.setCompetitionStatus(athlete.getCompetitionStatus());
		vo.setTotalScore(athlete.getTotalScore());

		// 设置项目名称
		if (athlete.getProjectId() != null) {
			MartialProject project = projectService.getById(athlete.getProjectId());
			if (project != null) {
				vo.setProjectName(project.getProjectName());
			}
		}

		// 设置评分状态
		if (scores != null && !scores.isEmpty()) {
			vo.setScoredJudgeCount(scores.size());
			
			// 查找当前裁判的评分
			MartialScore myScore = scores.stream()
				.filter(s -> s.getJudgeId().equals(currentJudgeId))
				.findFirst()
				.orElse(null);
			
			if (myScore != null) {
				vo.setScored(true);
				vo.setMyScore(myScore.getScore());
			} else {
				vo.setScored(false);
			}
		} else {
			vo.setScored(false);
			vo.setScoredJudgeCount(0);
		}

		return vo;
	}

	/**
	 * 解析项目JSON字符串
	 */
	private List<MiniLoginVO.ProjectInfo> parseProjects(String projectsJson) {
		List<MiniLoginVO.ProjectInfo> projects = new ArrayList<>();

		if (Func.isEmpty(projectsJson)) {
			return projects;
		}

		try {
			ObjectMapper mapper = new ObjectMapper();
			List<Long> projectIds = mapper.readValue(projectsJson, new TypeReference<List<Long>>() {});

			if (Func.isNotEmpty(projectIds)) {
				List<MartialProject> projectList = projectService.listByIds(projectIds);
				projects = projectList.stream().map(project -> {
					MiniLoginVO.ProjectInfo info = new MiniLoginVO.ProjectInfo();
					info.setProjectId(project.getId());
					info.setProjectName(project.getProjectName());
					return info;
				}).collect(Collectors.toList());
			}
		} catch (Exception e) {
			try {
				String[] ids = projectsJson.split(",");
				List<Long> projectIds = new ArrayList<>();
				for (String id : ids) {
					projectIds.add(Long.parseLong(id.trim()));
				}

				if (Func.isNotEmpty(projectIds)) {
					List<MartialProject> projectList = projectService.listByIds(projectIds);
					projects = projectList.stream().map(project -> {
						MiniLoginVO.ProjectInfo info = new MiniLoginVO.ProjectInfo();
						info.setProjectId(project.getId());
						info.setProjectName(project.getProjectName());
						return info;
					}).collect(Collectors.toList());
				}
			} catch (Exception ex) {
				// 解析失败，返回空列表
			}
		}

		return projects;
	}

}
