package com.sysu.admin.support.system.user;

import com.google.common.base.Objects;
import com.google.common.collect.Maps;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.QBean;
import com.querydsl.jpa.impl.JPAQuery;
import com.sysu.admin.support.system.organ.Organ;
import com.sysu.admin.support.system.organ.OrganRepository;
import com.sysu.admin.support.base.BaseVo;
import com.sysu.admin.support.base.ServiceContext;
import com.sysu.admin.support.system.role.SRole;
import com.sysu.admin.support.system.role.SRoleRepository;
import com.sysu.admin.utils.i18n.MessageUtils;
import com.xiesx.fastboot.base.pagination.PaginationHelper;
import com.xiesx.fastboot.base.pagination.PaginationResult;
import com.xiesx.fastboot.base.pagination.PaginationVo;
import com.xiesx.fastboot.base.result.BaseResult;
import com.xiesx.fastboot.base.result.R;
import com.xiesx.fastboot.core.exception.RunException;
import com.sysu.admin.support.system.organ.QOrgan;
import com.sysu.admin.support.system.role.QSRole;
import com.sysu.admin.support.system.user_role.PKUR;
import com.sysu.admin.support.system.user_role.QUserRole;
import com.sysu.admin.support.system.user_role.UserRole;
import com.sysu.admin.support.system.user_role.UserRoleRepository;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.Map;

/**
 * @title UserController
 * @description
 * @author XIE
 * @date 2020年4月24日下午10:08:02
 */
@Validated
@Controller
@RequestMapping(value = "user/")
public class UserController extends ServiceContext {

    @Autowired
    UserRepository mUserRepository;

    @Autowired
    SRoleRepository mRoleRepository;

    @Autowired
    UserRoleRepository mUserRoleRepository;

    @Autowired
    OrganRepository mOrganRepository;

    /**
     * 页面
     *
     * @return
     */
    @RequestMapping(value = "index")
    public String index() {
        return "system/user/index";
    }

    /**
     * 页面
     *
     * @return
     */
    @RequestMapping(value = "indexTree")
    public String indexTree() {
        return "system/user/indexTree";
    }

