package com.infoepoch.pms.dispatchassistant.controller.basic;

import com.infoepoch.pms.dispatchassistant.common.component.RedisTool;
import com.infoepoch.pms.dispatchassistant.common.component.Result;
import com.infoepoch.pms.dispatchassistant.common.constant.RedisKeys;
import com.infoepoch.pms.dispatchassistant.common.exception.NotLoginException;
import com.infoepoch.pms.dispatchassistant.common.exception.ValidationException;
import com.infoepoch.pms.dispatchassistant.common.utils.JsonUtils;
import com.infoepoch.pms.dispatchassistant.common.utils.ServletTool;
import com.infoepoch.pms.dispatchassistant.common.utils.StringUtils;
import com.infoepoch.pms.dispatchassistant.domain.basic.organization.Organization;
import com.infoepoch.pms.dispatchassistant.domain.basic.organization.OrganizationCriteria;
import com.infoepoch.pms.dispatchassistant.domain.basic.organization.OrganizationRoot;
import com.infoepoch.pms.dispatchassistant.domain.basic.organization.OrganizationService;
import com.infoepoch.pms.dispatchassistant.domain.basic.user.*;
import com.infoepoch.pms.dispatchassistant.domain.oa.user.IUserPmsRepository;
import com.infoepoch.pms.dispatchassistant.domain.oa.user.UserPms;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户管理控制层
 */
