package de.jottyfan.camporganizer.module.admin;

import java.security.Principal;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
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.servlet.mvc.support.RedirectAttributes;

import de.jottyfan.camporganizer.module.admin.model.CampBean;
import de.jottyfan.camporganizer.module.admin.model.CampDocumentBean;
import de.jottyfan.camporganizer.module.admin.model.DocumentBean;
import de.jottyfan.camporganizer.module.admin.model.LocationBean;
import de.jottyfan.camporganizer.module.camplist.CommonController;
import de.jottyfan.camporganizer.module.mail.MailBean;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;

/**
 *
 * @author jotty
 *
 */
@Controller
public class AdminController extends CommonController {

	private static final Logger LOGGER = LogManager.getLogger(AdminController.class);

	@Autowired
	private AdminService service;

	@Value("${spring.mail.username}")
	private String from;

	@GetMapping("/admin/mail")
	public String getMail(Model model, Principal principal) {
		MailBean mailBean = new MailBean();
		mailBean.setFrom(from);
		mailBean.getTo().add(getCurrentEmail(principal));
		model.addAttribute("bean", mailBean);
		return "/admin/mail";
	}

	@PostMapping("/admin/mail/send")
	public String sendMail(@Valid @ModelAttribute("bean") MailBean bean, final BindingResult bindingResult, Model model,
			HttpServletRequest request) {
		if (bindingResult.hasErrors()) {
			for (ObjectError error : bindingResult.getAllErrors())
				LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
			return "/admin/mail";
		}
		service.sendMail(bean);
		return "redirect:/admin/mail";
	}

	@GetMapping("/admin/document")
	public String getDocuments(Model model, HttpServletRequest request) {
		model.addAttribute("documents", service.getAllDocuments());
		return "/admin/document";
	}

	@GetMapping("/admin/document/add")
	public String prepareAddDocument(Model model, HttpServletRequest request) {
		model.addAttribute("bean", new DocumentBean());
		return "/admin/document_edit";
	}

	@GetMapping("/admin/document/edit/{id}")
	public String prepareAddDocument(@PathVariable("id") Integer id, Model model, HttpServletRequest request) {
		model.addAttribute("bean", service.getDocument(id));
		return "/admin/document_edit";
	}

	@PostMapping("/admin/document/update")
	public String updateDocument(@Valid @ModelAttribute("bean") DocumentBean bean, final BindingResult bindingResult,
			Model model, HttpServletRequest request) {
		if (bindingResult.hasErrors()) {
			for (ObjectError error : bindingResult.getAllErrors())
				LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
			return "/admin/document_edit";
		}
		service.updateDocument(bean);
		return "redirect:/admin/document";
	}

	@GetMapping("/admin/document/delete/{id}")
	public String deleteDocument(@PathVariable("id") Integer id, Model model, HttpServletRequest request) {
		service.deleteDocument(id);
		return "redirect:/admin/document";
	}

	@GetMapping("/admin/location")
	public String getLocations(Model model, HttpServletRequest request) {
		model.addAttribute("locations", service.getLocations());
		return "/admin/location";
	}

	@GetMapping("/admin/location/add")
	public String prepareAddLocation(Model model, HttpServletRequest request) {
		model.addAttribute("bean", new LocationBean());
		model.addAttribute("documents", service.getLocationDocuments());
		return "/admin/location_edit";
	}

	@GetMapping("/admin/location/edit/{id}")
	public String prepareAddLocation(@PathVariable("id") Integer id, Model model, HttpServletRequest request) {
		model.addAttribute("bean", service.getLocation(id));
		model.addAttribute("documents", service.getLocationDocuments());
		return "/admin/location_edit";
	}

	@PostMapping("/admin/location/update")
	public String updateDocument(@Valid @ModelAttribute("bean") LocationBean bean, final BindingResult bindingResult,
			Model model, HttpServletRequest request) {
		if (bindingResult.hasErrors()) {
			for (ObjectError error : bindingResult.getAllErrors()) {
				LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
			}
			model.addAttribute("documents", service.getLocationDocuments());
			return "/admin/location_edit";
		}
		service.upsertLocation(bean);
		return "redirect:/admin/location";
	}

