package com.gic.haoban.manage.service.service.out.impl;

import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.BasePageInfo;
import com.gic.api.base.commons.Page;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.util.EntityUtil;
import com.gic.haoban.manage.api.dto.OpenStaffDTO;
import com.gic.haoban.manage.api.dto.OpenStaffLicenseDTO;
import com.gic.haoban.manage.api.dto.OpenStaffListDTO;
import com.gic.haoban.manage.api.dto.StaffClerkRelationDTO;
import com.gic.haoban.manage.api.enums.OpenStaffOfflineEnum;
import com.gic.haoban.manage.api.enums.QwOpenStepEnum;
import com.gic.haoban.manage.api.qdto.OpenStaffInitQDTO;
import com.gic.haoban.manage.api.qdto.OpenStaffPageQDTO;
import com.gic.haoban.manage.api.service.OpenStaffApiService;
import com.gic.haoban.manage.service.dao.mapper.OpenStaffMapper;
import com.gic.haoban.manage.service.entity.TabOpenStaff;
import com.gic.haoban.manage.service.pojo.QwOpenResultInitBO;
import com.gic.haoban.manage.service.service.OpenStaffService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.haoban.manage.service.util.OpenUtils;
import com.gic.redis.data.util.RedisUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 企微托管账号
 */
@Service("openStaffApiService")
public class OpenStaffApiServiceImpl implements OpenStaffApiService {

    private static final Logger log = LogManager.getLogger(OpenStaffApiService.class);

    @Autowired
    private OpenStaffMapper openStaffMapper;
    @Autowired
    private OpenStaffService openStaffService;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;

    @Override
    public ServiceResponse<Void> delete(Long id) {
        TabOpenStaff staff = this.openStaffMapper.getById(id);
        if (null != staff) {
            this.openStaffService.logout(staff.getUuid(), "删除", 0, null);
        }
        this.openStaffMapper.deleteByPrimaryKey(id);
        return ServiceResponse.success();
    }

    @Override
    public ServiceResponse<Void> updateValiFlag(String uuid) {
        this.openStaffMapper.updateValidFlag(uuid);
        return ServiceResponse.success();
    }

    @Override
    public ServiceResponse<Void> update2QrcodeFlag(String uuid) {
        TabOpenStaff openStaff = this.openStaffService.getByUUID(uuid);
        if (null == openStaff) {
            return ServiceResponse.failure("9999", "登录错误");
        }
        // 需要二次验证
        this.openStaffService.logout(uuid, OpenStaffOfflineEnum.OFFLINE1.getDesc(), 0, OpenStaffOfflineEnum.OFFLINE1.getDesc());
        this.openStaffMapper.update2QrcodeFlag(openStaff.getOpenStaffId());
        return ServiceResponse.success();
    }

    @Override
    public ServiceResponse<OpenStaffDTO> get2Qrcode(long id) {
        TabOpenStaff openStaff = this.openStaffMapper.getById(id);
        if (null == openStaff) {
            return ServiceResponse.failure("9999", "登录错误");
        }
        ServiceResponse<QwOpenResultInitBO> resp = OpenUtils.getQrcode(openStaff.getUuid(), null, 2);
        String qrcodeData = null;
        if (resp.isSuccess()) {
            String qrcode = resp.getResult().getQrcode();
            String key = resp.getResult().getKey();
            this.openStaffMapper.update2Qrcode(openStaff.getOpenStaffId(), qrcode, key);
            openStaff.setQrCode2(qrcode);
            qrcodeData = resp.getResult().getQrcode_data();
        } else {
            return ServiceResponse.failure("9999", resp.getMessage());
        }
        OpenStaffDTO dto = EntityUtil.changeEntityByJSON(OpenStaffDTO.class, openStaff);
        dto.setQrcodeData(qrcodeData);
        return ServiceResponse.success(dto);
    }

    @Override
    public ServiceResponse<Void> updateLoginStep(String uuid, int step) {
        TabOpenStaff openStaff = this.openStaffService.getByUUID(uuid);
        if (null == openStaff) {
            return ServiceResponse.failure("9999", "登录错误");
        }
        this.openStaffMapper.updateLoginStep(openStaff.getOpenStaffId(), step);
        if (QwOpenStepEnum.isFail(step)) {
            this.openStaffService.logout(uuid, "企微返回退出/登录超时", 0, null);
        }
        return ServiceResponse.success();
    }

