package com.qxgmat.controller.api;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.nuliji.tools.*;
import com.nuliji.tools.exception.ParameterException;
import com.nuliji.tools.exception.SystemException;
import com.qxgmat.data.constants.enums.QuestionType;
import com.qxgmat.data.constants.enums.SettingKey;
import com.qxgmat.data.constants.enums.module.PaperModule;
import com.qxgmat.data.constants.enums.module.QuestionModule;
import com.qxgmat.data.constants.enums.status.DirectionStatus;
import com.qxgmat.data.dao.entity.*;
import com.qxgmat.data.relation.entity.UserCollectQuestionRelation;
import com.qxgmat.data.relation.entity.UserNoteQuestionRelation;
import com.qxgmat.dto.extend.UserReportExtendDto;
import com.qxgmat.dto.request.*;
import com.qxgmat.dto.request.UserNoteDto;
import com.qxgmat.dto.response.*;
import com.qxgmat.help.ShiroHelp;
import com.qxgmat.service.*;
import com.qxgmat.service.inline.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Validator;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.*;

/**
 * Created by GaoJie on 2017/10/31.
 */
@RestController
@RequestMapping("/api/my")
@Api(tags = "用户接口", description = "获取与操作当前用户信息", produces = MediaType.APPLICATION_JSON_VALUE)
public class MyController {

    @Value("${upload.local_path}")
    private String localPath;

    @Value("${upload.web_url}")
    private String webUrl;

    @Autowired
    private Validator validator;

    @Autowired
    private ShiroHelp shiroHelp;

    @Autowired
    private UsersService usersService;

    @Autowired
    private UserMessageService userMessageService;

    @Autowired
    private SettingService settingService;

    @Autowired
    private StatDayService statDayService;

    @Autowired
    private QuestionNoService questionNoService;

    @Autowired
    private UserServiceService userServiceService;

    @Autowired
    private UserCollectQuestionService userCollectQuestionService;

    @Autowired
    private UserNoteQuestionService userNoteQuestionService;

    @Autowired
    private UserAskQuestionService userAskQuestionService;

    @Autowired
    private UserFeedbackErrorService userFeedbackErrorService;

    @Autowired
    private UserQuestionService userQuestionService;

    @Autowired
    private UserReportService userReportService;

    @Autowired
    private UserPaperService userPaperService;

