package com.apobates.forum.thrones.admin.controller;

import com.apobates.forum.core.ImageIOMeta;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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 org.springframework.web.bind.annotation.ResponseBody;
import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.BoardGroup;
import com.apobates.forum.core.entity.ForumEntityStatusEnum;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.core.entity.proxy.TopicReplica;
import com.apobates.forum.core.service.BoardGroupService;
import com.apobates.forum.core.service.BoardService;
import com.apobates.forum.core.service.TopicService;
import com.apobates.forum.event.elderly.ActionEventCulpritor;
import com.apobates.forum.member.storage.core.MemberSessionBean;
import com.apobates.forum.thrones.admin.controller.form.SectionForm;
import com.apobates.forum.thrones.admin.controller.form.SectionTermForm;
import com.apobates.forum.thrones.admin.controller.form.TopicPublishForm;
import com.apobates.forum.thrones.admin.controller.helper.AdminUtils;
import com.apobates.forum.thrones.admin.exception.ResourceNotFoundException;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.FrontPageURL;
import com.apobates.forum.utils.TipMessage;
import com.apobates.forum.utils.lang.EnumArchitecture;
import com.apobates.forum.utils.persistence.Page;
import com.apobates.forum.utils.persistence.PageRequest;
import com.apobates.forum.utils.persistence.Pageable;
import java.util.Optional;
import javax.validation.Valid;
import org.springframework.validation.BindingResult;

/**
 * 栏目(原生版块组)/子栏目(原生的版块)/文章(原生的话题)控制器
 *
 * @author xiaofanku
 * @since 20190928
 */
@Controller
@RequestMapping(value = "/section")
public class AdminSectionArticleController {
    @Autowired
    private BoardGroupService boardGroupService;
    @Autowired
    private BoardService boardService;
    @Autowired
    private TopicService topicService;
    @Autowired
    private ImageIOMeta imageIOMeta;
    @Value("${site.pageSize}")
    private int pageSize;
    
    //栏目列表
    @GetMapping(path = "/")
    public String listPage(HttpServletRequest request, Model model) {
        List<BoardGroup> rs = boardGroupService.getAllOrigin().collect(Collectors.toList());
        model.addAttribute("rs", rs);
        return "admin/section/index";
    }
    //新增|编辑栏目
    @GetMapping(path = "/edit")
    public String editForm(
            @RequestParam(name = "section", required = false, defaultValue = "0") int sectionId,
            HttpServletRequest request,
            Model model) {
        BoardGroup section = boardGroupService.getOriginById(sectionId).orElseGet(BoardGroup::new);
        SectionForm form = new SectionForm();
        form.setRecord(section.getId()); //0
        form.setStatus((section.getId()==0)?true:section.isStatus()); //true
        form.setDirect(section.getDirectoryNames()); //""
        form.setTitle(section.getTitle());
        form.setDescription(section.getDescription());
        model.addAttribute("form", form);
        return "admin/section/edit";
    }
    
    @PostMapping(path = "/edit")
    public String editAction(
            HttpServletRequest request,
            @Valid @ModelAttribute("form") SectionForm form,
            BindingResult bindingResult,
            Model model) {
        if (bindingResult.hasErrors()) {
            model.addAttribute("form", form);
            return "admin/section/edit";
        }
        String directName = Commons.getAlphaNumberCharacter(form.getDirect());
        boolean symbol;
        if (form.isUpdate()) {
            symbol = boardGroupService.editSection(form.getIntegerRecord(), form.getTitle(), form.getDescription(), directName, form.getBooleanStatus()).orElse(false);
        } else {
            symbol = boardGroupService.buildOrigin(form.getTitle(), form.getDescription(), directName, form.getBooleanStatus())>0;
        }
        if (symbol) {
            return "redirect:/section/";
        }
        model.addAttribute("errors", form.getActionTitle() + "栏目操作失败");
        model.addAttribute("form", form);
        return "admin/section/edit";
    }
    //所有栏目
    @GetMapping(path = "/list/json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public Map<Integer, String> getAllForJson(
            @RequestParam(name = "ids", required = false, defaultValue = "") String idString,
            HttpServletRequest request,
            Model model) {
        Set<Integer> idList = AdminUtils.toIntegerSet(idString);
        return boardGroupService.getAllOriginById(idList).collect(Collectors.toMap(BoardGroup::getId, BoardGroup::getTitle));
    }
    // 栏目目录名称唯一性检查
    @GetMapping(path = "/direct/unique")
    public ResponseEntity<String> checkSectionDirectNames(
            @RequestParam("direct") String directoryNames,
            @RequestParam("record") int sectionId,
            HttpServletRequest request,
            Model model) {
        String tipMessage;
        boolean symbol = false;
        Optional<Boolean> result = boardGroupService.checkOriginDirectNameUnique(directoryNames, sectionId);
        if (result.orElse(false)) {
            tipMessage = result.get() ? "可以使用" : "未知的错误";
            symbol = true;
        } else {
            tipMessage = "目录名称唯一性检测失败";
        }
        //
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.set("Content-Type", "text/plain; charset=UTF-8");
        HttpStatus hs = symbol ? HttpStatus.OK : HttpStatus.BAD_REQUEST;
        return new ResponseEntity<>(tipMessage, responseHeaders, hs);
    }
    