    @Override
    public ServiceResponse<Void> login(String uuid, Long qwCorpId, String corpName, Long qwUserId) {
        TabOpenStaff openStaff = this.openStaffService.getByUUID(uuid);
        if (null == openStaff) {
            return ServiceResponse.failure("9999", "登录错误");
        }
        String wxEnterpriseId = openStaff.getWxEnterpriseId();
        List<String> backWxEnterpriseIdList = this.wxEnterpriseService.getWxEnterpriseIdByName(corpName);
        if (CollectionUtils.isEmpty(backWxEnterpriseIdList) || backWxEnterpriseIdList.size() > 1 || !backWxEnterpriseIdList.get(0).equals(wxEnterpriseId)) {
            this.openStaffService.logout(uuid, "授权登录账号与当前账号不一致", 10, null);
            log.info("登录的企业不对={},{}", uuid, corpName);
            return ServiceResponse.failure("9999", "登录错误");
        }
        TabOpenStaff staff = this.openStaffMapper.getByQwUserId(qwUserId);
        if (null != staff && !staff.getWxEnterpriseId().equals(wxEnterpriseId)) {
            this.openStaffService.logout(uuid, "只能托管一个企微企业", 0, null);
            log.info("只能托管一个企业={},{}", uuid, corpName);
            return ServiceResponse.failure("9999", "只能托管一个企业");
        }
        openStaff.setWxCorpId(qwCorpId);
        openStaff.setQwUserId(qwUserId);
        if (null == openStaff.getFirstAuthTime()) {
            openStaff.setFirstAuthTime(new Date());
        }
        openStaff.setAuthTime(new Date());
        openStaff.setStatusFlag(1);
        this.openStaffMapper.update(openStaff);
        return ServiceResponse.success();
    }

    @Override
    public ServiceResponse<Void> logout(String uuid, OpenStaffOfflineEnum offlineEnum) {
        this.openStaffService.logout(uuid, offlineEnum.getDesc(), 0, offlineEnum.getDesc());
        return ServiceResponse.success();
    }

    @Override
    public ServiceResponse<Void> logout(Long openStaffId) {
        TabOpenStaff staff = this.openStaffMapper.getById(openStaffId);
        this.openStaffService.logout(staff.getUuid(), "取消授权", 0, null);
        return ServiceResponse.success();
    }

    @Override
    public ServiceResponse<Void> checkCode(Long openStaffId, String validCode) {
        TabOpenStaff tab = this.openStaffMapper.getById(openStaffId);
        if (null == tab) {
            return ServiceResponse.failure("9999", "记录不存在");
        }
        return OpenUtils.checkCode(tab.getUuid(), tab.getKey1(), validCode);
    }

    @Override
    public ServiceResponse<OpenStaffDTO> getById(Long openStaffId) {
        TabOpenStaff openStaff = this.openStaffMapper.getById(openStaffId);
        if (null == openStaff) {
            return ServiceResponse.failure("9999", "已删除");
        }
        OpenStaffDTO dto = EntityUtil.changeEntityByJSON(OpenStaffDTO.class, openStaff);
        return ServiceResponse.success(dto);
    }

    @Override
    public ServiceResponse<OpenStaffDTO> getByQwUserId(Long qwUserId) {
        TabOpenStaff openStaff = this.openStaffMapper.getByQwUserId(qwUserId);
        if (null == openStaff) {
            return ServiceResponse.failure("9999", "已删除");
        }
        OpenStaffDTO dto = EntityUtil.changeEntityByJSON(OpenStaffDTO.class, openStaff);
        return ServiceResponse.success(dto);
    }

