package cn.com.qmth.stmms.ms.admin.api;

import cn.com.qmth.stmms.ms.admin.dto.MarkUserDTO;
import cn.com.qmth.stmms.ms.commons.web.PageableDTO;
import cn.com.qmth.stmms.ms.core.domain.MarkLog;
import cn.com.qmth.stmms.ms.core.domain.MarkStage;
import cn.com.qmth.stmms.ms.core.domain.MarkSubject;
import cn.com.qmth.stmms.ms.core.domain.user.MarkRight;
import cn.com.qmth.stmms.ms.core.domain.user.MarkUser;
import cn.com.qmth.stmms.ms.core.domain.user.Role;
import cn.com.qmth.stmms.ms.core.repository.MarkLogRepo;
import cn.com.qmth.stmms.ms.core.repository.MarkSubjectRepo;
import cn.com.qmth.stmms.ms.core.repository.MarkTaskRepo;
import cn.com.qmth.stmms.ms.core.repository.MarkUserRepo;
import cn.com.qmth.stmms.ms.core.vo.Subject;
import cn.com.qmth.stmms.ms.marking.assembler.MarkerAssembler;
import cn.com.qmth.stmms.ms.marking.dto.MarkerDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author ting.yin
 * @Description: 用户api
 * @date 2016年10月24日
 */
@RestController
@RequestMapping("api/admin/users")
public class UserApi {

    @Autowired
    private MarkUserRepo markUserRepo;

    @Autowired
    private MarkSubjectRepo markSubjectRepo;

    @Autowired
    private MarkTaskRepo markTaskRepo;

    @Autowired
    private MarkLogRepo markLogRepo;

    @Autowired
    MarkerAssembler markerAssembler;

    @RequestMapping(value = "{userId}", method = RequestMethod.DELETE)
    public void remove(@PathVariable Long userId) {
        long count = markTaskRepo.countByMarkerId(userId);
        if (count > 0) {
            throw new RuntimeException("已分配任务，不允许删除");
        }
        markUserRepo.delete(userId);
    }

    @RequestMapping(value = "{domain}", method = RequestMethod.PUT)
    public void update(@PathVariable MarkUser domain, @RequestBody MarkUser user) {
        MarkSubject markSubject = markSubjectRepo.findOne(user.getWorkId() + "-" + user.getSubject().toString());
        if (domain.getRole().equals(Role.MARKER)) {
            if (user.getWeight() - domain.getWeight() != 0 && !markSubject.getStage().equals(MarkStage.INIT)) {
                throw new RuntimeException("请在分档阶段前修改权重");
            }
            if (!(user.getWeight() >= 1)) {
                throw new RuntimeException("评卷员权重必须大于1");
            }
        }
        domain.setName(user.getName());
        domain.setMarkRight(user.getMarkRight());
        domain.setWeight(user.getWeight());
        domain.setOneClickLevel(user.getOneClickLevel());
        domain.setStandardVolume(user.getStandardVolume());
        domain.setLevelCallback(user.getLevelCallback());
        markUserRepo.save(domain);
    }

    @RequestMapping(method = RequestMethod.POST)
    public void create(HttpServletRequest request, @RequestBody MarkUser user) {
        Long organizationId = Long.valueOf(request.getHeader("organizationId"));
        MarkSubject markSubject = markSubjectRepo.findOne(user.getWorkId() + "-" + user.getSubject().toString());
        if (markSubject == null) {
            throw new RuntimeException("该科目不存在");
        }
        if (user.getRole() == Role.MARKER && user.getMarkRight() == MarkRight.ALLOW_LEVELING && !markSubject.getStage().equals(MarkStage.INIT)) {
            throw new RuntimeException("请进入分档阶段前创建");
        }
        MarkUser markUser = markUserRepo.findByLoginName(user.getLoginName());
        if (markUser != null) {
            throw new RuntimeException("该登录名已经存在");
        }
        user.setLoginName(user.getLoginName());
        //非科组长
        if (!Objects.equals(user.getRole().name(), Role.MARK_LEADER.name())) {
            user.setOneClickLevel(false);
            user.setStandardVolume(false);
            user.setLevelCallback(false);
        }
        user.setOrganizationId(organizationId);
        markUserRepo.save(user);
    }

    @RequestMapping(method = RequestMethod.GET)
    public List<MarkUser> list(@RequestParam Long workId,
                               @RequestParam Subject subject,
                               @RequestParam(required = false) Role role) {
        if (role != null) {
            return markUserRepo.findByWorkIdAndRole(workId, role).stream().filter(u -> u.getSubject() == subject)
                    .collect(Collectors.toList());
        } else {
            return markUserRepo.findByWorkId(workId).stream().filter(u -> u.getSubject() == subject && (Objects.equals(u.getRole().name(), Role.MARKER.name()) || Objects.equals(u.getRole().name(), Role.MARK_LEADER.name())))
                    .collect(Collectors.toList());
        }
    }