    /**
     * 分页
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "tree")
    @RequiresPermissions("user:view")
    public Map<String, Object> tree() {
        QOrgan qOrgan = QOrgan.organ;
        QUser qUser = QUser.user;
        QSRole qRole = QSRole.sRole;
        QUserRole qUserRole = QUserRole.userRole;
        // 条件
        Predicate predicate = qUser.id.isNotNull();

        User currentUser = mShiroService.getCurrentUser();

        //县级执法权限可以看下级的部门
        if(mShiroService.isXjzf()){
            predicate = ExpressionUtils.and(predicate, qOrgan.parentId.eq(currentUser.getOrganId()));
        }

        // 查询字段
        QBean<User> selectBean = Projections.fields(User.class, qUser.id.longValue(), qUser.username, qUser.nickname,
                qUser.isEnable, qUser.createDate, qUser.updateDate, qRole.id.longValue().as(User.FIELDS.roleId),
                qRole.name.as(User.FIELDS.roleName),qOrgan.company.as(User.FIELDS.organName),qOrgan.id.as(User.FIELDS.organId));
        // 构造查询
        JPAQuery<User> jpaQuery = mJPAQueryFactory.select(selectBean)
                .from(qUser)
                .leftJoin(qUserRole)
                .on(qUser.id.eq(qUserRole.pk.users))
                .leftJoin(qRole)
                .on(qRole.id.eq(qUserRole.pk.roles))
                .leftJoin(qOrgan)
                .on(qOrgan.id.eq(qUser.organId))
                .where(predicate);
        List<User> userList = jpaQuery.fetch();

        List<UserTreeNode> userTreeNodes = UserTreeNodeUtil.UserToTreeNode(userList);

        Map<String, Object> maps = Maps.newHashMap();
        maps.put("code", 0);
        maps.put("msg", MessageUtils.get("OP_MSG_SUCC"));
        maps.put("count", userTreeNodes.size());
        maps.put("data", userTreeNodes);
        return maps;
    }

    /**
     * 分页
     * @param base
     * @param page
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "page")
    @RequiresPermissions("user:view")
    public PaginationResult page(BaseVo base, PaginationVo page) {
        User currentUser = mShiroService.getCurrentUser();
        // 对象
        QOrgan qOrgan = QOrgan.organ;
        QUser qUser = QUser.user;
        QSRole qRole = QSRole.sRole;
        QUserRole qUserRole = QUserRole.userRole;
        // 条件
        Predicate predicate = new BooleanBuilder();

        if (ObjectUtils.isNotEmpty(base.getKeyword())) {
            Predicate p1 = qUser.id.like("%" + base.getKeyword() + "%");
            Predicate p2 = qUser.username.likeIgnoreCase("%" + base.getKeyword() + "%");
            Predicate p3 = qUser.nickname.likeIgnoreCase("%" + base.getKeyword() + "%");
            predicate = ExpressionUtils.and(predicate, ExpressionUtils.anyOf(p1, p2, p3));
        }

        // 分页
        Pageable pageable = PageRequest.of(page.getPage(), page.getLimit(), Sort.by(Direction.DESC, User.FIELDS.createDate));
        // 查询字段
        QBean<User> selectBean = Projections.fields(User.class, qUser.id.longValue(), qUser.username, qUser.nickname,
                qUser.isEnable, qUser.createDate, qUser.updateDate, qRole.id.longValue().as(User.FIELDS.roleId),
                qRole.name.as(User.FIELDS.roleName),qOrgan.company.as(User.FIELDS.organName));
        // 构造查询
        JPAQuery<User> jpaQuery = mJPAQueryFactory.select(selectBean)
                .from(qUser)
                .leftJoin(qUserRole)
                .on(qUser.id.eq(qUserRole.pk.users))
                .leftJoin(qRole)
                .on(qRole.id.eq(qUserRole.pk.roles))
                .leftJoin(qOrgan)
                .on(qOrgan.id.eq(qUser.organId))
                .where(predicate);
        // 分页查询
        Page<User> data = mUserRepository.findAll(jpaQuery, pageable);
        //
        return PaginationHelper.create(data);
    }

    /**
     * 用户选择
     * @param base
     * @param page
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "select")
    @RequiresPermissions("user:view")
    public PaginationResult select(BaseVo base, PaginationVo page) {
        User currentUser = mShiroService.getCurrentUser();
        // 对象
        QOrgan qOrgan = QOrgan.organ;
        QUser qUser = QUser.user;
        // 条件
        Predicate predicate = new BooleanBuilder();

        if(mShiroService.isXjzf()){
            List<Long> ids = mOrganRepository.findIdByParentId(currentUser.getOrganId());
            ids.add(currentUser.getOrganId());
            predicate = ExpressionUtils.and(predicate, qUser.organId.in(ids));
        }
        //镇级可以看到自己下面的任务
        if(mShiroService.isZjxc()){
            predicate = ExpressionUtils.and(predicate, qUser.organId.eq(currentUser.getOrganId()));
        }

        if (ObjectUtils.isNotEmpty(base.getKeyword())) {
            Predicate p1 = qUser.id.like("%" + base.getKeyword() + "%");
            Predicate p2 = qUser.username.likeIgnoreCase("%" + base.getKeyword() + "%");
            Predicate p3 = qUser.nickname.likeIgnoreCase("%" + base.getKeyword() + "%");
            predicate = ExpressionUtils.and(predicate, ExpressionUtils.anyOf(p1, p2, p3));
        }


        // 分页
        Pageable pageable = PageRequest.of(page.getPage(), page.getLimit(), Sort.by(Direction.DESC, User.FIELDS.createDate));
        // 查询字段
        QBean<User> selectBean = Projections.fields(User.class, qUser.id.longValue(), qUser.username, qUser.nickname,
                qUser.isEnable, qUser.createDate, qUser.updateDate,qOrgan.company.as(User.FIELDS.organName));
        // 构造查询
        JPAQuery<User> jpaQuery = mJPAQueryFactory.select(selectBean)
                .from(qUser)
                .leftJoin(qOrgan)
                .on(qOrgan.id.eq(qUser.organId))
                .where(predicate);
        // 分页查询
        Page<User> data = mUserRepository.findAll(jpaQuery, pageable);
        //
        return PaginationHelper.create(data);
    }

    /**
     * 详情
     * @param base
     * @param model
     * @return
     * @throws RunException
     */
    @RequestMapping(value = "form")
    @RequiresPermissions("user:view")
    public String form(BaseVo base, Model model) {
        User user = new User().setId(base.getId());
        List<SRole> sRoles = mRoleRepository.findAll();
        if (!Objects.equal(user.getId(), -1L)) {
            user = mUserRepository.findOne(user.getId());
            Organ organ = mOrganRepository.findOne(user.getOrganId());
            user.setOrganName(organ.getCompany());
        }

        model.addAttribute("user", user);
        model.addAttribute("json", user.toJSONString());
        if(Objects.equal(user.getId(), -1L)){
            Organ organ = mShiroService.getCurrentOrgan();
            user.setOrganId(organ.getId()).setOrganName(organ.getCompany());
            model.addAttribute("userRoles", new UserRole[]{ new UserRole().setPk(new PKUR().roles(4L))});// 这里用户对角色1v1
        }else {
            model.addAttribute("userRoles", mUserRoleRepository.getRoleByUsers(user.getId()));// 这里用户对角色1v1
        }
        model.addAttribute("roles", sRoles);
        return "system/user/form";
    }

