package cn.meowrain.aioj.backend.question.service.impl;

import cn.meowrain.aioj.backend.question.common.enums.ChainMarkEnums;
import cn.meowrain.aioj.backend.question.dao.entity.Question;
import cn.meowrain.aioj.backend.question.dao.mapper.QuestionMapper;
import cn.meowrain.aioj.backend.question.dto.chains.context.QuestionCreateRequestParamVerifyContext;
import cn.meowrain.aioj.backend.question.dto.chains.context.QuestionEditRequestParamVerifyContext;
import cn.meowrain.aioj.backend.question.dto.req.*;
import cn.meowrain.aioj.backend.question.dto.resp.QuestionResponseDTO;
import cn.meowrain.aioj.backend.question.service.QuestionService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 题目服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements QuestionService {

	private final QuestionCreateRequestParamVerifyContext questionCreateChainContext;
	private final QuestionEditRequestParamVerifyContext questionEditChainContext;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Long createQuestionWithChain(QuestionCreateRequestDTO requestDTO) {
		// 执行责任链校验
		log.info("开始执行题目创建责任链校验");
		questionCreateChainContext.handler(
			ChainMarkEnums.QUESTION_CREATE_PARAM_VERIFY_CHAIN.getMark(),
			requestDTO
		);
		log.info("题目创建责任链校验通过");

		// 校验通过，转换为实体并保存
		Question question = new Question();
		BeanUtils.copyProperties(requestDTO, question);

		// 处理 tags 字段：List<String> -> JSON 字符串
		if (requestDTO.getTags() != null && !requestDTO.getTags().isEmpty()) {
			try {
				com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
				question.setTags(mapper.writeValueAsString(requestDTO.getTags()));
			} catch (Exception e) {
				log.error("序列化 tags 失败", e);
			}
		}

		// 处理 judgeConfig 字段：JudgeConfig 对象 -> JSON 字符串
		if (requestDTO.getJudgeConfig() != null) {
			try {
				com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
				question.setJudgeConfig(mapper.writeValueAsString(requestDTO.getJudgeConfig()));
			} catch (Exception e) {
				log.error("序列化 judgeConfig 失败", e);
			}
		}

		// 处理 judgeCase 字段：List<JudgeCase> -> JSON 字符串
		if (requestDTO.getJudgeCase() != null && !requestDTO.getJudgeCase().isEmpty()) {
			try {
				com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
				question.setJudgeCase(mapper.writeValueAsString(requestDTO.getJudgeCase()));
			} catch (Exception e) {
				log.error("序列化 judgeCase 失败", e);
			}
		}

		question.setUserId(1L);
		this.save(question);
		return question.getId();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Long createQuestion(Question question) {
		this.save(question);
		return question.getId();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean updateQuestion(Question question) {
		return this.updateById(question);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean updateQuestionWithChain(Long questionId, QuestionEditRequestDTO requestDTO) {
		// 先检查题目是否存在
		Question existingQuestion = this.getById(questionId);
		if (existingQuestion == null) {
			throw new cn.meowrain.aioj.backend.framework.core.exception.ClientException(
				"题目不存在，题目ID: " + questionId,
				cn.meowrain.aioj.backend.framework.core.errorcode.ErrorCode.NOT_FOUND_ERROR
			);
		}

		// 执行责任链校验
		log.info("开始执行题目编辑责任链校验，题目ID: {}", questionId);
		questionEditChainContext.handler(
			ChainMarkEnums.QUESTION_EDIT_PARAM_VERIFY_CHAIN.getMark(),
			requestDTO
		);
		log.info("题目编辑责任链校验通过");

		// 校验通过，更新题目（只更新非空字段）
		Question questionToUpdate = new Question();
		questionToUpdate.setId(questionId);

		// 使用 BeanUtils.copyProperties 的忽略空值特性
		// 这里需要手动处理每个字段，因为 copyProperties 会覆盖 null 值
		if (StringUtils.isNotBlank(requestDTO.getTitle())) {
			questionToUpdate.setTitle(requestDTO.getTitle());
		}
		if (StringUtils.isNotBlank(requestDTO.getContent())) {
			questionToUpdate.setContent(requestDTO.getContent());
		}
		if (StringUtils.isNotBlank(requestDTO.getDifficulty())) {
			questionToUpdate.setDifficulty(requestDTO.getDifficulty());
		}
		if (StringUtils.isNotBlank(requestDTO.getAnswer())) {
			questionToUpdate.setAnswer(requestDTO.getAnswer());
		}

		// 处理复杂字段
		ObjectMapper mapper = new ObjectMapper();
		if (requestDTO.getTags() != null && !requestDTO.getTags().isEmpty()) {
			try {
				questionToUpdate.setTags(mapper.writeValueAsString(requestDTO.getTags()));
			} catch (Exception e) {
				log.error("序列化 tags 失败", e);
			}
		}
		if (requestDTO.getJudgeConfig() != null) {
			try {
				questionToUpdate.setJudgeConfig(mapper.writeValueAsString(requestDTO.getJudgeConfig()));
			} catch (Exception e) {
				log.error("序列化 judgeConfig 失败", e);
			}
		}
		if (requestDTO.getJudgeCase() != null && !requestDTO.getJudgeCase().isEmpty()) {
			try {
				questionToUpdate.setJudgeCase(mapper.writeValueAsString(requestDTO.getJudgeCase()));
			} catch (Exception e) {
				log.error("序列化 judgeCase 失败", e);
			}
		}

		return this.updateById(questionToUpdate);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean deleteQuestion(Long questionId) {
		return this.removeById(questionId);
	}

	@Override
	public QuestionResponseDTO getQuestionById(Long questionId) {
		Question question = this.getById(questionId);
		return convertToDTO(question);
	}

	@Override
	public Question getQuestionByIdInner(Long questionId) {
		return this.getById(questionId);
	}

	@Override
	public Page<QuestionResponseDTO> listQuestions(QuestionQueryRequestDTO request) {
		LambdaQueryWrapper<Question> wrapper = new LambdaQueryWrapper<>();

		// ID 精确查询
		if (request.getId() != null) {
			wrapper.eq(Question::getId, request.getId());
		}

		// 标题模糊查询
		if (StringUtils.isNotBlank(request.getTitle())) {
			wrapper.like(Question::getTitle, request.getTitle());
		}

		// 难度精确查询
		if (StringUtils.isNotBlank(request.getDifficulty())) {
			wrapper.eq(Question::getDifficulty, request.getDifficulty());
		}

		// 创建者 ID 查询
		if (request.getUserId() != null) {
			wrapper.eq(Question::getUserId, request.getUserId());
		}

		// 排序
		if (StringUtils.isNotBlank(request.getSortField())) {
			if ("asc".equalsIgnoreCase(request.getSortOrder())) {
				wrapper.orderByAsc(Question::getCreateTime);
			} else {
				wrapper.orderByDesc(Question::getCreateTime);
			}
		} else {
			wrapper.orderByDesc(Question::getCreateTime);
		}

		// 直接使用 request 作为分页对象
		Page<Question> page = this.page(request, wrapper);

		// 转换为 DTO
		Page<QuestionResponseDTO> dtoPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
		dtoPage.setRecords(page.getRecords().stream()
				.map(this::convertToDTO)
				.toList());
		return dtoPage;
	}

	/**
	 * 将 Question 实体转换为 QuestionResponseDTO
	 */
	private QuestionResponseDTO convertToDTO(Question question) {
		if (question == null) {
			return null;
		}
		QuestionResponseDTO dto = new QuestionResponseDTO();
		BeanUtils.copyProperties(question, dto);

		// 处理 tags 字段：JSON 字符串 -> List<String>
		if (question.getTags() != null && !question.getTags().isEmpty()) {
			try {
				ObjectMapper mapper = new ObjectMapper();
				List<String> tagList = mapper.readValue(question.getTags(),
					new TypeReference<List<String>>() {});
				dto.setTags(tagList);
			} catch (Exception e) {
				log.error("解析 tags JSON 失败: {}", question.getTags(), e);
			}
		}

		// 处理 judgeConfig 字段：JSON 字符串 -> JudgeConfig 对象
		if (question.getJudgeConfig() != null && !question.getJudgeConfig().isEmpty()) {
			try {
				ObjectMapper mapper = new ObjectMapper();
				JudgeConfig judgeConfig =
					mapper.readValue(question.getJudgeConfig(),
						JudgeConfig.class);
				dto.setJudgeConfig(judgeConfig);
			} catch (Exception e) {
				log.error("解析 judgeConfig JSON 失败: {}", question.getJudgeConfig(), e);
			}
		}

		// 处理 judgeCase 字段：JSON 字符串 -> List<JudgeCase>
		if (question.getJudgeCase() != null && !question.getJudgeCase().isEmpty()) {
			try {
				ObjectMapper mapper = new ObjectMapper();
				List<JudgeCase> judgeCaseList =
					mapper.readValue(question.getJudgeCase(),
						new TypeReference<List<JudgeCase>>() {});
				dto.setJudgeCase(judgeCaseList);
			} catch (Exception e) {
				log.error("解析 judgeCase JSON 失败: {}", question.getJudgeCase(), e);
			}
		}

		return dto;
	}
}