    /**
     * 采集员列表查询
     *
     * @param role
     * @return
     */
    @RequestMapping(value = "collect", method = RequestMethod.GET)
    public PageableDTO listCollect(HttpServletRequest request,@RequestParam Long workId, @RequestParam(required = false, defaultValue = "COLLECTOR") Role role, Pageable pageable) {
//        return markUserRepo.findByRole(role);

        Long organizationId = Long.valueOf(request.getHeader("organizationId"));

        Specification<MarkUser> specification = (root, query, builder) -> {
            List<Predicate> predicates = new ArrayList<>();
            predicates.add(builder.equal(root.get("role"), role));
            predicates.add(builder.equal(root.get("workId"), workId));
            predicates.add(builder.equal(root.get("organizationId"), organizationId));
            return builder.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        Page<MarkUser> markUsers = markUserRepo.findAll(specification, pageable);
        List<MarkerDTO> userDTOList = new ArrayList<>();
        markUsers.getContent().forEach(m -> {
            userDTOList.add(markerAssembler.toScanDTO(m));
        });
        return new PageableDTO(userDTOList, markUsers.getTotalElements(), markUsers.getTotalPages(), pageable.getPageNumber());
    }

    /**
     * 采集员新增
     *
     * @param user
     */
    @RequestMapping(value = "collect", method = RequestMethod.POST)
    public void collect(HttpServletRequest request, @RequestBody MarkUser user) {
        Long organizationId = Long.valueOf(request.getHeader("organizationId"));
        MarkUser markUser = markUserRepo.findByLoginName(user.getLoginName());
        if (markUser != null) {
            throw new RuntimeException("该账号已经存在");
        }
        user.setName(user.getLoginName());
        //采集员
        user.setRole(Role.COLLECTOR);
        //非空字段，随便设值，实际没用到
        user.setSubject(Subject.SC);
        user.setOneClickLevel(false);
        user.setStandardVolume(false);
        user.setLevelCallback(false);
        user.setOrganizationId(organizationId);
        markUserRepo.save(user);
    }

    /**
     * 采集员修改
     *
     * @param domain
     * @param user
     */
    @RequestMapping(value = "collect/{domain}", method = RequestMethod.PUT)
    public void updateCollect(@PathVariable MarkUser domain, @RequestBody MarkUser user) {
        //开始采集，不能修改
        List<MarkLog> list = markLogRepo.findByCreateUserId(domain.getId());
        if (list != null && list.size() > 0 && !domain.getLoginName().equals(user.getLoginName())) {
            throw new RuntimeException("已有采集记录，不能修改账号");
        }
        MarkUser markUser = markUserRepo.findByLoginName(user.getLoginName());
        if (markUser != null && !domain.getId().equals(markUser.getId())) {
            throw new RuntimeException("该账号已经存在");
        }
        //启用禁用
        if(domain.isEnabled() != user.isEnabled()){
            domain.setEnabled(user.isEnabled());
        } else {
            //修改用户名、密码
            domain.setLoginName(user.getLoginName());
            domain.setName(user.getLoginName());
            domain.setPassword(user.getPassword());
        }
        markUserRepo.save(domain);
    }

    /**
     * 采集员删除
     *
     * @param userId
     */
    @RequestMapping(value = "collect/{userId}", method = RequestMethod.DELETE)
    public void removeCollect(@PathVariable Long userId) {
        //开始采集，不能删除
        List<MarkLog> list = markLogRepo.findByCreateUserId(userId);
        if (list != null && list.size() > 0) {
            throw new RuntimeException("已有采集记录，不能删除");
        }
        //默认采集账号，不能删除
        MarkUser markUser = markUserRepo.findOne(userId);
        if (Objects.equals(Role.COLLECTOR.name(), markUser.getRole().name()) && Objects.nonNull(markUser.getDefaultAccount()) && markUser.getDefaultAccount()) {
            throw new RuntimeException("系统默认采集账号，不能删除");
        }
        markUserRepo.delete(userId);
    }


    /**
     * 纪检员/质检列表查询
     *
     * @param role
     * @return
     */
    @RequestMapping(value = "inspection", method = RequestMethod.GET)
    public List<MarkUser> listInspection(HttpServletRequest request, @RequestParam(required = false, defaultValue = "INSPECTION") Role role) {
        Long organizationId = Long.valueOf(request.getHeader("organizationId"));
        return markUserRepo.findByOrganizationIdAndRoleIn(organizationId, role, Role.QC);
    }

    /**
     * 纪检员首次登录修改密码、纪检员重置密码
     *
     * @param userId
     * @param password
     * @return
     */
    @RequestMapping(value = "inspection/updatePwd", method = RequestMethod.POST)
    public ResponseEntity updatePwd(@RequestParam Long userId, @RequestParam(defaultValue = "123456") String password) {
        MarkUser markUser = markUserRepo.findOne(userId);
        markUser.setPassword(password);
        markUser.setPwChangedCount(markUser.getPwChangedCount() + 1);
        markUserRepo.saveAndFlush(markUser);

        return new ResponseEntity(HttpStatus.OK);
    }

}