    /**
     * 添加/修改用户信息
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "submit")
    @RequiresPermissions("user:update")
    public BaseResult submit(BaseVo base, @Validated User req, String pwd) {
        User user = new User().setId(req.getId());
        //根据传入的用户id 是不是-1来判断是添加还是更新
        if (Objects.equal(user.getId(), -1L)) {
            BeanUtils.copyProperties(req, user);
            user.setCode(pwd);
            user.setPassword(DigestUtils.md5Hex(req.getUsername() + pwd));
        } else {
            //获取用户
            user = mUserRepository.findOne(user.getId());
            if (ObjectUtils.isNotEmpty(user)) {
                // 当前帐号/密码是否发生变动
                if (!user.getUsername().equals(req.getUsername())) {
                    user.setUsername(req.getUsername());
                }
                if (ObjectUtils.isNotEmpty(pwd) && (pwd = pwd.trim()).length() > 0) {
                    user.setCode(pwd);
                    String password = DigestUtils.md5Hex(req.getUsername() + pwd);
                    user.setPassword(password);
                }
                user.setNickname(req.getNickname());
                user.setOrganId(req.getOrganId());
            }

        }

        if(mUserRepository.findFirstByUsernameAndIdNot(req.getUsername(), req.getId()) != null){
            throw new RuntimeException(MessageUtils.get("user.repet_username"));
        }

        // 先保存
        user = mUserRepository.saveAndFlush(user);
        //  更新用户的角色权限
        List<UserRole> userRoles = mUserRoleRepository.getRoleByUsers(user.getId());
        for (UserRole userRole : userRoles) {
            mUserRoleRepository.delete(userRole);
        }
        for (Long roleId : base.getIds()) {
            UserRole userRole = new UserRole().setPk(new PKUR().users(user.getId()).roles(roleId));
            mUserRoleRepository.save(userRole);
        }
        return R.succ();
    }

    /**
     * 修改启用
     *
     * @param base
     * @param base
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "updateEnable")
    @RequiresPermissions("user:update")
    public BaseResult updateEnable(BaseVo base) {
        Integer row = mUserRepository.enable(base.getIsEnable(), base.getId());
        return (row >= 1) ? R.succ() : R.fail();
    }

    /**
     * 删除状态
     *
     * @param base
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "delete")
    @RequiresPermissions("user:delete")
    public BaseResult delete(BaseVo base) {
        Integer row = mUserRepository.delete(base.getIds());
        return (row >= 1) ? R.succ() : R.fail();
    }
}
