package com.dd.admin.business.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.dd.admin.business.author.entity.Author;
import com.dd.admin.business.author.service.AuthorService;
import com.dd.admin.business.chat.domain.ChatDto;
import com.dd.admin.business.chat.domain.ChatVo;
import com.dd.admin.business.chat.entity.Chat;
import com.dd.admin.business.chat.service.ChatService;
import com.dd.admin.business.file.entity.File;
import com.dd.admin.business.file.service.FileService;
import com.dd.admin.business.follow.domain.FollowDto;
import com.dd.admin.business.follow.domain.FollowVo;
import com.dd.admin.business.follow.entity.Follow;
import com.dd.admin.business.follow.service.FollowService;
import com.dd.admin.business.history.domain.HistoryDto;
import com.dd.admin.business.history.domain.HistoryVo;
import com.dd.admin.business.history.entity.History;
import com.dd.admin.business.history.service.HistoryService;
import com.dd.admin.business.note.domain.NoteDto;
import com.dd.admin.business.note.domain.NoteVo;
import com.dd.admin.business.note.domain.ReplayMeVo;
import com.dd.admin.business.note.domain.UpMeVo;
import com.dd.admin.business.note.entity.Note;
import com.dd.admin.business.note.service.NoteService;
import com.dd.admin.business.noteImg.entity.NoteImg;
import com.dd.admin.business.noteImg.service.NoteImgService;
import com.dd.admin.business.reply.domain.ReplyDto;
import com.dd.admin.business.reply.domain.ReplyVo;
import com.dd.admin.business.reply.entity.Reply;
import com.dd.admin.business.reply.service.ReplyService;
import com.dd.admin.business.starNotes.domain.StarNotesDto;
import com.dd.admin.business.starNotes.domain.StarNotesVo;
import com.dd.admin.business.starNotes.entity.StarNotes;
import com.dd.admin.business.starNotes.service.StarNotesService;
import com.dd.admin.business.upNotes.domain.UpNotesDto;
import com.dd.admin.business.upNotes.domain.UpNotesVo;
import com.dd.admin.business.upNotes.entity.UpNotes;
import com.dd.admin.business.upNotes.service.UpNotesService;
import com.dd.admin.business.upReplys.entity.UpReplys;
import com.dd.admin.business.upReplys.service.UpReplysService;
import com.dd.admin.common.aop.operationLog.aop.OperLog;
import com.dd.admin.common.aop.operationLog.aop.OperType;
import com.dd.admin.common.exception.ApiException;
import com.dd.admin.common.model.result.ResultBean;
import com.dd.admin.common.utils.AddressUtils;
import com.dd.admin.common.utils.CommonUtil;
import com.dd.admin.common.utils.IPUtils;
import com.dd.admin.common.utils.StringUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotBlank;
import java.util.*;
import java.util.stream.Collectors;

import static com.dd.admin.common.consts.XhsConst.TRUE;
@ApiModel("笔记相关Api")
@RestController
public class AuthNoteApi {
    @Autowired
    AuthorService authorService;
    @Autowired
    HttpServletRequest request;
    @Autowired
    NoteService noteService;
    @Autowired
    FileService fileService;
    @Autowired
    NoteImgService noteImgService;
    @Value("${server.port}")
    String port;
    @Autowired
    FollowService followService;
    @Autowired
    ReplyService replyService;
    @Autowired
    HistoryService historyService;

    @ApiOperation(value = "获取所有关注笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getFollowNotes")
    @OperLog(operModule = "获取所有关注笔记",operType = OperType.QUERY,operDesc = "获取所有关注笔记")
    public ResultBean<IPage<NoteVo>> getFollowNotes() {
        String followId = String.valueOf(request.getAttribute("authorId"));
        NoteDto noteDto = new NoteDto();
        noteDto.setFollowId(followId);
        List<Follow> follows = followService.selectFollowListByFollowId(followId);

        IPage<NoteVo> pageInfo = new IPage<NoteVo>() {
            @Override
            public List<OrderItem> orders() {
                return null;
            }

            @Override
            public List<NoteVo> getRecords() {
                return null;
            }

            @Override
            public IPage<NoteVo> setRecords(List<NoteVo> records) {
                return null;
            }

            @Override
            public long getTotal() {
                return 0;
            }

            @Override
            public IPage<NoteVo> setTotal(long total) {
                return null;
            }

            @Override
            public long getSize() {
                return 0;
            }

            @Override
            public IPage<NoteVo> setSize(long size) {
                return null;
            }

            @Override
            public long getCurrent() {
                return 0;
            }

            @Override
            public IPage<NoteVo> setCurrent(long current) {
                return null;
            }
        };
        if(CollectionUtil.isNotEmpty(follows)){
            String authorIds = CommonUtil.getIds(follows, "authorId");
            noteDto.setAuthorIds(authorIds);
            pageInfo = noteService.selectNotePage(noteDto);
        }
        return ResultBean.success(pageInfo);
    }

