/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.coldchain.modular.alarmuser.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.coldchain.core.alarm.bean.SensorAlarmUser;
import vip.xiaonuo.coldchain.modular.alarmuser.dto.ExtendUserDTO;
import vip.xiaonuo.coldchain.modular.alarmuser.entity.AlarmUser;
import vip.xiaonuo.coldchain.modular.alarmuser.enums.AlarmUserEnum;
import vip.xiaonuo.coldchain.modular.alarmuser.mapper.AlarmUserMapper;
import vip.xiaonuo.coldchain.modular.alarmuser.param.AlarmUserAddParam;
import vip.xiaonuo.coldchain.modular.alarmuser.param.AlarmUserEditParam;
import vip.xiaonuo.coldchain.modular.alarmuser.param.AlarmUserIdParam;
import vip.xiaonuo.coldchain.modular.alarmuser.param.AlarmUserPageParam;
import vip.xiaonuo.coldchain.modular.alarmuser.service.AlarmUserService;
import vip.xiaonuo.coldchain.modular.monitortarget.entity.MonitorTarget;
import vip.xiaonuo.coldchain.modular.monitortarget.mapper.MonitorTargetMapper;
import vip.xiaonuo.coldchain.modular.push.entity.WeChatUser;
import vip.xiaonuo.coldchain.modular.push.utils.PushUtil;
import vip.xiaonuo.common.enums.CommonDeleteFlagEnum;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.listener.CommonDataChangeEventCenter;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.common.util.CommonAvatarUtil;
import vip.xiaonuo.common.util.CommonCryptogramUtil;
import vip.xiaonuo.dev.api.DevConfigApi;
import vip.xiaonuo.sys.core.enums.SysDataTypeEnum;
import vip.xiaonuo.sys.modular.user.entity.SysUser;
import vip.xiaonuo.sys.modular.user.enums.SysUserStatusEnum;
import vip.xiaonuo.sys.modular.user.service.SysUserService;
import vip.xiaonuo.sys.modular.user.service.impl.SysUserServiceImpl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 报警接收人Service接口实现类
 *
 * @author 黄渊昊
 * @date 2024/12/02 15:41
 **/
@Service
@Slf4j
public class AlarmUserServiceImpl extends ServiceImpl<AlarmUserMapper, AlarmUser> implements AlarmUserService {

    @Resource
    private SysUserService sysUserService;
    @Resource
    private DevConfigApi devConfigApi;
    @Resource
    private MonitorTargetMapper monitorTargetMapper;

