package cn.iocoder.yudao.module.basic.service.workersinfo;

import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.basic.api.redis.RedisBasicInfoUtilApi;
import cn.iocoder.yudao.module.basic.controller.admin.workersinfo.vo.WorkersInfoCreateReqVO;
import cn.iocoder.yudao.module.basic.controller.admin.workersinfo.vo.WorkersInfoPageReqVO;
import cn.iocoder.yudao.module.basic.controller.admin.workersinfo.vo.WorkersInfoUpdateReqVO;
import cn.iocoder.yudao.module.basic.controller.app.workersinfo.vo.Code2SessionReqVO;
import cn.iocoder.yudao.module.basic.controller.app.workersinfo.vo.VerifyReqVO;
import cn.iocoder.yudao.module.basic.convert.workersinfo.WorkersInfoConvert;
import cn.iocoder.yudao.module.basic.dal.dataobject.workersinfo.WorkersInfoDO;
import cn.iocoder.yudao.module.basic.dal.mysql.workersinfo.WorkersInfoMapper;
import cn.iocoder.yudao.module.basic.service.businessinfo.BusinessInfoServiceImpl;
import cn.iocoder.yudao.module.basic.util.WXUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.basic.enums.ErrorCodeConstants.*;

/**
 * 员工 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class WorkersInfoServiceImpl implements WorkersInfoService {

    @Resource
    private WorkersInfoMapper workersInfoMapper;
    @Resource
    private RedisBasicInfoUtilApi redisUtil;
    @Resource
    private BusinessInfoServiceImpl businessInfoService;

    @Override
    public Long createWorkersInfo(WorkersInfoCreateReqVO createReqVO) {
        // 校验存在
        validateWorkersCodeInfoExists(createReqVO.getWorkersCode(), (long) 0);
        //手机号进行唯一校验
        validateContactPhoneExists(createReqVO.getContactPhone());
        //校验所属商户是否存在
        businessInfoService.validateBusinessInfoExists(createReqVO.getBelongBusinessId());

        // 插入
        WorkersInfoDO workersInfo = WorkersInfoConvert.INSTANCE.convert(createReqVO);
        workersInfoMapper.insert(workersInfo);
        // 返回
        return workersInfo.getId();
    }

    @Override
    public void updateWorkersInfo(WorkersInfoUpdateReqVO updateReqVO) {
        // 校验存在
        WorkersInfoDO workersInfo = workersInfoMapper.selectById(updateReqVO.getId());
        if (workersInfo == null) {
            throw exception(WORKERS_INFO_NOT_EXISTS);
        }
        validateWorkersCodeInfoExists(updateReqVO.getWorkersCode(), updateReqVO.getId());
        // 检查手机号是否发生变化
        if (!Objects.equals(workersInfo.getContactPhone(), updateReqVO.getContactPhone())) {
            // 手机号发生变化，进行唯一校验
            validateContactPhoneExists(updateReqVO.getContactPhone());
        }

        //校验所属商户是否存在
        businessInfoService.validateBusinessInfoExists(updateReqVO.getBelongBusinessId());

        // 更新
        WorkersInfoDO updateObj = WorkersInfoConvert.INSTANCE.convert(updateReqVO);
        workersInfoMapper.updateById(updateObj);
    }

    @Override
    public void deleteWorkersInfo(Long id) {
        // 校验存在
        validateWorkersInfoExists(id);
        // 删除
        workersInfoMapper.deleteById(id);
    }

    private void validateWorkersInfoExists(Long id) {
        if (workersInfoMapper.selectById(id) == null) {
            throw exception(WORKERS_INFO_NOT_EXISTS);
        }
    }

    private void validateWorkersCodeInfoExists(String code, Long id) {
        QueryWrapper<WorkersInfoDO> wrapper = new QueryWrapper<>();
        wrapper.eq("workers_code", code);
        wrapper.ne("id", id);
        if (workersInfoMapper.selectOne(wrapper) != null) {
            throw exception(WORKERS_INFO_IS_EXISTS_WORKERS_CODE);
        }
    }

    @Override
    public WorkersInfoDO getWorkersInfo(Long id) {
        WorkersInfoDO workersInfoDO = workersInfoMapper.selectById(id);
        return workersInfoDO;
    }

    @Override
    public PageResult<WorkersInfoDO> getWorkersInfoPage(WorkersInfoPageReqVO pageReqVO) {
        PageResult<WorkersInfoDO> workersInfoDOPageResult = new PageResult<>();

        if (pageReqVO.getBelongBusinessName() != null && !Objects.equals(pageReqVO.getBelongBusinessName(), "")) {
            Page<WorkersInfoDO> page = new Page<>(pageReqVO.getPageNo(),pageReqVO.getPageSize());
            IPage<WorkersInfoDO> workersInfoDOIPage = workersInfoMapper.selectPageByInfo(page, new QueryWrapperX<WorkersInfoDO>()
                    .likeIfPresent("workers_name", pageReqVO.getWorkersName())
                    .eqIfPresent("workers_code", pageReqVO.getWorkersCode())
                    .likeIfPresent("bbi.business_name",pageReqVO.getBelongBusinessName())
                    .eq("bwi.deleted",0));
            workersInfoDOPageResult.setList(workersInfoDOIPage.getRecords());
            workersInfoDOPageResult.setTotal(workersInfoDOIPage.getTotal());
        }else {
            workersInfoDOPageResult = workersInfoMapper.selectPage(pageReqVO);
        }

        workersInfoDOPageResult.getList().forEach(item -> {
            if(redisUtil.validateBusinessInfoRedisExists(item.getBelongBusinessId())){
                item.setBelongBusinessName(redisUtil.getBusinessInfoRedis(item.getBelongBusinessId()).getBusinessName());
            }else {
                item.setBelongBusinessName("所属商户不存在");
            }
        });
        return workersInfoDOPageResult;
    }

    /**
     * 条件查询 根据商户id 查询所有底下的员工昵称
     *
     * @param belongBusinessId
     * @return
     */
    @Override
    public List<WorkersInfoDO> findByBelongBusinessId(Long belongBusinessId) {
        return workersInfoMapper.selectList(new QueryWrapper<WorkersInfoDO>()
                .eq("belong_business_id", belongBusinessId));
    }

    @Override
    public WorkersInfoDO getWorkersInfo(Long businessInfoId, String openid) {
        return workersInfoMapper.selectOne(new LambdaQueryWrapperX<WorkersInfoDO>().eq(WorkersInfoDO::getBelongBusinessId, businessInfoId)
                .eq(WorkersInfoDO::getOpenid, openid));
    }

    @Override
    public String bindWXToWorkers(Code2SessionReqVO reqVO) {
        // 校验手机号是否存在
        WorkersInfoDO workersInfo = workersInfoMapper.selectOne(new LambdaQueryWrapperX<WorkersInfoDO>().eq(WorkersInfoDO::getBelongBusinessId, reqVO.getBusinessInfoId())
                .eq(WorkersInfoDO::getContactPhone, reqVO.getPhone()));
        if(workersInfo == null) {
            throw ServiceExceptionUtil.exception(WORKERS_INFO_NOT_EXISTS);
        }
        if(workersInfo.getOpenid() != null && !workersInfo.getOpenid().isEmpty()) {
            throw ServiceExceptionUtil.exception(WORKERS_HAS_BIND_OPENID);
        }

        String openid = WXUtils.code2Session(reqVO.getCode());

        // 校验该openid是否已绑定过
        WorkersInfoDO hasBindDO = workersInfoMapper.selectOne(new LambdaQueryWrapperX<WorkersInfoDO>().eq(WorkersInfoDO::getBelongBusinessId, reqVO.getBusinessInfoId())
                .eq(WorkersInfoDO::getOpenid, openid));
        if(hasBindDO != null) {
            throw ServiceExceptionUtil.exception(THIS_OPENID_HAS_BE_USED);
        }

        workersInfo.setOpenid(openid);
        workersInfoMapper.updateById(workersInfo);

        return openid;
    }

    @Override
    public void unbindingWX(Long id) {
        WorkersInfoDO workersInfo = workersInfoMapper.selectById(id);
        if(workersInfo == null) {
            throw ServiceExceptionUtil.exception(WORKERS_INFO_NOT_EXISTS);
        }

        workersInfo.setOpenid("");
        workersInfoMapper.updateById(workersInfo);
    }

    @Override
    public WorkersInfoDO getWorkersInfoByOpenId(VerifyReqVO reqVO) {
        // 根据code获得openid
        String openid = WXUtils.code2Session(reqVO.getCode());
        return workersInfoMapper.selectOne(new LambdaQueryWrapperX<WorkersInfoDO>().eq(WorkersInfoDO::getBelongBusinessId, reqVO.getBusinessInfoId())
                .eq(WorkersInfoDO::getOpenid, openid));
    }

    private void validateContactPhoneExists(String contactPhone) {
        QueryWrapper<WorkersInfoDO> wrapper = new QueryWrapper<>();
        wrapper.eq("contact_phone",contactPhone);
        if (workersInfoMapper.selectOne(wrapper) != null) {
            throw exception(WORKERS_INFO_ALREADY_EXIST);
        }
    }

}


