package ru.ulstu.paper.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.deadline.model.DeadlineDto;
import ru.ulstu.paper.model.Paper;
import ru.ulstu.paper.model.PaperDto;
import ru.ulstu.paper.model.PaperFilterDto;
import ru.ulstu.paper.service.PaperService;
import ru.ulstu.user.model.User;

import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

import static org.springframework.util.StringUtils.isEmpty;


@Controller()
@RequestMapping(value = "/papers")
public class PaperController {
    private final PaperService paperService;

    public PaperController(PaperService paperService) {
        this.paperService = paperService;
    }

    @GetMapping("/papers")
    public void getPapers(ModelMap modelMap) {
        modelMap.put("filteredPapers", new PaperFilterDto(paperService.findAllDto(), null, null));
    }

    @PostMapping("/papers")
    public void filterPapers(@Valid PaperFilterDto paperFilterDto, ModelMap modelMap) {
        modelMap.put("filteredPapers", new PaperFilterDto(paperService.filter(paperFilterDto),
                paperFilterDto.getFilterAuthorId(),
                paperFilterDto.getYear()));
    }

    @GetMapping("/dashboard")
    public void getDashboard(ModelMap modelMap) {
        modelMap.put("papers", paperService.findAllActive());
    }

    @GetMapping("/paper")
    public void getPapers(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
        if (id != null && id > 0) {
            modelMap.put("paperDto", paperService.findOneDto(id));
        } else {
            modelMap.put("paperDto", new PaperDto());
        }
    }

    @PostMapping(value = "/paper", params = "save")
    public String save(@Valid PaperDto paperDto, Errors errors) throws IOException {
        filterEmptyDeadlines(paperDto);
        if (paperDto.getDeadlines().isEmpty()) {
            errors.rejectValue("deadlines", "errorCode", "Не может быть пустым");
        }
        if (errors.hasErrors()) {
            return "/papers/paper";
        }
        paperService.save(paperDto);
        return "redirect:/papers/papers";
    }

    @PostMapping(value = "/paper", params = "addDeadline")
    public String addDeadline(@Valid PaperDto paperDto, Errors errors) {
        filterEmptyDeadlines(paperDto);
        if (errors.hasErrors()) {
            return "/papers/paper";
        }
        paperDto.getDeadlines().add(new DeadlineDto());
        return "/papers/paper";
    }

    @GetMapping("/delete/{paper-id}")
    public String delete(@PathVariable("paper-id") Integer paperId) throws IOException {
        paperService.delete(paperId);
        return "redirect:/papers/papers";
    }

    @ModelAttribute("allStatuses")
    public List<Paper.PaperStatus> getPaperStatuses() {
        return paperService.getPaperStatuses();
    }

    @ModelAttribute("allAuthors")
    public List<User> getAllAuthors() {
        return paperService.getPaperAuthors();
    }

    @ModelAttribute("allYears")
    public List<Integer> getAllYears() {
        List<Integer> years = new ArrayList<>();
        for (int i = Calendar.getInstance().get(Calendar.YEAR); i > 2010; i--) {
            years.add(i);
        }
        return years;
    }

    private void filterEmptyDeadlines(PaperDto paperDto) {
        paperDto.setDeadlines(paperDto.getDeadlines().stream()
                .filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
                .collect(Collectors.toList()));
    }
}
