package me.qwq.doghouse.controller.admin;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;

import me.qwq.doghouse.controller.common.BaseController;
import me.qwq.doghouse.entity.User;
import me.qwq.doghouse.entity.Comment;
import me.qwq.doghouse.entity.config.CommentConfig;
import me.qwq.doghouse.entity.Post;
import me.qwq.doghouse.enums.CommentAction;
import me.qwq.doghouse.enums.CommentStatusEnum;
import me.qwq.doghouse.exception.RException;
import me.qwq.doghouse.pojo.bo.IpInfo;
import me.qwq.doghouse.pojo.dto.LayPageReq;
import me.qwq.doghouse.pojo.dto.LayPageResp;
import me.qwq.doghouse.pojo.dto.R;
import me.qwq.doghouse.service.CommentService;
import me.qwq.doghouse.service.IpService;
import me.qwq.doghouse.service.MailService;
import me.qwq.doghouse.service.post.PostService;
import me.qwq.doghouse.util.GeoIPUtil;
import me.qwq.doghouse.util.SessionUtils;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import java.util.Objects;


/**
 * 评论管理
 * 
 */
@Controller
@RequestMapping("/admin/v2/comment")
public class CommentController extends BaseController {

    @Autowired
    private PostService postService;
    
    @Autowired
    private CommentService commentService;

    @Autowired
    CommentConfig commentConfig;
    
    @Autowired
    MailService mailService;
    
    @Autowired
    IpService ipService;

    @GetMapping({"", "/", "/index"})
    public String index(Long postId) {
        request.setAttribute("title", "评论管理");
        if (postId != null) {
            Post post = postService.getById(postId);
            if (post != null) {
                request.setAttribute("postId", postId);
                request.setAttribute("title", post.getPostTitle() + " 的评论管理");
            }
        }
        return "admin/comment/index";
    }

    /**
     * 更新评论
     * @param comment
     * @param bindingResult
     * @return
     */
    @ResponseBody
    @PostMapping("/update")
    public R<String> update(Comment comment, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new RException(HttpStatus.BAD_REQUEST, bindingResult.getAllErrors().get(0).getDefaultMessage());
        }
        if (Objects.isNull(comment) || Objects.isNull(comment.getId())) {
            return R.status(HttpStatus.BAD_REQUEST);
        }
        
        LambdaUpdateWrapper<Comment> uw = new LambdaUpdateWrapper<>();
        uw.eq(Comment::getId, comment.getId())
          .set(Comment::getAuthor, comment.getAuthor())
          .set(Comment::getEmail, comment.getEmail())
          .set(Comment::getUrl, comment.getUrl())
          .set(Comment::getContent, comment.getContent())
          .set(Comment::isMarkdown, comment.isMarkdown());
        