    @ApiOperation(value = "获取所有笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/notes")
    @OperLog(operModule = "获取所有笔记",operType = OperType.QUERY,operDesc = "获取所有笔记")
    public ResultBean<IPage<NoteVo>> page(NoteDto noteDto) {
        String followId = String.valueOf(request.getAttribute("authorId"));
        noteDto.setFollowId(followId);
        IPage<NoteVo> pageInfo = noteService.selectNotePage(noteDto);
        return ResultBean.success(pageInfo);
    }

    @ApiOperation(value = "模糊查询笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getNotesLike")
    @OperLog(operModule = "模糊查询笔记",operType = OperType.QUERY,operDesc = "模糊查询笔记")
    public ResultBean<IPage<NoteVo>> getNotesLike(NoteDto noteDto) {
        IPage<NoteVo> pageInfo = noteService.selectNoteListLike(noteDto);
        return ResultBean.success(pageInfo);
    }

    //外层倒叙 回复正序
    @ApiOperation(value = "获取笔记评论")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getNoteReply")
    @OperLog(operModule = "获取笔记评论",operType = OperType.QUERY,operDesc = "获取笔记评论")
    public ResultBean<Map> getNoteReply( ReplyDto replyDto) {
        String fellowId = String.valueOf(request.getAttribute("authorId"));


        String noteId = replyDto.getNoteId();
        List<ReplyVo> replyList = replyService.selectReplyList(new ReplyDto().setNoteId(noteId).setFollowId(fellowId));
        Integer totalCount = replyList.size();
        // 先构建一个以回复ID为键，回复对象为值的Map，方便后续快速查找回复对象
        // 构建以replyId为键，ReplyVo对象为值的Map，方便后续快速查找回复对象
        Map<String, ReplyVo> replyMap = replyList.stream()
                .collect(Collectors.toMap(ReplyVo::getReplyId, reply -> reply));

        List<ReplyVo> secondLevelReplies = replyList
                .stream()
                .filter(reply ->
                        (StringUtil.isNotEmpty(reply.getParentId())||StringUtil.isNotEmpty(reply.getTopParentId()))
                ).sorted(Comparator.comparing(ReplyVo::getCreateTime)).collect(Collectors.toList());
        secondLevelReplies.forEach(replyVo -> {
            if(StringUtil.isNotEmpty(replyVo.getParentId())){
                replyVo.setParentAuthorId(replyMap.get(replyVo.getParentId()).getAuthorId());
                replyVo.setParentAuthorName(replyMap.get(replyVo.getParentId()).getAuthorName());
            }
        });

        // 获取第一层回复（topId为空且parentId也为空）
        List<ReplyVo> firstLevelReplies = replyList.stream()
                .filter(reply -> reply.getTopParentId() == null && reply.getParentId() == null)
                .collect(Collectors.toList());

        // 将第二层回复添加到对应的第一层回复下（通过topId与replyId关联）
        firstLevelReplies.forEach(firstLevelReply -> {
            String firstLevelReplyId = firstLevelReply.getReplyId();
            List<ReplyVo> relatedSecondLevelReplies = secondLevelReplies.stream()
                    .filter(secondLevelReply -> firstLevelReplyId.equals(secondLevelReply.getTopParentId()))
                    .collect(Collectors.toList());
            if (firstLevelReply.getReply() == null) {
                firstLevelReply.setReply(new ArrayList<>());
            }
            firstLevelReply.getReply().addAll(relatedSecondLevelReplies);
        });


        Map map = new HashMap();
        map.put("totalCount",totalCount);
        map.put("replys",firstLevelReplies);


        return ResultBean.success(map);
    }