    @Override
    public ServiceResponse<OpenStaffDTO> init(OpenStaffInitQDTO qdto) {
        String staffId = qdto.getStaffId();
        if (StringUtils.isBlank(staffId)) {
            log.info("staffId is null");
            return ServiceResponse.failure("9999", "staffId为空");
        }
        String lockKey = "lock:qywx:open:" + staffId;
        try {
            RedisUtil.lock(lockKey, 3L);
            TabOpenStaff openStaff = this.openStaffMapper.getByStaffId(staffId);
            Long qwUserId = null;
            if (null != openStaff) {
                if (openStaff.getStatusFlag() == 1 && qdto.getLoginAgainFlag() == 0) {
                    return ServiceResponse.failure("9999", "成员已托管中");
                }
                qwUserId = openStaff.getQwUserId();
                log.info("重新初始化");
                this.openStaffService.logout(openStaff.getUuid(), "重新初始化", 0, null);
                // 自动登录
                String newUuid = this.openStaffService.autoLogin(openStaff.getOpenStaffId(),openStaff.getQwUserId()) ;
                if(null != newUuid) {
                    log.info("自动登录成功");
                    openStaff.setAuthTime(new Date());
                    openStaff.setStatusFlag(1);
                    openStaff.setUuid(newUuid);
                    openStaff.setLoginRemark("自动登录成功");
                    this.openStaffMapper.update(openStaff);
                    OpenStaffDTO dto = EntityUtil.changeEntityByJSON(OpenStaffDTO.class, openStaff);
                    return ServiceResponse.success(dto);
                }
            }
            if (null == openStaff) {
                openStaff = new TabOpenStaff();
                openStaff.setStaffId(staffId);
                openStaff.setWxEnterpriseId(qdto.getWxEnterpriseId());
                openStaff.setEnterpriseId(qdto.getEnterpriseId());
            }
            ServiceResponse<QwOpenResultInitBO> resp = OpenUtils.init(qwUserId,true);
            log.info("resp={}", JSONObject.toJSONString(resp));
            QwOpenResultInitBO init = resp.getResult();
            openStaff.setUuid(init.getUuid());
            openStaff.setQrCode1(init.getQrcode());
            openStaff.setKey1(init.getKey());
            openStaff.setStatusFlag(2);
            openStaff.setStep(0);
            openStaff.setValidFlag(0);
            openStaff.setValidQrcodeFlag(0);
            openStaff.setQrCode2(null);
            openStaff.setKey2(null);
            openStaff = this.openStaffService.save(openStaff);
            OpenStaffDTO dto = EntityUtil.changeEntityByJSON(OpenStaffDTO.class, openStaff);
            dto.setQrcodeData(init.getQrcode_data());
            return ServiceResponse.success(dto);
        } catch (Exception e) {
            log.info("异常", e);
        }
        return ServiceResponse.failure("9999", "登录失败");
    }

    @Override
    public ServiceResponse<OpenStaffLicenseDTO> getLicenseInfo(String wxEnterpriseId, String enterpriseId) {
        OpenStaffLicenseDTO dto = new OpenStaffLicenseDTO();
        int useNum = this.openStaffMapper.getNum(wxEnterpriseId, enterpriseId, 0);
        int validNum = this.openStaffMapper.getNum(wxEnterpriseId, enterpriseId, 1);
        dto.setUseNum(useNum);
        dto.setValidNum(validNum);
        return ServiceResponse.success(dto);
    }

    @Override
    public ServiceResponse<Page<OpenStaffListDTO>> page(OpenStaffPageQDTO qdto, BasePageInfo basePageInfo) {
        return this.openStaffService.page(qdto, basePageInfo);
    }

    @Override
    public ServiceResponse<OpenStaffDTO> getByStaffId(String staffId) {
        TabOpenStaff tab = this.openStaffMapper.getByStaffId(staffId);
        if (null == tab) {
            return ServiceResponse.failure("9999", "已删除");
        }
        OpenStaffDTO dto = EntityUtil.changeEntityByJSON(OpenStaffDTO.class, tab);
        return ServiceResponse.success(dto);
    }

    @Override
    public ServiceResponse<OpenStaffDTO> getByUUID(String uuid) {
        TabOpenStaff tab = this.openStaffMapper.getByUUID(uuid);
        if (null == tab) {
            return ServiceResponse.failure("9999", "不存在");
        }
        OpenStaffDTO dto = EntityUtil.changeEntityByJSON(OpenStaffDTO.class, tab);
        return ServiceResponse.success(dto);
    }

    @Override
    public List<StaffClerkRelationDTO> listOpenStaffByClerk(String wxEnterpriseId, String enterpriseId, List<String> clerkIdList) {
        return this.openStaffMapper.listOpenStaffByClerk(wxEnterpriseId, enterpriseId, clerkIdList);
    }

    @Override
    public List<StaffClerkRelationDTO> listOpenStaffByStore(String wxEnterpriseId, String enterpriseId, List<String> storeIdList) {
        return this.openStaffMapper.listOpenStaffByStore(wxEnterpriseId, enterpriseId, storeIdList);
    }

    @Override
    public List<String> listAllOnlineStaff() {
        return this.listAllOnlineStaff(null, null);
    }


    @Override
    public List<String> listAllOnlineStaff(String wxEnterpriseId, String enterpriseId) {
        List<TabOpenStaff> list = this.openStaffMapper.listAllOnline(wxEnterpriseId, enterpriseId);
        return list.stream().map(o -> o.getStaffId()).collect(Collectors.toList());
    }

    @Override
    public List<String> listOpenStoreId(String wxEnterpriseId, String enterpriseId) {
        return this.openStaffMapper.listOpenStoreId(wxEnterpriseId, enterpriseId);
    }

    @Override
    public void updateStopTime(Long openStaffId, int type, int time) {
        this.openStaffMapper.updateStopTime(openStaffId, type, time);
    }
}