    @Override
    public Page<ExtendUserDTO> page(AlarmUserPageParam alarmUserPageParam) {
        SaBaseLoginUser loginUser = StpLoginUserUtil.getLoginUser();
        QueryWrapper<AlarmUser> queryWrapper = new QueryWrapper<AlarmUser>().checkSqlInjection();
        queryWrapper.lambda().like(StrUtil.isNotBlank(alarmUserPageParam.getNickName()), AlarmUser::getNickName, alarmUserPageParam.getNickName());
        if (ObjectUtil.isNotEmpty(alarmUserPageParam.getName())) {
            Page<SysUser> userPageByName = sysUserService.getUserByName(alarmUserPageParam.getName());
            if (userPageByName.getTotal() < 1) {
                return Page.of(userPageByName.getCurrent(), userPageByName.getSize());
            }
            List<String> userIds = userPageByName.getRecords().stream().map(SysUser::getId).toList();
            queryWrapper.lambda().in(AlarmUser::getUserId, userIds);
        }
        if (ObjectUtil.isAllNotEmpty(alarmUserPageParam.getSortField(), alarmUserPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(alarmUserPageParam.getSortOrder());
            queryWrapper.orderBy(true, alarmUserPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(alarmUserPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByDesc(AlarmUser::getCreateTime);
        }
        queryWrapper.lambda()
                .eq(!loginUser.isSuperAdmin(), AlarmUser::getCreateOrg, loginUser.getOrgId())
                .eq(AlarmUser::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE);
        Page<AlarmUser> page = this.page(CommonPageRequest.defaultPage(), queryWrapper);
        if (page.getTotal() < 1) {
            return Page.of(page.getCurrent(), page.getSize());
        }

        Page<ExtendUserDTO> extendUserDTOPage = Page.of(page.getCurrent(), page.getSize(), page.getTotal());
        extendUserDTOPage.setRecords(alarmUser2ExtendUserDTO(page.getRecords()));
        return extendUserDTOPage;
    }

    /**
     * 将AlarmUser转为ExtendUserDTO
     */
    private List<ExtendUserDTO> alarmUser2ExtendUserDTO(List<AlarmUser> alarmUserList) {
        List<ExtendUserDTO> dtoList = BeanUtil.copyToList(alarmUserList, ExtendUserDTO.class);
        Set<String> userIdSet = dtoList.stream().map(AlarmUser::getUserId).filter(StrUtil::isNotBlank).collect(Collectors.toSet());
        if (userIdSet.isEmpty()) {
            return dtoList;
        }

        //获取用户真实姓名
        List<SysUser> sysUserList = sysUserService.list(new LambdaQueryWrapper<>(SysUser.class)
                .in(SysUser::getId, userIdSet)
                .eq(SysUser::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE));
        Map<String, SysUser> userNameMap = sysUserList.stream().collect(Collectors.toMap(SysUser::getId, Function.identity()));
        dtoList.forEach(dto -> {
            if (StrUtil.isNotBlank(dto.getUserId()) && userNameMap.containsKey(dto.getUserId())) {
                SysUser sysUser = userNameMap.get(dto.getUserId());
                dto.setName(sysUser.getName());
                dto.setPhone(sysUser.getPhone());
            }
        });
        return dtoList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(AlarmUserAddParam alarmUserAddParam) {
        AlarmUser alarmUser = BeanUtil.toBean(alarmUserAddParam, AlarmUser.class);
        this.save(alarmUser);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(AlarmUserEditParam alarmUserEditParam) {
        AlarmUser alarmUser = this.queryEntity(alarmUserEditParam.getId());
        BeanUtil.copyProperties(alarmUserEditParam, alarmUser);

        // 判断是否有系统用户关联
        if (StrUtil.isBlank(alarmUser.getUserId())) {
            // 如果没有关联，则创建用户
            SysUser sysUser = createSysUser(alarmUser, null, alarmUserEditParam.getName());
            sysUser.setPhone(alarmUserEditParam.getPhone());
            sysUserService.updateById(sysUser);
            alarmUser.setUserId(sysUser.getId());
        } else {
            // 如果有关联，则修改用户姓名
            SysUser sysUser = sysUserService.getById(alarmUser.getUserId());
            sysUser.setName(alarmUserEditParam.getName());
            sysUser.setPhone(alarmUserEditParam.getPhone());
            sysUser.setAvatar(CommonAvatarUtil.generateImg(sysUser.getName()));
            sysUserService.updateById(sysUser);
        }

        this.updateById(alarmUser);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<AlarmUserIdParam> alarmUserIdParamList) {
        List<String> userIds = CollStreamUtil.toList(alarmUserIdParamList, AlarmUserIdParam::getId);

        //检查报警接收人是否在使用
        List<MonitorTarget> monitorTargets = monitorTargetMapper.selectList(new LambdaQueryWrapper<>(MonitorTarget.class)
                .select(MonitorTarget::getAlarmUsers)
                .eq(MonitorTarget::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE));
        if (CollUtil.isNotEmpty(monitorTargets)) {
            List<String> sensorAlarmUserOpenIdList = monitorTargets.stream()
                    .flatMap(x -> x.getAlarmUsers().stream())
                    .map(SensorAlarmUser::getOpenId)
                    .filter(StrUtil::isNotBlank)
                    .distinct().toList();
            long usedUser = count(new LambdaQueryWrapper<>(AlarmUser.class).eq(AlarmUser::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE)
                    .in(AlarmUser::getOpenId, sensorAlarmUserOpenIdList)
                    .in(AlarmUser::getId, userIds));
            Assert.isTrue(usedUser == 0, "报警接收人正在使用中，无法删除");
        }

        // 执行删除
        this.removeByIds(userIds);
    }

    @Override
    public AlarmUser detail(AlarmUserIdParam alarmUserIdParam) {
        return this.queryEntity(alarmUserIdParam.getId());
    }

    @Override
    public AlarmUser queryEntity(String id) {
        AlarmUser alarmUser = this.getById(id);
        if (ObjectUtil.isEmpty(alarmUser)) {
            throw new CommonException("报警接收人不存在，id值为：{}", id);
        }
        return alarmUser;
    }

    @Override
    public List<ExtendUserDTO> myList() {
        SaBaseLoginUser loginUser = StpLoginUserUtil.getLoginUser();
        LambdaQueryWrapper<AlarmUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlarmUser::getCreateOrg, loginUser.getOrgId()).eq(AlarmUser::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE);
        List<AlarmUser> list = list(queryWrapper);
        return alarmUser2ExtendUserDTO(list);
    }

    @Override
    public String getUserInfo(String code, String orgId, String name) {
        WeChatUser userInfo = PushUtil.getUserInfo(code);
        log.info("获取用户信息:{}", JSONUtil.toJsonStr(userInfo));

        List<AlarmUser> userList = getByOpenId(userInfo.getOpenid());
        AlarmUser alarmUser = BeanUtil.copyProperties(userInfo, AlarmUser.class);
        alarmUser.setOpenId(userInfo.getOpenid());
        alarmUser.setUnionId(userInfo.getUnionid());
        alarmUser.setNickName(userInfo.getNickname());
        if (userList.isEmpty()) {
            SysUser sysUser = createSysUser(alarmUser, orgId, name);
            alarmUser.setUserId(sysUser.getId());
            if (StrUtil.isNotEmpty(orgId)) {
                alarmUser.setCreateOrg(orgId);
            }
            save(alarmUser);
            return "绑定成功！";
        }

        //更新用户信息
        Map<String, SysUser> sysUserMap = new HashMap<>();
        for (AlarmUser user : userList) {
            String alarmUserId = user.getId();

            //如果没有创建系统用户，则进行创建
            if (StrUtil.isBlank(user.getUserId())) {
                if (sysUserMap.containsKey(alarmUserId)) {
                    alarmUser.setUserId(sysUserMap.get(alarmUserId).getId());
                } else {
                    SysUser sysUser = createSysUser(user, orgId, name);
                    sysUserMap.put(alarmUserId, sysUser);
                    alarmUser.setUserId(sysUser.getId());
                }
            }

            if (StrUtil.isNotEmpty(orgId)) {
                alarmUser.setCreateOrg(orgId);
            }
            alarmUser.setId(alarmUserId);
            updateById(alarmUser);
        }
        return "您已绑定过该组织，已为您更新个人信息";
    }

    @Override
    public AlarmUser subscribe(String openid) {
        log.info("用户关注公众号 openid={}", openid);

        List<AlarmUser> users = getByOpenId(openid);
        if (users.isEmpty()) {
            //创建用户
            AlarmUser alarmUser = new AlarmUser();
            alarmUser.setOpenId(openid);
            alarmUser.setSubscribed(AlarmUserEnum.SUBSCRIBE.getValue());
            SysUser sysUser = createSysUser(alarmUser, null, "");

            alarmUser.setUserId(sysUser.getId());
            alarmUser.setId(IdWorker.getIdStr());
            save(alarmUser);
            return alarmUser;
        }

        //更新用户关注标志
        AlarmUser alarmUser = new AlarmUser();
        alarmUser.setSubscribed(AlarmUserEnum.SUBSCRIBE.getValue());
        update(alarmUser, new LambdaUpdateWrapper<>(AlarmUser.class).eq(AlarmUser::getOpenId, openid));
        return users.get(0);
    }

    @Override
    public void unsubscribe(String openid) {
        log.info("用户取消关注公众号 openid={}", openid);
        AlarmUser alarmUser = new AlarmUser();
        alarmUser.setSubscribed(AlarmUserEnum.UNSUBSCRIBE.getValue());
        update(alarmUser, new LambdaUpdateWrapper<>(AlarmUser.class).eq(AlarmUser::getOpenId, openid));
    }

    public List<AlarmUser> getByOpenId(String openId) {
        LambdaQueryWrapper<AlarmUser> queryWrapper = new LambdaQueryWrapper<>(AlarmUser.class)
                .eq(AlarmUser::getOpenId, openId)
                .eq(AlarmUser::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE)
                .orderByDesc(AlarmUser::getCreateTime);
        return list(queryWrapper);
    }

    /**
     * 新增系统用户
     */
    private SysUser createSysUser(AlarmUser alarmUser, String orgId, String name) {
        //创建系统用户
        SysUser sysUser;
        if (alarmUser == null) {
            sysUser = new SysUser();
        } else {
            sysUser = BeanUtil.copyProperties(alarmUser, SysUser.class);
        }
        sysUser.setId(IdWorker.getIdStr());
        sysUser.setName(name);
        if (StrUtil.isNotEmpty(orgId)) {
            sysUser.setOrgId(orgId);
        }
        sysUser.setAvatar(CommonAvatarUtil.generateImg(sysUser.getName()));
        // 设置默认密码
        sysUser.setPassword(CommonCryptogramUtil.doHashValue(devConfigApi.getValueByKey(SysUserServiceImpl.SNOWY_SYS_DEFAULT_PASSWORD_KEY)));
        // 设置排序码
        sysUser.setSortCode(99);
        // 设置状态
        sysUser.setUserStatus(SysUserStatusEnum.ENABLE.getValue());
        // 发布增加事件
        CommonDataChangeEventCenter.doAddWithData(SysDataTypeEnum.USER.getValue(), JSONUtil.createArray().put(sysUser));
        sysUserService.save(sysUser);

        return sysUser;
    }
}
