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.springblade.modules.martial.pojo.entity.MtVenue;
import org.springblade.core.redis.cache.BladeRedis;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
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 IMtVenueService mtVenueService;
	private final IMartialProjectService projectService;
	private final IMartialAthleteService athleteService;
	private final IMartialScoreService scoreService;
	private final BladeRedis bladeRedis;

	// Redis缓存key前缀
	private static final String MINI_LOGIN_CACHE_PREFIX = "mini:login:";
	// 登录缓存过期时间（7天）
	private static final Duration LOGIN_CACHE_EXPIRE = Duration.ofDays(7);

	/**
	 * 登录验证
	 */
	@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);

		// 从 mt_venue 表获取场地信息
		MtVenue mtVenue = null;
		if (invite.getVenueId() != null) {
			mtVenue = mtVenueService.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(mtVenue != null ? mtVenue.getId() : null);
		vo.setVenueName(mtVenue != null ? mtVenue.getVenueName() : null);
		vo.setProjects(projects);

		// 将登录信息缓存到Redis（服务重启后仍然有效）
		String cacheKey = MINI_LOGIN_CACHE_PREFIX + token;
		bladeRedis.setEx(cacheKey, vo, LOGIN_CACHE_EXPIRE);

		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);
		
		// 评分保存成功后，计算并更新选手总分
		if (success) {
			Long athleteId = parseLong(dto.getAthleteId());
			Long projectId = parseLong(dto.getProjectId());
			Long venueId = parseLong(dto.getVenueId());
			if (athleteId != null && projectId != null) {
				updateAthleteTotalScore(athleteId, projectId, venueId);
			}
		}
		
		return success ? R.success("评分提交成功") : R.fail("评分提交失败");
	}
	
	/**
	 * 计算并更新选手总分
	 * 总分算法：去掉一个最高分和一个最低分，取剩余分数的平均值
	 * 特殊情况：裁判数量<3时，直接取平均分
	 * 只有所有裁判都评分完成后才更新总分
	 */
	private void updateAthleteTotalScore(Long athleteId, Long projectId, Long venueId) {
		try {
			// 1. 查询该场地的普通裁判数量
			int requiredJudgeCount = getRequiredJudgeCount(venueId);

			// 2. 获取裁判长ID列表
			List<Long> chiefJudgeIds = getChiefJudgeIds(venueId);

			// 3. 查询该选手在该项目的所有评分（排除裁判长的评分）
			LambdaQueryWrapper<MartialScore> scoreQuery = new LambdaQueryWrapper<>();
			scoreQuery.eq(MartialScore::getAthleteId, athleteId);
			scoreQuery.eq(MartialScore::getProjectId, projectId);
			scoreQuery.eq(MartialScore::getIsDeleted, 0);
			// 排除裁判长的所有评分（包括普通评分和修改记录）
			if (!chiefJudgeIds.isEmpty()) {
				scoreQuery.notIn(MartialScore::getJudgeId, chiefJudgeIds);
			}
			List<MartialScore> scores = scoreService.list(scoreQuery);

			// 4. 判断是否所有裁判都已评分
			if (scores == null || scores.isEmpty()) {
				return;
			}
			
			// 如果配置了裁判数量，检查是否评分完成
			if (requiredJudgeCount > 0 && scores.size() < requiredJudgeCount) {
				// 未完成评分，清空总分
				MartialAthlete athlete = athleteService.getById(athleteId);
				if (athlete != null && athlete.getTotalScore() != null) {
					athlete.setTotalScore(null);
					athleteService.updateById(athlete);
				}
				return;
			}
			
			// 4. 计算总分（去掉最高最低分取平均）
			BigDecimal totalScore = calculateTotalScore(scores);
			
			// 5. 更新选手总分
			if (totalScore != null) {
				MartialAthlete athlete = athleteService.getById(athleteId);
				if (athlete != null) {
					athlete.setTotalScore(totalScore);
					athleteService.updateById(athlete);
				}
			}
		} catch (Exception e) {
			// 记录错误但不影响评分提交
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取场地应评分的裁判数量（普通裁判，不包括裁判长）
	 * 注意：使用 DISTINCT judge_id 来避免重复计数
	 */
	private int getRequiredJudgeCount(Long venueId) {
		if (venueId == null) {
			return 0;
		}
		LambdaQueryWrapper<MartialJudgeInvite> judgeQuery = new LambdaQueryWrapper<>();
		judgeQuery.eq(MartialJudgeInvite::getVenueId, venueId);
		judgeQuery.eq(MartialJudgeInvite::getIsDeleted, 0);
		judgeQuery.ne(MartialJudgeInvite::getRole, "chief_judge"); // 排除裁判长
		List<MartialJudgeInvite> judges = judgeInviteService.list(judgeQuery);
		// 使用 distinct judge_id 来计算不重复的裁判数量
		return (int) judges.stream()
			.map(MartialJudgeInvite::getJudgeId)
			.filter(Objects::nonNull)
			.distinct()
			.count();
	}
	
	/**
	 * 计算总分
	 * 算法：去掉一个最高分和一个最低分，取剩余分数的平均值
	 * 特殊情况：裁判数量<3时，直接取平均分
	 */
	private BigDecimal calculateTotalScore(List<MartialScore> scores) {
		if (scores == null || scores.isEmpty()) {
			return null;
		}
		
		// 提取所有分数并排序
		List<BigDecimal> scoreValues = scores.stream()
			.map(MartialScore::getScore)
			.filter(Objects::nonNull)
			.sorted()
			.collect(Collectors.toList());
		
		int count = scoreValues.size();
		if (count == 0) {
			return null;
		}
		
		if (count < 3) {
			// 裁判数量<3，直接取平均分
			BigDecimal sum = scoreValues.stream()
				.reduce(BigDecimal.ZERO, BigDecimal::add);
			return sum.divide(new BigDecimal(count), 3, RoundingMode.HALF_UP);
		}
		
		// 去掉最高分和最低分（已排序，去掉第一个和最后一个）
		List<BigDecimal> middleScores = scoreValues.subList(1, count - 1);
		
		// 计算平均分
		BigDecimal sum = middleScores.stream()
			.reduce(BigDecimal.ZERO, BigDecimal::add);
		return sum.divide(new BigDecimal(middleScores.size()), 3, RoundingMode.HALF_UP);
	}

	/**
	 * 安全地将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. 获取该场地所有裁判长的judge_id列表
		List<Long> chiefJudgeIds = getChiefJudgeIds(venueId);

		// 3. 获取所有评分记录（排除裁判长的评分）
		LambdaQueryWrapper<MartialScore> scoreQuery = new LambdaQueryWrapper<>();
		scoreQuery.eq(MartialScore::getIsDeleted, 0);
		if (projectId != null) {
			scoreQuery.eq(MartialScore::getProjectId, projectId);
		}
		// 添加场地过滤
		if (venueId != null) {
			scoreQuery.eq(MartialScore::getVenueId, venueId);
		}
		// 排除裁判长的评分
		if (!chiefJudgeIds.isEmpty()) {
			scoreQuery.notIn(MartialScore::getJudgeId, chiefJudgeIds);
		}
		List<MartialScore> allScores = scoreService.list(scoreQuery);

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

		// 4. 获取该场地的应评裁判数量
		int requiredJudgeCount = getRequiredJudgeCount(venueId);

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

		if (refereeType == 1) {
			// 裁判长：返回所有选手，前端根据totalScore判断是否显示修改按钮
			filteredList = athletes.stream()
				.map(athlete -> convertToAthleteListVO(athlete, scoresByAthlete.get(athlete.getId()), judgeId, requiredJudgeCount))
				.collect(java.util.stream.Collectors.toList());
		} else {
			// 普通裁判：返回所有选手，标记是否已评分
			filteredList = athletes.stream()
				.map(athlete -> convertToAthleteListVO(athlete, scoresByAthlete.get(athlete.getId()), judgeId, requiredJudgeCount))
				.collect(java.util.stream.Collectors.toList());
		}

		// 6. 手动分页
		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);
		}

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

		return R.data(page);
	}

	/**
	 * 获取场地所有裁判长的judge_id列表
	 */
	private List<Long> getChiefJudgeIds(Long venueId) {
		if (venueId == null) {
			return new ArrayList<>();
		}
		LambdaQueryWrapper<MartialJudgeInvite> judgeQuery = new LambdaQueryWrapper<>();
		judgeQuery.eq(MartialJudgeInvite::getVenueId, venueId);
		judgeQuery.eq(MartialJudgeInvite::getIsDeleted, 0);
		judgeQuery.eq(MartialJudgeInvite::getRole, "chief_judge");
		List<MartialJudgeInvite> chiefJudges = judgeInviteService.list(judgeQuery);
		return chiefJudges.stream()
			.map(MartialJudgeInvite::getJudgeId)
			.filter(Objects::nonNull)
			.collect(Collectors.toList());
	}

	/**
	 * 获取评分详情
	 */
	@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(@RequestHeader(value = "Authorization", required = false) String token) {
		// 从Redis删除登录缓存
		if (token != null && !token.isEmpty()) {
			String cacheKey = MINI_LOGIN_CACHE_PREFIX + token;
			bladeRedis.del(cacheKey);
		}
		return R.success("退出成功");
	}

	/**
	 * Token验证（从Redis恢复登录状态）
	 */
	@GetMapping("/verify")
	@Operation(summary = "Token验证", description = "验证token并返回登录信息，支持服务重启后恢复登录状态")
	public R<MiniLoginVO> verify(@RequestHeader(value = "Authorization", required = false) String token) {
		if (token == null || token.isEmpty()) {
			return R.fail("Token不能为空");
		}

		// 从Redis获取登录信息
		String cacheKey = MINI_LOGIN_CACHE_PREFIX + token;
		MiniLoginVO loginInfo = bladeRedis.get(cacheKey);

		if (loginInfo != null) {
			// 刷新缓存过期时间
			bladeRedis.setEx(cacheKey, loginInfo, LOGIN_CACHE_EXPIRE);
			return R.data(loginInfo);
		}

		// Redis中没有，尝试从数据库恢复
		LambdaQueryWrapper<MartialJudgeInvite> inviteQuery = new LambdaQueryWrapper<>();
		inviteQuery.eq(MartialJudgeInvite::getAccessToken, token);
		inviteQuery.eq(MartialJudgeInvite::getIsDeleted, 0);
		MartialJudgeInvite invite = judgeInviteService.getOne(inviteQuery);

		if (invite == null) {
			return R.fail("Token无效");
		}

		if (invite.getTokenExpireTime() != null && invite.getTokenExpireTime().isBefore(LocalDateTime.now())) {
			return R.fail("Token已过期");
		}

		// 重建登录信息
		MartialCompetition competition = competitionService.getById(invite.getCompetitionId());
		MartialJudge judge = judgeService.getById(invite.getJudgeId());
		MtVenue mtVenue = invite.getVenueId() != null ? mtVenueService.getById(invite.getVenueId()) : null;
		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 != null ? competition.getId() : null);
		vo.setMatchName(competition != null ? competition.getCompetitionName() : null);
		vo.setMatchTime(competition != null && competition.getCompetitionStartTime() != null ?
			competition.getCompetitionStartTime().toString() : "");
		vo.setJudgeId(judge != null ? judge.getId() : null);
		vo.setJudgeName(judge != null ? judge.getName() : null);
		vo.setVenueId(mtVenue != null ? mtVenue.getId() : null);
		vo.setVenueName(mtVenue != null ? mtVenue.getVenueName() : null);
		vo.setProjects(projects);

		// 重新缓存到Redis
		bladeRedis.setEx(cacheKey, vo, LOGIN_CACHE_EXPIRE);

		return R.data(vo);
	}

	/**
	 * 转换选手实体为VO
	 * 新增：只有评分完成时才显示总分
	 */
	private org.springblade.modules.martial.pojo.vo.MiniAthleteListVO convertToAthleteListVO(
			MartialAthlete athlete, 
			List<MartialScore> scores, 
			Long currentJudgeId,
			int requiredJudgeCount) {
		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.setRequiredJudgeCount(requiredJudgeCount);

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

		// 设置评分状态
		int scoredCount = 0;
		if (scores != null && !scores.isEmpty()) {
			scoredCount = scores.size();
			vo.setScoredJudgeCount(scoredCount);
			
			// 查找当前裁判的评分
			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);
		}
		
		// 判断评分是否完成（所有裁判都已评分）
		boolean scoringComplete = false;
		if (requiredJudgeCount > 0) {
			scoringComplete = scoredCount >= requiredJudgeCount;
		} else {
			// 如果没有配置裁判数量，只要有评分就算完成
			scoringComplete = scoredCount > 0;
		}
		vo.setScoringComplete(scoringComplete);
		
		// 只有评分完成时才显示总分
		if (scoringComplete) {
			vo.setTotalScore(athlete.getTotalScore());
		} else {
			vo.setTotalScore(null);
		}

		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;
	}

}