@RestController
@RequestMapping("/api/user")
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private UserQueryService userQueryService;

    @Autowired
    private Auth auth;
    @Autowired
    private RedisTool redisTool;
    @Autowired
    private OrganizationService organizationService;
    @Autowired
    private IUserPmsRepository userPmsRepository;
    @Autowired
    private IUserRepository userRepository;

    /**
     * 根据ID获取用户信息
     *
     * @param id
     * @return
     */
    @GetMapping("/get-by-id/{id}")
    public Result getById(@PathVariable String id) {
        return Result.successData(userService.getUserById(id));
    }

    /**
     * @param ids
     * @return
     */
    @PostMapping("/get-by-ids")
    public Result getByIds(@RequestBody List<String> ids) {
        return Result.successData(userService.getUsersByIds(ids));
    }

    /**
     * 分页列表
     *
     * @param criteria
     * @return
     */
    @PostMapping("/list")
    public Result pageList(@RequestBody UserCriteria criteria) throws NotLoginException {
        if (criteria.getRegionFilterFlag()) {
            // 如果开启了地区过滤，那么子公司只能查询子公司的用户
            User user = auth.getUserReq();
            if (OrganizationRoot.judgeBranchCompany(user.getOrganizationId())) {
                Organization branchCompany = OrganizationRoot.getCompanyById(user.getOrganizationId());
                criteria.setOrganizationId(branchCompany.getId());
                criteria.setBranchCompanyFlag(true);
            }
        }
        if (StringUtils.isNotBlank(criteria.getBranchCompanyId())) {
            List<String> organizationIdList = OrganizationRoot.getChildrenLoopId(criteria.getBranchCompanyId());
            criteria.setOrganizationIds(organizationIdList);
        }
        return Result.successData(userService.pageList(criteria));
    }

    @PostMapping("/popup-list")
    public Result popupList(@RequestBody UserCriteria criteria) throws NotLoginException {
        if (criteria.getRegionFilterFlag()) {
            // 如果开启了地区过滤，那么子公司只能查询子公司的用户
            User user = auth.getUserReq();
            if (OrganizationRoot.judgeBranchCompany(user.getOrganizationId())) {
                Organization branchCompany = OrganizationRoot.getCompanyById(user.getOrganizationId());
                criteria.setOrganizationId(branchCompany.getId());
                criteria.setBranchCompanyFlag(true);
            }
        }
        if (StringUtils.isNotBlank(criteria.getBranchCompanyId())) {
            Organization branchCompany = OrganizationRoot.getCompanyById(criteria.getBranchCompanyId());
            List<String> organizationIdList = OrganizationRoot.getChildrenLoopId(branchCompany.getId());
            criteria.setOrganizationIds(organizationIdList);
        }
        if (StringUtils.isNotBlank(criteria.getDepartmentId())) {
            Organization department = OrganizationRoot.getDepartmentById(criteria.getDepartmentId());
            List<String> organizationIdList = OrganizationRoot.getChildrenLoopId(department.getId());
            criteria.setOrganizationIds(organizationIdList);
        }
        //部门简称
        if (StringUtils.isNotBlank(criteria.getShortName())) {
            Organization department = OrganizationRoot.getDepartmentByShortName(criteria.getShortName());
            if(department != null) {
                List<String> organizationIdList = OrganizationRoot.getChildrenLoopId(department.getId());
                criteria.setOrganizationIds(organizationIdList);
            }
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("list", userQueryService.popupList(criteria));
        resultMap.put("totalCount", userQueryService.popupListCount(criteria));
        return Result.successData(resultMap);
    }

    @PostMapping("/save")
    public Result save(@RequestBody User user) {
        userService.save(user);
        return Result.success();
    }

    @GetMapping("/remove/{id}")
    public Result remove(@PathVariable("id") String id) {
        userService.removeById(id);
        return Result.success();
    }

    @GetMapping("/userPick")
    public Result getUserPick() {
        return Result.successData(userService.getUserPick());
    }

    /**
     * 修改密码
     *
     * @param changePassword
     * @return
     */
    @PostMapping("/change-password")
    public Result changePassword(@RequestBody ChangePassword changePassword) {
        userService.changePassword(changePassword);
        return Result.success();
    }

    /**
     * 根据组织ID查询组织用户列表
     *
     * @param orgId
     * @return
     */
    @PostMapping("/org-user-list")
    public Result orgUserList(String orgId) {
        UserCriteria criteria = new UserCriteria();
        criteria.setOrganizationIds(Collections.singletonList(orgId));
        List<User> userList = userService.queryListByCriteria(criteria);
        return Result.successData(userList);
    }

    /**
     * 刷新用户redis缓存
     *
     * @return
     */
    @GetMapping("/refresh-user")
    public Result refreshUser() {
        Set<String> allUserKeys = new HashSet<>(redisTool.keys("supermarketAllUserList*"));
        if (CollectionUtils.isNotEmpty(allUserKeys)) {
            for (String key : allUserKeys) {
                redisTool.remove(key);
            }
        }
        Set<String> userPickKeys = new HashSet<>(redisTool.keys("supermarketUserPick*"));
        if (CollectionUtils.isNotEmpty(userPickKeys)) {
            for (String key : userPickKeys) {
                redisTool.remove(key);
            }
        }
        userService.getAllUser();
        userService.getUserPick();
        return Result.success();
    }

    /**
     * 取所有组织及用户，ztree格式
     */
    @RequestMapping(value = "/mock/ztree", method = RequestMethod.GET)
    public Result getMockZtree() {
        List<Map<String, Object>> l = new ArrayList<>();
        List<User> users = userService.getAllUser();

        for (Organization o : OrganizationRoot.getRootOrganizations()) {
            appendZtreeOrganizationRecursion(l, o, users);
        }
        return Result.successData(l);
    }

    /**
     * 查询当前登录用户关联的组织列表
     *
     * @return
     */
    @GetMapping("/relate-org-list")
    public Result relateOrgList() throws NotLoginException {
        User user = auth.getUserReq();
        List<UserPms> userPmsList = userPmsRepository.selectByReference3(user.getUsername());
        if (CollectionUtils.isNotEmpty(userPmsList)) {
            List<String> orgCodeList = userPmsList.stream().map(UserPms::getOaOrgCode).distinct().collect(Collectors.toList());
            OrganizationCriteria criteria = new OrganizationCriteria();
            criteria.setOaOrgCodeList(orgCodeList);
            List<Organization> organizationList = organizationService.queryByCriteria(criteria);
            return Result.successData(organizationList);
        }
        return Result.successData(new ArrayList<>());
    }

    /**
     * 组织确认（修改用户所属组织）
     *
     * @param orgId
     * @return
     * @throws NotLoginException
     */
    @PostMapping("/org-confirm")
    public Result orgConfirm(String orgId) throws NotLoginException {
        if (StringUtils.isBlank(orgId)) {
            throw new ValidationException("确认的组织ID不可为空");
        }
        User user = auth.getUserReq();
        // 修改用户所属组织
        user.setOrganizationId(orgId);
        // 修改用户确认状态
        user.setOrgConfirmStatus(1);
        // 持久化到数据库
        userRepository.update(user);
        // 刷新redis用户缓存
        String sign = ServletTool.getSign();
        redisTool.put(RedisKeys.AUTHED_USER + sign, JsonUtils.objectToJson(user), 2, TimeUnit.HOURS);
        return Result.success();
    }

    /**
     * 递归添加组织和用户到列表
     */
    private void appendZtreeOrganizationRecursion(List<Map<String, Object>> list, Organization organization, List<User> allUsers) {
        Map<String, Object> m = new HashMap();
        m.put("id", organization.getId());
        m.put("name", organization.getName() + "/" + organization.getId());
        //m.put("open", false);
        m.put("nocheck", true);

        List<Map<String, Object>> l = new ArrayList<>();
        appendZtreeUser(l, organization.getId(), allUsers);

        if (organization.hasChildren()) {
            for (Organization o : organization.getChildren()) {
                appendZtreeOrganizationRecursion(l, o, allUsers);
            }
        }
        if (l.size() > 0)
            m.put("children", l);
        list.add(m);
    }

    /**
     * 递归添加组织和用户到列表
     */
    private void appendZtreeUser(List<Map<String, Object>> list, String organizationId, List<User> allUsers) {
        List<User> users = allUsers.stream()
                .filter(s -> s.getOrganizationId().equalsIgnoreCase(organizationId))
                .sorted(Comparator.comparing(User::getDisplayOrderValue))
                .collect(Collectors.toList());
        if (users.size() == 0)
            return;
        for (User user : users) {
            if (user.isDisabled())
                continue;

            Map<String, Object> m = new HashMap();
            m.put("id", user.getId());
            m.put("name", user.getDisplayName() + "/" + user.getId() + "/" + user.getPosition());
            //m.put("open", false);
            list.add(m);
        }
    }


    @PostMapping("/province-popup-list")
    public Result provincePopupList(@RequestBody UserCriteria criteria) throws NotLoginException {

        List<Organization> departments =OrganizationRoot.selectOrganizationByName(criteria);

        if (!CollectionUtils.isEmpty(departments)){
            List<String> organizationIdList=new ArrayList<>();
            departments.stream().forEach(department->{
                if(department != null) {
                    organizationIdList.add(department.getId());
                }
            });
            criteria.setOrganizationIds(organizationIdList);
        }


        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("list", userQueryService.provincePopupList(criteria));
        resultMap.put("totalCount", userQueryService.provincePopupListCount(criteria));
        return Result.successData(resultMap);
    }

}