    @ApiOperation(value = "获取目标博主笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getAuthorNotes")
    @OperLog(operModule = "获取目标博主笔记",operType = OperType.QUERY,operDesc = "获取目标博主笔记")
    public ResultBean<IPage<NoteVo>> getAuthorNotes(String authorId) {
        String followId = String.valueOf(request.getAttribute("authorId"));
        NoteDto noteDto = new NoteDto();
        noteDto.setFollowId(followId);
        noteDto.setAuthorId(authorId);
        IPage<NoteVo> pageInfo = noteService.selectNotePage(noteDto);
        return ResultBean.success(pageInfo);
    }

    @ApiOperation(value = "获取当前博主笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getMineNotes")
    @OperLog(operModule = "获取当前博主笔记",operType = OperType.QUERY,operDesc = "获取当前博主笔记")
    public ResultBean<IPage<NoteVo>> getMineNotes() {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        NoteDto noteDto = new NoteDto();
        noteDto.setFollowId(authorId);
        noteDto.setAuthorId(authorId);
        IPage<NoteVo> pageInfo = noteService.selectNotePage(noteDto);
        return ResultBean.success(pageInfo);
    }


    @ApiOperation(value = "获取所有点赞笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getUpNotes")
    @OperLog(operModule = "获取所有点赞笔记",operType = OperType.QUERY,operDesc = "获取所有点赞笔记")
    public ResultBean<IPage<NoteVo>> getUpNotes() {
        String followId = String.valueOf(request.getAttribute("authorId"));
        NoteDto noteDto = new NoteDto();
        noteDto.setFollowId(followId);
        noteDto.setMyUpById(followId);
        IPage<NoteVo> pageInfo = noteService.selectNotePage(noteDto);
        return ResultBean.success(pageInfo);
    }


    @ApiOperation(value = "获取所有收藏笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getStarNotes")
    @OperLog(operModule = "获取所有收藏笔记",operType = OperType.QUERY,operDesc = "获取所有收藏笔记")
    public ResultBean<IPage<NoteVo>> getStarNotes() {
        String followId = String.valueOf(request.getAttribute("authorId"));
        NoteDto noteDto = new NoteDto();
        noteDto.setFollowId(followId);
        noteDto.setMyStarById(followId);
        IPage<NoteVo> pageInfo = noteService.selectNotePage(noteDto);
        return ResultBean.success(pageInfo);
    }

    @ApiOperation(value = "创建搜索记录")
    @ApiOperationSupport(order = 1)
    @PostMapping("/api/auth/addHistory")
    @OperLog(operModule = "创建搜索记录",operType = OperType.ADD,operDesc = "创建搜索记录")
    public ResultBean addHistory(@RequestBody History history) {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        history.setAuthorId(authorId);
        historyService.save(history);
        return ResultBean.success();
    }

    @ApiOperation(value = "删除搜索记录")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/deleteHistory")
    @OperLog(operModule = "删除搜索记录",operType = OperType.ADD,operDesc = "删除搜索记录")
    public ResultBean deleteHistory() {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        LambdaUpdateWrapper<History>  deleteWrapper = new LambdaUpdateWrapper<>();
        deleteWrapper.eq(History::getAuthorId,authorId);
        historyService.remove(deleteWrapper);
        return ResultBean.success();
    }

    @ApiOperation(value = "获取搜索记录")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getHistory")
    @OperLog(operModule = "获取搜索记录",operType = OperType.ADD,operDesc = "获取搜索记录")
    public ResultBean getHistory() {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        HistoryDto history = new HistoryDto();
        history.setAuthorId(authorId);
        List<HistoryVo> historyList = historyService.selectHistoryList(history);
        return ResultBean.success(historyList);
    }

    @ApiOperation(value = "获取热搜记录")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getHotHistory")
    @OperLog(operModule = "获取热搜记录",operType = OperType.ADD,operDesc = "获取热搜记录")
    public ResultBean getHotHistory() {
        List<HistoryVo> historyList = historyService.selectHotHistoryList();
        return ResultBean.success(historyList);
    }

    @ApiOperation(value = "获取热搜笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getHotNotes")
    @OperLog(operModule = "获取热搜笔记",operType = OperType.ADD,operDesc = "获取热搜笔记")
    public ResultBean getHotNotes() {
        List<NoteVo> historyList = noteService.selectHotNoteList();
        return ResultBean.success(historyList);
    }

