package org.fuseri.moduleexercise.question;

import jakarta.transaction.Transactional;
import org.fuseri.model.dto.exercise.AnswerDto;
import org.fuseri.model.dto.exercise.AnswerInQuestionCreateDto;
import org.fuseri.model.dto.exercise.QuestionCreateDto;
import org.fuseri.model.dto.exercise.QuestionDto;
import org.fuseri.model.dto.exercise.QuestionUpdateDto;
import org.fuseri.moduleexercise.answer.AnswerMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Represent facade for managing questions
 * Provide simplified interface for manipulating with questions
 */
@Transactional
@Service
public class QuestionFacade {
    private final QuestionService questionService;
    private final QuestionMapper questionMapper;
    private final AnswerMapper answerMapper;

    @Autowired
    public QuestionFacade(
            QuestionService questionService, QuestionMapper questionMapper,
            AnswerMapper answerMapper) {
        this.questionService = questionService;
        this.questionMapper = questionMapper;
        this.answerMapper = answerMapper;
    }

    /**
     * Find a question by ID.
     *
     * @param id the ID of the question to find
     * @return a QuestionDto object representing the found question
     */
    public QuestionDto find(long id) {
        return questionMapper.toDto(questionService.find(id));
    }

    /**
     * Retrieve a list of AnswerDto objects which belong to question with questionId
     *
     * @param questionId the ID of the question for which to retrieve answers
     * @return a List of AnswerDto objects
     */
    public List<AnswerDto> getQuestionAnswers(long questionId) {
        var question = questionService.find(questionId);
        return answerMapper.toDtoList(new ArrayList<>(question.getAnswers()));
    }

    /**
     * Add answers to question
     *
     * @param id  question ID
     * @param dto List with AnswerInQuestionCreateDto to add to question
     * @return a QuestionDto object representing the updated question
     */
    public QuestionDto addAnswers(Long id, List<AnswerInQuestionCreateDto> dto) {
        return questionMapper.toDto(questionService.addAnswers(id, answerMapper.fromCreateDtoList(dto)));
    }

    /**
     * Create a new question
     *
     * @param dto a QuestionCreateDto object representing the new question to add
     * @return a QuestionDto object representing the added question
     */
    public QuestionDto create(QuestionCreateDto dto) {
        return questionMapper.toDto(questionService.create(questionMapper.fromCreateDto(dto)));
    }

    /**
     * Update question
     *
     * @param dto dto of updated question with correct id
     * @return dto of updated question
     */
    public QuestionDto patchUpdate(long id, QuestionUpdateDto dto) {
        var updatedQuestion = questionService.patchUpdateWithoutAnswers(id, questionMapper.fromUpdateDto(dto));
        return questionMapper.toDto(updatedQuestion);
    }

    /**
     * Delete question
     *
     * @param id of qustion to delete
     */
    public void delete(long id) {
        questionService.delete(id);
    }
}
