package thyyxxk.webserver.service.settings;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.Message;
import thyyxxk.webserver.dao.his.settings.SettingsDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.login.PersonnelQueryConditions;
import thyyxxk.webserver.entity.login.UserInfo;
import thyyxxk.webserver.entity.login.VueMenu;
import thyyxxk.webserver.entity.settings.deptphones.DeptPhones;
import thyyxxk.webserver.entity.settings.permissions.*;
import thyyxxk.webserver.entity.settings.users.ChangePwdParam;
import thyyxxk.webserver.entity.settings.users.WorkIntegrationPlatformAdvice;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.service.externalhttp.CorpWxSrvc;
import thyyxxk.webserver.service.redislike.RedisLikeService;
import thyyxxk.webserver.utils.*;
import thyyxxk.webserver.websocket.WebSocketServer;

import java.util.*;

/**
 * @author dj
 */
@Slf4j
@Service
public class SettingsService {
    private final SettingsDao dao;
    private final CorpWxSrvc srvc;
    private final PublicServer publicServer;

    private final RedisLikeService redis;

    @Autowired
    public SettingsService(SettingsDao dao, CorpWxSrvc srvc, PublicServer publicServer, RedisLikeService redis) {
        this.dao = dao;
        this.srvc = srvc;
        this.publicServer = publicServer;
        this.redis = redis;
    }

