package ru.ulstu.grant.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.Deadline;
import ru.ulstu.grant.model.Grant;
import ru.ulstu.grant.model.GrantDto;
import ru.ulstu.grant.service.GrantService;

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

import static org.springframework.util.StringUtils.isEmpty;
import static ru.ulstu.grant.controller.Navigation.GRANTS_PAGE;
import static ru.ulstu.grant.controller.Navigation.GRANT_PAGE;
import static ru.ulstu.grant.controller.Navigation.REDIRECT_TO;
import static ru.ulstu.grant.controller.Navigation.hasErrors;


@Controller()
@RequestMapping(value = "/grants")
public class GrantController {
    private final GrantService grantService;

    public GrantController(GrantService grantService) {
        this.grantService = grantService;
    }

    @GetMapping("/grants")
    public void getGrants(ModelMap modelMap) {
        modelMap.put("grants", grantService.findAllDto());
    }

    @GetMapping("/dashboard")
    public void getDashboard(ModelMap modelMap) {
        modelMap.put("grants", grantService.findAllDto());
    }

    @GetMapping("/grant")
    public void getGrant(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
        if (id != null && id > 0) {
            modelMap.put("grantDto", grantService.findOneDto(id));
        } else {
            modelMap.put("grantDto", new GrantDto());
        }
    }

    @PostMapping(value = "/grant", params = "save")
    public String save(@Valid GrantDto grantDto, Errors errors) throws IOException {
        filterEmptyDeadlines(grantDto);
        if (grantDto.getDeadlines().isEmpty()) {
            errors.rejectValue("deadlines", "errorCode", "Не может быть пустым");
        }
        hasErrors(errors, GRANT_PAGE);
        grantService.save(grantDto);
        return String.format(REDIRECT_TO, GRANTS_PAGE);
    }

    @PostMapping(value = "/grant", params = "addDeadline")
    public String addDeadline(@Valid GrantDto grantDto, Errors errors) {
        filterEmptyDeadlines(grantDto);
        hasErrors(errors, GRANT_PAGE);
        grantDto.getDeadlines().add(new Deadline());
        return GRANT_PAGE;
    }

    @PostMapping(value = "/grant", params = "createProject")
    public String createProject(@Valid GrantDto grantDto, Errors errors) {
        hasErrors(errors, GRANT_PAGE);
        grantService.createProject(grantDto);
        return GRANT_PAGE;
    }

    @GetMapping("/delete/{grant-id}")
    public String delete(@PathVariable("grant-id") Integer grantId) throws IOException {
        grantService.delete(grantId);
        return String.format(REDIRECT_TO, GRANTS_PAGE);
    }

    @ModelAttribute("allStatuses")
    public List<Grant.GrantStatus> getGrantStatuses() {
        return grantService.getGrantStatuses();
    }

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