	@GetMapping("/admin/location/delete/{id}")
	public String deleteLocation(@PathVariable("id") Integer id, Model model, HttpServletRequest request) {
		service.deleteLocation(id);
		return "redirect:/admin/location";
	}

	@GetMapping("/admin/camp")
	public String getCamplist(Model model, HttpServletRequest request) {
		model.addAttribute("camps", service.getAllCamps());
		model.addAttribute("locations", service.getLocations());
		return "/admin/camp";
	}

	@GetMapping("/admin/camp/add")
	public String prepareAddCamp(Model model, HttpServletRequest request) {
		model.addAttribute("bean", new CampBean());
		model.addAttribute("documents", service.getCampDocuments());
		model.addAttribute("locations", service.getLocations());
		model.addAttribute("profiles", service.getProfiles());
		return "/admin/camp_edit";
	}

	@GetMapping("/admin/camp/edit/{id}")
	public String prepareEditCamp(@PathVariable("id") Integer id, Model model, HttpServletRequest request) {
		model.addAttribute("bean", service.getCamp(id));
		model.addAttribute("documents", service.getCampDocuments());
		model.addAttribute("locations", service.getLocations());
		model.addAttribute("profiles", service.getProfiles());
		String error = (String) request.getAttribute("error");
		if (error != null) {
			model.addAttribute("error", error);
		}
		return "/admin/camp_edit";
	}

	@PostMapping("/admin/camp/update")
	public String updateDocument(@Valid @ModelAttribute("bean") CampBean bean, final BindingResult bindingResult,
			Model model, HttpServletRequest request, RedirectAttributes redirect) {
		if (bindingResult.hasErrors()) {
			for (ObjectError error : bindingResult.getAllErrors()) {
				LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
			}
			model.addAttribute("documents", service.getCampDocuments());
			model.addAttribute("locations", service.getLocations());
			model.addAttribute("profiles", service.getProfiles());
			return "/admin/camp_edit";
		}
		String error = service.upsertCamp(bean);
		redirect.addAttribute("error", error);
		Integer pk = bean.getPk();
		String errorDest = pk == null ? "redirect:/admin/camp/add" : "redirect:/admin/camp/edit/" + bean.getPk();
		return error != null ? errorDest : "redirect:/admin/camp";
	}

	@GetMapping("/admin/camp/delete/{id}")
	public String deleteCamp(@PathVariable("id") Integer id, Model model, HttpServletRequest request,
			RedirectAttributes redirect) {
		String error = service.deleteCamp(id);
		redirect.addAttribute("error", error);
		return error != null ? "redirect:/admin/camp/edit/" + id : "redirect:/admin/camp";
	}

	@GetMapping("/admin/campdocument")
	public String getCampDocumentList(Model model, HttpServletRequest request) {
		model.addAttribute("campmap", service.getCampMap());
		model.addAttribute("documentmap", service.getDocumentsMap());
		model.addAttribute("camps", service.getAllCamps());
		model.addAttribute("documents", service.getDocumentsForCamps());
		model.addAttribute("campdocuments", service.getAllCampDocuments());
		model.addAttribute("campdocument", new CampDocumentBean());
		return "/admin/campdocument";
	}

	@PostMapping("/admin/campdocument/add")
	public String addCampDocument(@Valid @ModelAttribute("bean") CampDocumentBean bean, final BindingResult bindingResult,
			Model model, HttpServletRequest request, RedirectAttributes redirect) {
		if (bindingResult.hasErrors()) {
			for (ObjectError error : bindingResult.getAllErrors()) {
				LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
			}
			model.addAttribute("campmap", service.getCampMap());
			model.addAttribute("documentmap", service.getDocumentsMap());
			model.addAttribute("camps", service.getAllCamps());
			model.addAttribute("documents", service.getDocumentsForCamps());
			model.addAttribute("campdocuments", service.getAllCampDocuments());
			return "/admin/campdocument";
		}
		service.upsertCampDocument(bean);
		return "redirect:/admin/campdocument";
	}

	@GetMapping("/admin/campdocument/delete/{id}")
	public String deleteCampDocument(@PathVariable("id") Integer id, Model model, HttpServletRequest request,
			RedirectAttributes redirect) {
		service.deleteCampDocument(id);
		return "redirect:/admin/campdocument";
	}

}