    @ApiOperation(value = "创建笔记")
    @ApiOperationSupport(order = 1)
    @PostMapping("/api/auth/addNote")
    @OperLog(operModule = "创建笔记",operType = OperType.ADD,operDesc = "创建笔记")
    public ResultBean addNote(@RequestBody NoteDto noteDto) {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        Author author = authorService.getById(authorId);

        Note note = BeanUtil.copyProperties(noteDto, Note.class);
        note.setAuthorId(author.getAuthorId());
        note.setAuthorName(author.getAuthorName());
        note.setIpAddress(IPUtils.getIpAddr(request)); // 请求IP
        note.setIpRealAddress(AddressUtils.getRealAddress(note.getIpAddress()));
        noteService.save(note);

        List<String> imgs = noteDto.getImgs();
        List<NoteImg> noteImgList = new ArrayList<>();
        for(int i=0;i<imgs.size();i++){
            NoteImg noteImg = new NoteImg();
            noteImg.setAuthorId(authorId);
            noteImg.setNoteId(note.getNoteId());
            noteImg.setImgSort(i);
            File file = fileService.selectFileByFileId(imgs.get(i));
            String serverName = request.getServerName();
            System.out.println(serverName);
            noteImg.setImgUrl("http://" + serverName + ":" + port + file.getFilePath());
            noteImgList.add(noteImg);
        }
        noteImgService.saveBatch(noteImgList);

        Note updateNote = noteService.getById(note.getNoteId());
        updateNote.setFirstPicture(noteImgList.get(0).getImgUrl());
        noteService.updateById(updateNote);
        return ResultBean.success();
    }


    @ApiOperation(value = "修改笔记")
    @ApiOperationSupport(order = 1)
    @PostMapping("/api/auth/updateNote")
    @OperLog(operModule = "修改笔记",operType = OperType.ADD,operDesc = "修改笔记")
    @Transactional
    public ResultBean updateNote(@RequestBody NoteDto noteDto) {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        Author author = authorService.getById(authorId);

        Note note = BeanUtil.copyProperties(noteDto, Note.class);
        note.setAuthorId(author.getAuthorId());
        note.setAuthorName(author.getAuthorName());
        note.setIpAddress(IPUtils.getIpAddr(request)); // 请求IP
        note.setIpRealAddress(AddressUtils.getRealAddress(note.getIpAddress()));
        noteService.updateById(note);

        List<String> imgs = noteDto.getImgs();
        List<NoteImg> noteImgList = new ArrayList<>();
        for(int i=0;i<imgs.size();i++){
            NoteImg noteImg = new NoteImg();
            noteImg.setAuthorId(authorId);
            noteImg.setNoteId(note.getNoteId());
            noteImg.setImgSort(i);
            File file = fileService.selectFileByFileId(imgs.get(i));
            String serverName = request.getServerName();
            System.out.println(serverName);
            noteImg.setImgUrl("http://" + serverName + ":" + port + file.getFilePath());
            noteImgList.add(noteImg);
        }
        noteImgService.deleteNoteImgByNoteId(note.getNoteId());
        noteImgService.saveBatch(noteImgList);

        Note updateNote = noteService.getById(note.getNoteId());
        updateNote.setFirstPicture(noteImgList.get(0).getImgUrl());
        noteService.updateById(updateNote);
        return ResultBean.success();
    }

    @ApiOperation(value = "删除笔记")
    @ApiOperationSupport(order = 1)
    @PostMapping("/api/auth/deleteNote")
    @OperLog(operModule = "删除笔记",operType = OperType.ADD,operDesc = "删除笔记")
    @Transactional
    public ResultBean deleteNote(@RequestBody NoteDto noteDto) {
       String noteId = noteDto.getNoteId();
       noteService.removeById(noteId);
       return ResultBean.success();
    }


    @ApiOperation(value = "获取所有收藏点赞我的笔记记录")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getUpMeNotes")
    @OperLog(operModule = "获取所有收藏点赞我的笔记记录",operType = OperType.QUERY,operDesc = "获取所有收藏点赞我的笔记记录")
    public ResultBean<IPage<UpMeVo>> getUpMeNotes() {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        IPage<UpMeVo> upMeVoIPage = noteService.selectUpMeNotes(authorId);
        return ResultBean.success(upMeVoIPage);
    }

    @ApiOperation(value = "获取所有评论我的笔记记录")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getReplayMes")
    @OperLog(operModule = "获取所有评论我的笔记记录",operType = OperType.QUERY,operDesc = "获取所有评论我的笔记记录")
    public ResultBean<IPage<UpMeVo>> getReplayMes() {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        IPage<ReplayMeVo> replyMeNotes = noteService.selectReplyMeNotes(authorId);
        return ResultBean.success(replyMeNotes);
    }
}