    @RequestMapping(value = "/email", method = RequestMethod.POST)
    @ApiOperation(value = "绑定邮箱", httpMethod = "POST")
    public Response<Boolean> email(@RequestBody @Validated UserEmailDto dto, HttpSession session, HttpServletRequest request) {
        User user = (User) shiroHelp.getLoginUser();
        usersService.edit(User.builder()
                .id(user.getId())
                .email(dto.getEmail())
                .build());
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/info", method = RequestMethod.POST)
    @ApiOperation(value = "修改用户信息", httpMethod = "POST")
    public Response<Boolean> info(@RequestBody @Validated UserInfoDto dto){
        User user = (User) shiroHelp.getLoginUser();
        usersService.edit(User.builder()
                .id(user.getId())
                .nickname(dto.getNickname())
                .avatar(dto.getAvatar())
                .build());
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/real", produces = MediaType.IMAGE_JPEG_VALUE, method = RequestMethod.POST)
    @ApiOperation(value = "实名认证", notes = "保存用户实名信息", httpMethod = "POST")
    public Response<UserRealDto> real(@RequestParam("file") MultipartFile multipartFile)  {
        if (multipartFile.isEmpty()) {
            throw new ParameterException("上传文件为空");
        }
        String contentType = multipartFile.getContentType();
        if (!contentType.contains("")) {
            throw new ParameterException("文件类型错误");
        }
        User user = (User) shiroHelp.getLoginUser();
        UserRealDto dto = new UserRealDto();

        // todo 第三方验证

        String file = UUID.randomUUID().toString();
        try {
            File dest = new File(localPath + File.separator+file);
            multipartFile.transferTo(dest);
            dto.setPhoto(webUrl+file);
            usersService.edit(User.builder()
                    .id(user.getId())
                    .realAddress(dto.getAddress())
                    .realName(dto.getName())
                    .realIdentity(dto.getIdentity())
                    .realPhoto(dto.getPhoto())
                    .build());
            return ResponseHelp.success(dto);
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseHelp.exception(new SystemException("图片上传失败"));
        }
    }

    @RequestMapping(value = "/message", method = RequestMethod.GET)
    @ApiOperation(value = "用户站内信", notes = "用户消息列表", httpMethod = "GET")
    public Response<PageMessage<UserMessage>> message(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) String type,
            @RequestParam(required = false) Integer read
    )  {
        User user = (User) shiroHelp.getLoginUser();
        Page<UserMessage> p = userMessageService.select(page, size, user.getId(), type, read);

        return ResponseHelp.success(p, page, size, p.getTotal());
    }

    @RequestMapping(value = "/message/read", method = RequestMethod.PUT)
    @ApiOperation(value = "读取消息", notes = "读取用户消息/全部", httpMethod = "PUT")
    public Response<Boolean> readMessage(@RequestBody @Validated MessageReadDto dto)  {
        User user = (User) shiroHelp.getLoginUser();

        if (dto.getAll()){
            userMessageService.clearAll(user.getId());
        }else{
            userMessageService.clear(user.getId(), dto.getId());
        }

        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/prepare", method = RequestMethod.PUT)
    @ApiOperation(value = "修改备考信息", notes = "修改用户备考信息", httpMethod = "PUT")
    public Response<Boolean> editPrepare(@RequestBody @Validated UserPrepareDto dto)  {
        User entity = Transform.dtoToEntity(dto);
        User user = (User) shiroHelp.getLoginUser();
        entity.setId(user.getId());
        usersService.edit(entity);

        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/prepare", method = RequestMethod.GET)
    @ApiOperation(value = "获取备考信息", notes = "获取备考信息及分布", httpMethod = "GET")
    public Response<UserPrepareDetailDto> getPrepare()  {
        User user = (User) shiroHelp.getLoginUser();
        User entity = usersService.get(user.getId());
        UserPrepareDetailDto dto = Transform.convert(entity, UserPrepareDetailDto.class);

        Setting setting = settingService.getByKey(SettingKey.PREPARE_INFO);
        JSONObject value = setting.getValue();
        return ResponseHelp.success(dto);
    }

    @RequestMapping(value = "/study", method = RequestMethod.GET)
    @ApiOperation(value = "获取学习记录", notes = "获取选择那天的做题信息", httpMethod = "GET")
    public Response<UserStudyDetailDto> studyTime(
            @RequestParam(required = false) String date
    )  {
        User user = (User) shiroHelp.getLoginUser();
        try {
            Date day = DateFormat.getDateInstance().parse(date);
        } catch (ParseException e) {
            throw new ParameterException("日期格式错误");
        }
        UserStudyDetailDto dto = new UserStudyDetailDto();

        // todo 获取学习统计
        return ResponseHelp.success(dto);
    }

    @RequestMapping(value = "/collect", method = RequestMethod.PUT)
    @ApiOperation(value = "添加收藏", notes = "添加收藏", httpMethod = "PUT")
    public Response<Boolean> addCollect(@RequestBody @Validated UserCollectDto dto)  {
        UserCollectQuestion entity = Transform.dtoToEntity(dto);
        User user = (User) shiroHelp.getLoginUser();
        QuestionNo questionNo = questionNoService.get(dto.getQuestionNoId());
        entity.setQuestionId(questionNo.getQuestionId());
        entity.setModule(questionNo.getModule());
        entity.setUserId(user.getId());
        userCollectQuestionService.addQuestion(entity);

        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/collect", method = RequestMethod.DELETE)
    @ApiOperation(value = "移除收藏", notes = "移除收藏", httpMethod = "DELETE")
    public Response<Boolean> deleteCollect(Integer questionNoId)  {
        User user = (User) shiroHelp.getLoginUser();
        Boolean result = userCollectQuestionService.deleteQuestion(user.getId(), questionNoId);

        return ResponseHelp.success(result);
    }

    @RequestMapping(value = "/collect/bind", method = RequestMethod.POST)
    @ApiOperation(value = "收藏组卷", notes = "收藏组卷", httpMethod = "POST")
    public Response<Boolean> bindCollect(@RequestBody @Validated UserQuestionIdsDto dto)  {
        User user = (User) shiroHelp.getLoginUser();

        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/collect/question", method = RequestMethod.GET)
    @ApiOperation(value = "获取收藏题目列表", notes = "获取收藏题目列表", httpMethod = "GET")
    public Response<PageMessage<UserCollectQuestionDto>> listCollect(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = true) String module,
            @RequestParam(required = false) String type,
            @RequestParam(required = false, name="start_time") String startTime,
            @RequestParam(required = false, name="end_time") String endTime,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session)  {
        User user = (User) shiroHelp.getLoginUser();
        PageResult<UserCollectQuestionRelation> p = userCollectQuestionService.listQuestion(page, size, user.getId(), QuestionModule.ValueOf(module), QuestionType.ValueOf(type), startTime, endTime, order, DirectionStatus.ValueOf(direction));

        List<UserCollectQuestionDto> pr = Transform.convert(p, UserCollectQuestionDto.class);

        // todo 绑定做题数据


        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/error/list", method = RequestMethod.GET)
    @ApiOperation(value = "获取错题列表", notes = "获取错题列表", httpMethod = "GET")
    public Response<PageMessage<UserQuestionListDto>> listError(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = true) String module,
            @RequestParam(required = false) Number category
    )  {
        User user = (User) shiroHelp.getLoginUser();
        PageResult<UserQuestion> p = userQuestionService.listError(page, size, user.getId());
        List<UserQuestionListDto> pr = Transform.convert(p, UserQuestionListDto.class);

        // todo 绑定数据

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/error/bind", method = RequestMethod.POST)
    @ApiOperation(value = "错题组卷", notes = "错题组卷", httpMethod = "POST")
    public Response<Boolean> bindError(@RequestBody @Validated UserErrorBindDto dto)  {
        User user = (User) shiroHelp.getLoginUser();

        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/error/clear", method = RequestMethod.POST)
    @ApiOperation(value = "错题移除", notes = "错题移除", httpMethod = "POST")
    public Response<Boolean> clearError(@RequestBody @Validated UserQuestionIdsDto dto)  {
        User user = (User) shiroHelp.getLoginUser();

        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/note", method = RequestMethod.PUT)
    @ApiOperation(value = "更新笔记", notes = "更新笔记", httpMethod = "PUT")
    public Response<Boolean> updateNote(@RequestBody @Validated UserNoteDto dto)  {
        UserNoteQuestion entity = Transform.dtoToEntity(dto);
        User user = (User) shiroHelp.getLoginUser();
        entity.setUserId(user.getId());
        QuestionNo questionNo = questionNoService.get(dto.getQuestionNoId());
        entity.setQuestionId(questionNo.getQuestionId());
        entity.setModule(questionNo.getModule());
        userNoteQuestionService.update(entity);

        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/note/list", method = RequestMethod.GET)
    @ApiOperation(value = "获取笔记列表", notes = "获取笔记列表", httpMethod = "GET")
    public Response<PageMessage<UserNoteDetailDto>> listNote(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = true) String module,
            @RequestParam(required = false) String type,
            @RequestParam(required = false, name="start_time") String startTime,
            @RequestParam(required = false, name="end_time") String endTime,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session)  {
        User user = (User) shiroHelp.getLoginUser();
        PageResult<UserNoteQuestionRelation> p = userNoteQuestionService.list(page, size, user.getId(), QuestionModule.ValueOf(module), QuestionType.ValueOf(type), startTime, endTime, order, DirectionStatus.ValueOf(direction));
        List<UserNoteDetailDto> pr = Transform.convert(p, UserNoteDetailDto.class);

        // todo 绑定数据

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/report/list", method = RequestMethod.GET)
    @ApiOperation(value = "获取报告列表", notes = "获取报告列表", httpMethod = "GET")
    public Response<PageMessage<UserPaperDto>> reportList(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = true) String module,
            @RequestParam(required = false) String type,
            @RequestParam(required = false, name="start_time") String startTime,
            @RequestParam(required = false, name="end_time") String endTime,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session)  {
        User user = (User) shiroHelp.getLoginUser();
        PageResult<UserPaper> p = userPaperService.list(page, size, user.getId(), PaperModule.ValueOf(module), QuestionType.ValueOf(type), startTime, endTime, order, DirectionStatus.ValueOf(direction));

        List<UserPaperDto> pr = Transform.convert(p, UserPaperDto.class);

        Collection paperIds = Transform.getIds(p, UserPaper.class, "id");
        // 绑定用户报告
        Map<Object, Collection<UserReport>> reportByPaper = userReportService.mapByPaper(paperIds);
        Transform.combine(pr, reportByPaper, UserPaperDto.class, "id", "reports", UserReportExtendDto.class);

        // 错题 -> 题型

        // 模考 -> 分数

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/ask", method = RequestMethod.POST)
    @ApiOperation(value = "添加提问", notes = "添加提问", httpMethod = "POST")
    public Response<Boolean> addAsk(@RequestBody @Validated UserAskDto dto)  {
        UserAskQuestion entity = Transform.dtoToEntity(dto);
        User user = (User) shiroHelp.getLoginUser();
        entity.setUserId(user.getId());
        QuestionNo questionNo = questionNoService.get(dto.getQuestionNoId());
        entity.setQuestionId(questionNo.getQuestionId());
        entity.setModule(questionNo.getModule());
        userAskQuestionService.add(entity);

        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/feedback/error", method = RequestMethod.POST)
    @ApiOperation(value = "添加勘误", notes = "添加勘误", httpMethod = "POST")
    public Response<Boolean> addFeedbackError(@RequestBody @Validated UserFeedbackErrorDto dto)  {
        UserFeedbackError entity = Transform.dtoToEntity(dto);
        User user = (User) shiroHelp.getLoginUser();
        entity.setUserId(user.getId());
        QuestionNo questionNo = questionNoService.get(dto.getQuestionNoId());
        entity.setQuestionId(questionNo.getQuestionId());
        entity.setModule(questionNo.getModule());
        userFeedbackErrorService.add(entity);

        return ResponseHelp.success(true);
    }
}