        if (commentService.update(uw)) {
            comment = commentService.getById(comment.getId());
            mailService.addOrUpdateSendQueue(comment);
            return R.status(HttpStatus.OK);
        }
        return R.status(HttpStatus.INTERNAL_SERVER_ERROR);
    }
    
    /**
     * 管理员回复
     * @param id
     * @param content
     * @param markdown
     * @return
     */
    @ResponseBody
    @PostMapping("/reply")
    public R<?> reply(Long id, String content, Boolean markdown) {
        if (StringUtils.isBlank(content) || id == null) {
            throw RException.badRequest();
        }
        User user = SessionUtils.getUser(session);
        Comment comment = commentService.getById(id);
        if (comment == null) {
            return R.ok("回复的评论已不存在");
        }
        
        if (markdown == null) markdown = false;
        
        if (markdown && !commentConfig.isMarkdownOn()) {
            throw RException.badRequest("当前评论设置未开启 Markdown，请先开启 Markdown");
        }
        
        Comment myComment = new Comment()
            .setAgent(request.getHeader("User-Agent"))
            .setAuthor(user.getNickname())
            .setCommentStatus(CommentStatusEnum.RELEASED)
            .setContent(content)//StringEscapeUtils.escapeEcmaScript())
            .setEmail(user.getEmail())
            .setIp(ipService.getClientIp(request))
            .setPostId(comment.getPostId())
            .setReplyTo(id)
            .setUrl(user.getSite())
            .setMarkdown(commentConfig.isMarkdownOn() && markdown);
        
        if (commentService.save(myComment)) {
            mailService.addOrUpdateSendQueue(myComment);
            return R.ok();
        }
        throw RException.internalServerError("回复失败");
    }
    
    /**
     * 转到对应 Post 的评论页
     * @param id
     * @return
     */
    @GetMapping("/jumpTo")
    public String jumpToPostPage(Long id) {
        return "redirect:" + commentService.getJumpToUrl(id);
    }

    /**
     * 评论分页列表
     *
     * @param pageReq 分页参数
     * @param condition   筛选条件
     * @return {@code me.qwq.doghouse.pojo.dto.LayPageResp<?>}
     */
    @ResponseBody
    @GetMapping("/list")
    public LayPageResp<?> getCommentList(
            LayPageReq<Comment> pageReq, Comment condition) {
        
        MPJLambdaWrapper<Comment> ew = new MPJLambdaWrapper<Comment>()
                .selectAll(Comment.class)
                .selectAll(Post.class)
                .leftJoin(Post.class, Post::getPostId, Comment::getPostId)
                // TODO xxx
                //.likeOrEqNotNull(condition)
                .eq(Objects.nonNull(condition.getPostId()), Comment::getPostId, condition.getPostId())
                .eq(Objects.nonNull(condition.getCommentStatus()), Comment::getCommentStatus, condition.getCommentStatus())
                
                .eq(Comment::getIsDeleted, false)
                .orderByDesc(Comment::getCreateTime);
        
        Page<Comment> page = commentService.page(pageReq, ew);
        
        // 查询 IP 归属地
        for (Comment comment : page.getRecords()) {
            IpInfo ipInfo = new IpInfo().setIp(comment.getIp());
            GeoIPUtil.queryIpInfoGeoLite(ipInfo);
            comment.setIpInfo(ipInfo);
        }
        
        LayPageResp<Comment> result = new LayPageResp<Comment>(page);
        return result;
    }
    

    /**
     * 评论批量操作
     *
     * @param blogInfo
     * @return me.qwq.doghouse.pojo.dto.R
     * @date 2019/8/29 12:22
     */
    @ResponseBody
    @PostMapping("/batchOp")
    public R<?> batchOp(
            @RequestParam("ids[]")
            Long[] ids, CommentStatusEnum op) {
        
        if (Objects.isNull(ids) || ids.length == 0) {
            throw RException.badRequest("提供的评论 ID 不能为空");
        }
        
        LambdaUpdateWrapper<Comment> uw =
                new LambdaUpdateWrapper<Comment>()
                .in(Comment::getId, (Object[])ids);
        
        if (Objects.isNull(op)) {
            uw.set(Comment::getIsDeleted, true);
        }
        else {
            uw.set(Comment::getCommentStatus, op);
        }
        if (commentService.update(uw)) {
            for (Comment comment : commentService.list(
             new LambdaQueryWrapper<Comment>()
              .in(Comment::getId, (Object[])ids))) {
               mailService.addOrUpdateSendQueue(comment);
            }
            return R.ok();
        }
        throw RException.internalServerError("批量操作失败");
    }
    
    /**
     * 设置封禁 IP 或 emial
     * @param ip
     * @param email
     * @return
     */
    @ResponseBody
    @PostMapping("/block")
    public R<?> block(@RequestParam(required=false) String ip, @RequestParam(required=false) String email) {
        if (StringUtils.isAllBlank(ip, email)) {
            throw RException.badRequest();
        }
        
        commentConfig
                .addBlockEmail(email)
                .addBlockIp(ip);
        if (commentConfig.saveOrUpdate()) {
            if (commentConfig.getBlockEmailAction() == CommentAction.NONE || commentConfig.getBlockIpAction() == CommentAction.NONE) {
                return R.ok(
                    "封禁成功，但您未设置触发封禁后的动作<br>" + 
                    "请前往 <b>设置</b> >> <b>评论设置</b> 进行设置");
            }
            return R.ok();
        }
        throw RException.internalServerError("设置封禁失败");
    }

}
