package thyyxxk.webserver.service.settings;

import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
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.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
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.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.http.websocket.SocketV2;
import thyyxxk.webserver.http.websocket.dto.WebSocketByListUserCode;
import thyyxxk.webserver.http.websocket.dto.WebSocketByUserCode;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.service.TokenService;
import thyyxxk.webserver.service.archive.ArchiveServer;
import thyyxxk.webserver.service.externalhttp.CorpWxSrvc;
import thyyxxk.webserver.service.hutoolcache.CacheEnums;
import thyyxxk.webserver.service.hutoolcache.ExtraCache;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.utils.*;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author dj
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SettingsService {
    private final SettingsDao dao;
    private final CorpWxSrvc srvc;
    private final PublicServer publicServer;
    private final ExtraCache extraCache;
    private final UserCache userCache;
    private final TokenService tokenService;
    private final SocketV2 intergrationPlatformSocket;
    private final ArchiveServer archiveServer;


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

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

    public ResultVo<List<DeptTree>> getDeptTree() {
        List<DeptTree> list = new ArrayList<>();
        DeptTree deptTree = new DeptTree();
        deptTree.setCode("");
        deptTree.setName("沭阳铭和医院");
        String code = TokenUtil.getInstance().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, 62, 19)) {
            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.getInstance().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());
        userCache.refreshCache(param.getCode());
        log.info("更改人员角色 => 操作员：{}，数据：{}", TokenUtil.getInstance().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.getInstance().getTokenUserId());
        dao.addNewRole(role);
        return ResultVoUtil.success();
    }

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

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

    public ResultVo<List<WorkIntegrationPlatformAdvice>> getMyAdvices() {
        String userId = TokenUtil.getInstance().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.getInstance().getTokenUserId();
        dao.insertNewAdvice(userId, advice.getSubmitContent());
        List<String> admins = dao.selectAdmins();
        JSONObject obj = new JSONObject();
        obj.put("message", String.format("用户【%s】提交了新的建议，请前往个人中心查看。", userId));
        String message = SocketMsg.socketVo(Message.SYSTEM_NOTIFICATION, obj);

        intergrationPlatformSocket.sendUserCodeListMessage(
                WebSocketByListUserCode.create(admins, message)
        );
        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.getInstance().getTokenUserId());
        String message = SocketMsg.socketVo(Message.SYSTEM_NOTIFICATION, "您提交的建议已有新的回复，请前往个人中心查看。");
        intergrationPlatformSocket.sendMessageByUserCode(WebSocketByUserCode.create(advice.getSubmitStaff(), message));
        return ResultVoUtil.success();
    }

    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.getInstance().getTokenUserId(), param);
        dao.insertRoleVueMenus(param.getId(), param.getMenus());
        extraCache.del(CacheEnums.ROLE_MENU);
        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 (StringUtil.notBlank(changedField)) {
            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());
        }
        if(userInfo.getDoctorYpZl() == null) {
            dao.setDoctorYpZlNull(userInfo.getCode());
        }
        dao.delPartTimeDeptByCode(userInfo.getCode());
        if (ListUtil.notBlank(userInfo.getPartTimeDept())) {
            dao.insertPartTimeDept(userInfo.getCode(), userInfo.getPartTimeDept());
        }
        userCache.refreshCache(userInfo.getCode());
        log.info("修改员工信息==>操作人:{},数据:{}", TokenUtil.getInstance().getTokenUserId(), JSON.toJSONString(userInfo));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<String> saveEmployeeInfo(UserInfo userInfo) {
        if (dao.doesThePersonnelNumberExist(userInfo.getCodeRs()) > 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "人事工号已存在,换一个.");
        }
        userInfo.setCode("0" + publicServer.getPersonnelCode());
        userInfo.setPyCode(PingYinUtils.pyShouZiMuDaXie(userInfo.getName()));
        userInfo.setDCode(PingYinUtils.getWBCode(userInfo.getName()));
        dao.saveEmployeeInfo(userInfo);
        dao.delPartTimeDeptByCode(userInfo.getCode());
        if (ListUtil.notBlank(userInfo.getPartTimeDept())) {
            dao.insertPartTimeDept(userInfo.getCode(), userInfo.getPartTimeDept());
        }
        userCache.refreshCache(userInfo.getCode());
        log.info("添加员工信息==>操作人:{},数据:{}", TokenUtil.getInstance().getTokenUserId(), JSON.toJSONString(userInfo));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<String> resetPasswordByCode(String code, Integer nextTime) {
        dao.resetPassword(code);
        return ResultVoUtil.fail(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    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);
    }


    /**
     * @param code 医生编码
     * @return map
     * @Description 查询医生签名图片
     * @Author hsh
     * @Date 2024/5/15 9:47
     */
    public ResultVo<Map<String, Object>> selectAutographImageByCode(String code) {
        return ResultVoUtil.success(dao.selectAutographImageByCode(code));
    }


    public ResultVo<JSONObject> putAutographImage(MultipartFile file, String code) {
        String codeRs = "";
        if (code == null) {
            codeRs = FileNameUtil.mainName(file.getOriginalFilename());
        }
        if (StringUtil.isBlank(code) && StringUtil.notBlank(codeRs)) {
            code = dao.selectCodeByCodeRs(codeRs);
            if (StringUtil.isBlank(code)) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "工号不存在");
            }
        }

        String createFilePath = StrUtil.format("/{}/doctorSignature/{}.png", "archive", code);
        archiveServer.createFile(file, createFilePath);
        JSONObject js = new JSONObject();
        String name = FileNameUtil.extName(file.getOriginalFilename());
        String fileName = code + "." + name;
        js.put("url", StrUtil.format("/doctorSignatureImage/{}.png", code));
        js.put("name", fileName);
        return ResultVoUtil.success(js);
    }

    public void setUserConfig(String js) {
        String id = TokenUtil.getInstance().getTokenUserId();
        dao.updateUserConfig(js, id);
        userCache.refreshCache(id);
    }

    public void importUser() throws IOException {
        File file = new File("D:\\his\\基础数据\\铭和\\上级专家(2).xlsx");
        List<List<String>> data = ExcelReaderUtil.readExcel(file);

        // 打印读取到的数据
        for (List<String> row : data) {
            if("科室".equals(row.get(0))) {
                continue;
            }
            try {
                UserInfo userInfo = new UserInfo();
                userInfo.setCodeRs(row.get(7));
                userInfo.setName(row.get(1));
                userInfo.setDeptCode(row.get(0));
                userInfo.setSocialNo(row.get(3));
                userInfo.setYbCode(row.get(6));
                userInfo.setPhoneNo(row.get(4));
                userInfo.setYbName(row.get(5));
                userInfo.setDoctorXzYp("0");
                userInfo.setOrderYn("1");
                userInfo.setCode("0" + publicServer.getPersonnelCode());
                userInfo.setPyCode(PingYinUtils.pyShouZiMuDaXie(userInfo.getName()));
                userInfo.setDCode(PingYinUtils.getWBCode(userInfo.getName()));
                dao.saveEmployeeInfo(userInfo);
                dao.delPartTimeDeptByCode(userInfo.getCode());
                if (ListUtil.notBlank(userInfo.getPartTimeDept())) {
                    dao.insertPartTimeDept(userInfo.getCode(), userInfo.getPartTimeDept());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

}