    //子栏目
    @GetMapping(path = "/term")
    public String termPage(
            @RequestParam(name = "s", required = false, defaultValue = "0") int sectionId,
            HttpServletRequest request,
            Model model) {
        List<Board> rs = boardService.getAllTermByOriginId(sectionId);
        model.addAttribute("rs", rs);
        model.addAttribute("paramSection", sectionId); //页面这个值等于0不能新增子栏目
        return "admin/section/term";
    }
    //新增|编辑子栏目
    @GetMapping(path = "/term/edit")
    public String termEditForm(
            @RequestParam(name = "s", required = false, defaultValue = "0") int sectionId,
            @RequestParam(name = "term", required = false, defaultValue = "0") long termId,
            HttpServletRequest request,
            Model model) {
        Board term = boardService.getTermById(termId).orElseGet(Board::new);
        SectionTermForm form = new SectionTermForm();
        form.setSection(term.getVolumesId() + ""); //sectionId+""
        form.setDirect(term.getDirectoryNames()); //""
        form.setTitle(term.getTitle());
        form.setDescription(term.getDescription());
        form.setRecord(term.getId());
        try{
            form.setEntityStatus(term.getStatus());
        }catch(NullPointerException e){ //新增时可能抛出
            form.setEntityStatus(ForumEntityStatusEnum.ACTIVE);
        }
        //补刀
        if (0 == termId && sectionId > 0) {
            form.setSection(sectionId + "");
        }
        model.addAttribute("form", form);
        //
        model.addAttribute("boardStatusData", EnumArchitecture.getInstance(ForumEntityStatusEnum.class));
        return "admin/section/term_edit";
    }
    
    @PostMapping(path = "/term/edit")
    public String termEditAction(
            HttpServletRequest request,
            @Valid @ModelAttribute("form") SectionTermForm form,
            BindingResult bindingResult,
            Model model) {
        if (bindingResult.hasErrors()) {
            model.addAttribute("form", form);
            //
            model.addAttribute("boardStatusData", EnumArchitecture.getInstance(ForumEntityStatusEnum.class));
            return "admin/section/term_edit";
        }
        String directName = Commons.getAlphaNumberCharacter(form.getDirect());
        boolean symbol;
        if (form.isUpdate()) {
            symbol = boardService.editTerm(form.getLongRecord(), form.getTitle(), form.getDescription(), directName, form.getEnumEntityStatus()).orElse(false);
        } else {
            symbol = boardService.buildOrigin(form.getIntegerSection(), form.getTitle(), form.getDescription(), directName, form.getEnumEntityStatus())>0;
        }
        if (symbol) {
            return "redirect:/section/term?s=" + form.getSection();
        }
        model.addAttribute("errors", form.getActionTitle() + "子栏目操作失败");
        model.addAttribute("form", form);
        //
        model.addAttribute("boardStatusData", EnumArchitecture.getInstance(ForumEntityStatusEnum.class));
        return "admin/section/term_edit";
    }
    //指定栏目的所有子栏目
    @GetMapping(path = "/term/all/json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public Map<Long, String> getAllTermForJson(
            @RequestParam("parent") int sectionId,
            HttpServletRequest request,
            Model model) {
        return boardService.getAllTermByOriginId(sectionId).stream().collect(Collectors.toMap(Board::getId, Board::getTitle));
    }
    //指定的子栏目
    @GetMapping(path = "/term/list/json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public Map<Long, String> getAllTermForIdJson(
            @RequestParam("ids") String termIdString,
            HttpServletRequest request,
            Model model) {
        Set<Long> idList = Commons.toLongSet(termIdString);
        return boardService.getAllTermById(idList).collect(Collectors.toMap(Board::getId, Board::getTitle));
    }
    // 子栏目目录名称唯一性检查
    @GetMapping(path = "/term/direct/unique")
    public ResponseEntity<String> checkTermDirectNames(
            @RequestParam("direct") String termDirectoryNames,
            @RequestParam("record") long termId,
            HttpServletRequest request,
            Model model) {
        String tipMessage;
        boolean symbol = false;
        Optional<Boolean> result = boardService.checkTermDirectNameUnique(termDirectoryNames, termId);
        if (result.orElse(false)) {
            tipMessage = result.get() ? "可以使用" : "未知的错误";
            symbol = true;
        } else {
            tipMessage = "目录名称唯一性检测失败";
        }
        //
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.set("Content-Type", "text/plain; charset=UTF-8");
        HttpStatus hs = symbol ? HttpStatus.OK : HttpStatus.BAD_REQUEST;
        return new ResponseEntity<>(tipMessage, responseHeaders, hs);
    }
    