    public ResultVo<UserInfo> getUserInfo() {
        final String code = TokenUtil.getTokenUserId();
        final UserInfo user = dao.getUserInfo(code);
        if (null == user) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有找到此用户的在职信息，请重新登录！");
        }
        JSONObject json = srvc.getUserinfo(TokenUtil.getWeComAddressBookToken(), user.getCodeRs());
        user.setAvatar(json.getString("avatar"));
        user.setRoles(dao.getUserRoles(code));
        return ResultVoUtil.success(user);
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> changePassword(ChangePwdParam param) {
        String code = TokenUtil.getTokenUserId();
        String password = dao.getPassword(code);
        if (!param.getOldPassword().equals(password)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "旧密码错误，请检查！");
        }
        if ("".equals(param.getNewPassword().trim())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "新密码不能包含空格，请检查！");
        }
        dao.updatePassword(code, param.getNewPassword());
        redis.handleUserPwdChanged(code, param.getNewPassword());
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "密码修改成功，请重新登录。");
    }

    public ResultVo<List<DeptTree>> getDeptTree() {
        List<DeptTree> list = new ArrayList<>();
        DeptTree deptTree = new DeptTree();
        deptTree.setCode("");
        deptTree.setName("湖南泰和医院");
        String code = TokenUtil.getTokenUserId();
        List<Integer> roles = dao.getUserRoles(code);
        if (roles.contains(1) || roles.contains(2)) {
            deptTree.setChildren(dao.selectAllDepts());
        } else {
            deptTree.setChildren(dao.selectDeptsByUserCode(code));
        }
        list.add(deptTree);
        return ResultVoUtil.success(list);
    }

    public ResultVo<IPage<UserInfo>> getAllUsers(PersonnelQueryConditions param) {
        IPage<UserInfo> page = new Page<>(param.getCurrentPage(), param.getPageSize(), param.getTotal() == 0);
        if (publicServer.needRule(1, 2)) {
            return ResultVoUtil.success(dao.selectAllUsers(page, personnelQuery(param)));
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "你没有查看的权限.");
    }

    private QueryWrapper<?> personnelQuery(PersonnelQueryConditions param) {
        QueryWrapper<?> qw = new QueryWrapper<>();
        if (StringUtil.notBlank(param.getDeptCode())) {
            qw.eq("dept_code", param.getDeptCode());
        }
        if (StringUtil.notBlank(param.getName())) {
            qw.and(QueryWrapper -> QueryWrapper.like("name", param.getName()).or().eq("code_rs", param.getName()));
        }
        if (StringUtil.notBlank(param.getYbCode())) {
            qw.eq("yb_code", param.getYbCode());
        }
        if (param.getWhetherToDisable() != 9) {
            qw.eq("isnull(del_flag,0)", param.getWhetherToDisable());
        }
        if (param.getIsThereAMedicalInsuranceCode() == 1) {
            qw.isNotNull("yb_code");
        } else if (param.getIsThereAMedicalInsuranceCode() == 2) {
            qw.isNull("yb_code");
        }
        return qw;
    }

    public ResultVo<List<Role>> getAllRoles() {
        List<Integer> roles = dao.getUserRoles(TokenUtil.getTokenUserId());
        if (roles.contains(1)) {
            return ResultVoUtil.success(dao.getAllRoles());
        } else {
            return ResultVoUtil.success(dao.getAllRolesExceptAdmin());
        }
    }

    public ResultVo<List<Integer>> getUserRoles(String code) {
        return ResultVoUtil.success(dao.getUserRoles(code));
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> saveUserRoles(SaveUserRolesParam param) {
        dao.deleteUserRoles(param.getCode());
        if (null == param.getRoles() || param.getRoles().isEmpty()) {
            return ResultVoUtil.success();
        }
        dao.insertUserRoles(param.getCode(), param.getRoles());
        redis.handleUserRoleChanged(param.getCode());
        log.info("更改人员角色 => 操作员：{}，数据：{}", TokenUtil.getTokenUserId(), param);
        return ResultVoUtil.success();
    }

    public ResultVo<String> addNewRole(String name) {
        if (dao.isRoleExist(name) > 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该角色已存在，请匆重复添加！");
        }
        Role role = new Role();
        role.setName(name);
        role.setCreateStaff(TokenUtil.getTokenUserId());
        dao.addNewRole(role);
        return ResultVoUtil.success();
    }

    public ResultVo<List<Integer>> getRoleMenus(Integer id) {
        return ResultVoUtil.success(dao.getRoleMenus(id));
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> saveRoleMenus(SaveRoleMenusParam param) {
        dao.deleteRoleMenus(param.getId());
        if (null == param.getMenus() || param.getMenus().isEmpty()) {
            return ResultVoUtil.success();
        }
        log.info("更改角色菜单 => 操作员：{}，数据：{}", TokenUtil.getTokenUserId(), param);
        dao.insertRoleMenus(param.getId(), param.getMenus());
        return ResultVoUtil.success();
    }

    public ResultVo<List<DeptPhones>> getDeptPhones() {
        return ResultVoUtil.success(dao.getDeptPhones());
    }

    public ResultVo<String> saveDeptPhone(DeptPhones param) {
        log.info("修改科室电话 => 操作员：{}，数据：{}", TokenUtil.getTokenUserId(), param);
        dao.saveDeptPhone(param);
        return ResultVoUtil.success();
    }

    public ResultVo<List<WorkIntegrationPlatformAdvice>> getMyAdvices() {
        String userId = TokenUtil.getTokenUserId();
        List<Integer> userRoles = dao.getUserRoles(userId);
        List<WorkIntegrationPlatformAdvice> list;
        if (null != userRoles && userRoles.contains(1)) {
            list = dao.selectAllAdvices();
        } else {
            list = dao.selectMyAdvices(userId);
        }
        return ResultVoUtil.success(list);
    }

    public ResultVo<String> submitNewAdvice(WorkIntegrationPlatformAdvice advice) {
        if (StringUtil.isBlank(advice.getSubmitContent())) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "请填写建议内容！");
        }
        String userId = TokenUtil.getTokenUserId();
        dao.insertNewAdvice(userId, advice.getSubmitContent());
        List<String> admins = dao.selectAdmins();
        JSONObject obj = new JSONObject();
        obj.put("message", String.format("用户【%s】提交了新的建议，请前往个人中心查看。", userId));
        admins.forEach(code -> WebSocketServer.sendMessageByUserCode(code, SocketMsg.socketVo(Message.SYSTEM_NOTIFICATION, obj)));
        return ResultVoUtil.success();
    }

    public ResultVo<String> checkAdvice(Integer id) {
        dao.checkAdvice(id);
        return ResultVoUtil.success();
    }

    public ResultVo<String> dismissUserBadge(Integer id) {
        dao.dismissUserBadge(id);
        return ResultVoUtil.success();
    }

    public ResultVo<String> replyAdvice(WorkIntegrationPlatformAdvice advice) {
        if (StringUtil.isBlank(advice.getReply())) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "请填写回复内容！");
        }
        dao.updateReply(advice.getId(), advice.getReply(), TokenUtil.getTokenUserId());
        JSONObject obj = new JSONObject();
        obj.put("message", "您提交的建议已有新的回复，请前往个人中心查看。");
        WebSocketServer.sendMessageByUserCode(advice.getSubmitStaff(), SocketMsg.socketVo(Message.SYSTEM_NOTIFICATION,obj));
        return ResultVoUtil.success();
    }

    public ResultVo<List<VueMenu>> getAllVueMenus() {
        List<VueMenu> tempList = dao.selectAllVueMenus();
        return ResultVoUtil.success(TreeUtil.getVueMenuTree(tempList));
    }

    public ResultVo<List<Integer>> getRoleVueMenus(Integer id) {
        return ResultVoUtil.success(dao.getRoleVueMenus(id));
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> saveRoleVueMenus(SaveRoleMenusParam param) {
        dao.deleteRoleVueMenus(param.getId());
        if (null == param.getMenus() || param.getMenus().isEmpty()) {
            return ResultVoUtil.success();
        }
        log.info("修改角色菜单 => 操作员：{}，数据：{}", TokenUtil.getTokenUserId(), param);
        dao.insertRoleVueMenus(param.getId(), param.getMenus());
        return ResultVoUtil.success();
    }

    public ResultVo<String> modifyEmployeeInfo(UserInfo userInfo) {
        UserInfo info = getEmployeeOriginalInformation(userInfo.getCode());
        if (null == info) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有查询到原来信息");
        }
        String changedField = CampareObject.getChangedFieldsOfSql(info, userInfo);
        if (changedField.contains("name")) {
            changedField += String.format(",py_code = '%s',d_code = '%s' ",
                    PingYinUtils.pyShouZiMuDaXie(userInfo.getName()), PingYinUtils.getWBCode(userInfo.getName()));
        }
        dao.modifyPersonnelInformation(changedField, userInfo.getCode());
        log.info("修改员工信息==>操作人:{},数据:{}", TokenUtil.getTokenUserId(), JSON.toJSONString(userInfo));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
    }

    public ResultVo<String> saveEmployeeInfo(UserInfo userInfo) {
        if (dao.doesThePersonnelNumberExist(userInfo.getCodeRs()) > 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "人事工号已存在,换一个.");
        }

        userInfo.setCode("0" + publicServer.getPersonnelCode())
                .setPyCode(PingYinUtils.pyShouZiMuDaXie(userInfo.getName()))
                .setDCode(PingYinUtils.getWBCode(userInfo.getName()));
        dao.saveEmployeeInfo(userInfo);
        log.info("添加员工信息==>操作人:{},数据:{}", TokenUtil.getTokenUserId(), JSON.toJSONString(userInfo));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
    }

    private UserInfo getEmployeeOriginalInformation(String code) {
        IPage<UserInfo> page = new Page<>(1, 1, false);
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.eq("a.code", code);
        return dao.selectAllUsers(page, qw).getRecords().get(0);
    }


}