    //子栏目最近的文章
    @GetMapping(path = "/article")
    public String articlePage(
            HttpServletRequest request,
            Model model) {
        List<Topic> rs = topicService.getRecentTermArticle(pageSize).collect(Collectors.toList());
        model.addAttribute("rs", rs);
        return "admin/section/article";
    }
    //子栏目下的文章
    @GetMapping(path = "/article/list/{id}.xhtml")
    public String articleListPage(
            @PathVariable("id") long termId,
            @RequestParam(value = "p", required = false, defaultValue = "1") int page,
            HttpServletRequest request,
            Model model) {
        Board term = boardService.get(termId).orElseThrow(()->new ResourceNotFoundException("子栏目不存在或暂时无法访问"));
        FrontPageURL fpbuild = new FrontPageURL(request.getContextPath() + "/section/article/list/" + termId + ".xhtml").addPageSize("number", pageSize);
        Pageable pr = new PageRequest(page, fpbuild.getPageSize());
        Page<Topic> rs = topicService.getTermArticle(termId, pr);
        model.addAttribute("rs", rs.getResult().collect(Collectors.toList()));
        model.addAttribute("pageData", fpbuild.toPageData(pr, rs.getTotalElements()));
        model.addAttribute("term", term);
        return "admin/section/article_list";
    }
    //文章内容页
    @GetMapping(path = "/article/{id}.xhtml")
    public String articleViewPage(
            @PathVariable("id") long articleId,
            HttpServletRequest request,
            Model model) {
        TopicReplica article = topicService.getTermArticleContent(articleId, imageIOMeta).orElseThrow(()->new ResourceNotFoundException("文章不存在或暂时无法访问"));
        model.addAttribute("article", article);
        return "admin/section/article_view";
    }
    
    //新文章
    @GetMapping(path = "/article/publish")
    public String createArticleForm(
            @RequestParam(name = "section", required = false, defaultValue = "-1") int sectionId,
            @RequestParam(name = "term", required = false, defaultValue = "0") long termId,
            HttpServletRequest request,
            Model model) {
        TopicPublishForm form = new TopicPublishForm();
        form.setBoard(termId + "");
        form.setVolumes(sectionId + "");
        model.addAttribute("form", form);
        return "admin/section/article_create";
    }
    
    @PostMapping(path = "/article/publish")
    public String createArticleAction(
            @ModelAttribute("form") TopicPublishForm form,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        int sectionId = form.getIntegerVolumes();
        long termId = form.getLongBoard();
        //
        if (termId > 0 && sectionId > 0) { //有可能在默认分组中
            ActionEventCulpritor aec = AdminHomeController.getActionCulpritor(mbean.getMid(), mbean.getNickname(), request, form.getToken());
            long id = topicService.createTermArticle(
                    sectionId,
                    termId,
                    form.getTitle(),
                    form.getContent(),
                    imageIOMeta,
                    aec);
            if (id>0) {
                return "redirect:/section/article/" + id + ".xhtml";
            }
        }
        model.addAttribute("form", form);
        model.addAttribute("errors", "发布文章操作失败");
        return "admin/section/article_create";
    }
    //编辑文章
    @GetMapping(path = "/article/modify")
    public String modifyArticleForm(
            @RequestParam("id") long articleId,
            HttpServletRequest request,
            Model model) {
        TopicReplica article = topicService.getTermArticleContent(articleId, imageIOMeta).orElseThrow(()->new ResourceNotFoundException("文章不存在或暂时无法访问"));
        TopicPublishForm form = new TopicPublishForm();
        form.setBoard(article.getBoardId() + "");
        form.setVolumes(article.getVolumesId() + "");
        form.setRecord(article.getId());
        //只允许编辑这个项
        form.setTitle(article.getTitle());
        form.setContent(article.getContent().getContent());
        model.addAttribute("form", form);
        return "admin/section/article_modify";
    }
    
    @PostMapping(path = "/article/modify")
    public String modifyArticleAction(
            @ModelAttribute("form") TopicPublishForm form,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        ActionEventCulpritor aec = AdminHomeController.getActionCulpritor(mbean.getMid(), mbean.getNickname(), request, form.getToken());
        boolean symbol = topicService.editTermArticle(
                form.getLongRecord(),
                form.getTitle(),
                form.getContent(),
                imageIOMeta,
                aec).orElse(false);
        if (symbol) {
            return "redirect:/section/article/" + form.getLongRecord() + ".xhtml";
        }
        model.addAttribute("form", form);
        model.addAttribute("errors", "编辑文章操作失败");
        return "admin/section/article_modify";
    }
    
    //删除文章
    @PostMapping(path = "/article/remove", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public TipMessage removeArticleAction(
            @RequestParam("id") long articleId,
            @RequestParam("term") long termId,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        ActionEventCulpritor aec = AdminHomeController.getActionCulpritor(mbean.getMid(), mbean.getNickname(), request, "");
        return TipMessage.Builder.take(()->topicService.removeTermArticle(articleId, termId, aec)).success("文章删除成功").error("操作失败");
    }
}