package com.qmth.themis.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.boot.core.solar.config.SolarProperties;
import com.qmth.boot.core.solar.model.AppInfo;
import com.qmth.boot.core.solar.model.OrgInfo;
import com.qmth.boot.core.solar.service.SolarService;
import com.qmth.themis.business.constant.SpringContextHolder;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.entity.TBOrg;
import com.qmth.themis.business.entity.TEOrgSummary;
import com.qmth.themis.business.entity.TSAuth;
import com.qmth.themis.business.enums.AuthEnum;
import com.qmth.themis.business.enums.UploadFileEnum;
import com.qmth.themis.business.service.*;
import com.qmth.themis.business.util.OssUtil;
import com.qmth.themis.common.enums.ExceptionResultEnum;
import com.qmth.themis.common.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FileCopyUtils;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;

/**
 * @Description: 授权信息service
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2022/5/17
 */
@Service
public class AuthInfoServiceImpl implements AuthInfoService {
    private final static Logger log = LoggerFactory.getLogger(AuthInfoServiceImpl.class);

    @Resource
    SolarProperties solarProperties;

    @Resource
    SolarService solarService;

    @Resource
    TSAuthService tsAuthService;

    @Resource
    ThemisCacheService themisCacheService;

    @Resource
    TBOrgService tbOrgService;

    @Resource
    AuthInfoService authInfoService;

    @Resource
    OssUtil ossUtil;

    @Resource
    TEOrgSummaryService teOrgSummaryService;

    /**
     * 授权信息初始化
     *
     * @return
     */
    @Override
    public AppInfo appInfoInit() {
        AppInfo appInfo = null;
        try {
            appInfo = solarService.getAppInfo();
            if (Objects.nonNull(appInfo) && Objects.nonNull(solarProperties)) {
                if (Objects.nonNull(solarProperties.getAccessKey())
                        && !Objects.equals(solarProperties.getAccessKey().trim(), "")
                        && Objects.nonNull(solarProperties.getAccessSecret())
                        && !Objects.equals(solarProperties.getAccessSecret().trim(), "")) {//在线激活
                    authInfoService.saveAuthInfo(appInfo, AuthEnum.ON_LINE, null);
                } else if (Objects.nonNull(solarProperties.getLicense())
                        && !Objects.equals(solarProperties.getLicense().trim(), "")) {//离线激活
                    authInfoService.saveAuthInfo(appInfo, AuthEnum.OFF_LINE, null);
                }
            } else {
                QueryWrapper<TSAuth> tsAuthQueryWrapper = new QueryWrapper<>();
                tsAuthQueryWrapper.lambda().isNotNull(TSAuth::getFile);
                List<TSAuth> tsAuthList = tsAuthService.list(tsAuthQueryWrapper);
                if (!CollectionUtils.isEmpty(tsAuthList)) {
                    for (TSAuth t : tsAuthList) {
                        appInfo = solarService.update(t.getFile());
                        authInfoService.saveAuthInfo(appInfo, AuthEnum.OFF_LINE, t.getFile());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return appInfo;
    }

    /**
     * app是否过期
     *
     * @param code
     * @return
     */
    @Override
    public void appHasExpired(String code) {
        TBOrg tbOrg = themisCacheService.addOrgCodeCache(code);
        if ((Objects.nonNull(tbOrg) && Objects.nonNull(tbOrg.getEnable()) && tbOrg.getEnable().intValue() == 0)
                || (Objects.isNull(solarService.getAppInfo()) || solarService.getAppInfo().getControl().hasExpired())
                || (Objects.isNull(solarService.getAppControl()) || solarService.getAppControl().hasExpired())) {
            throw new BusinessException(ExceptionResultEnum.AUTH_INFO_ERROR);
        }
    }

    /**
     * 离线激活
     *
     * @param licenseData
     */
    @Override
    public void updateLicense(byte[] licenseData) throws Exception {
        AppInfo appInfo = solarService.update(licenseData);
        if (Objects.isNull(appInfo)) {
            throw new BusinessException("激活失败");
        }
        authInfoService.saveAuthInfo(appInfo, AuthEnum.OFF_LINE, licenseData);
    }

    /**
     * 查询授权信息
     *
     * @return
     */
    @Override
    public Long selectAuthInfo() {
        Long expireTime = null;
        AppInfo appInfo = solarService.getAppInfo();
        if (Objects.nonNull(appInfo) && Objects.nonNull(appInfo.getControl())) {
            expireTime = Objects.nonNull(appInfo.getControl().getExpireTime()) ? appInfo.getControl().getExpireTime() : -1;
        }
        return expireTime;
    }

    /**
     * 保存鉴权信息
     *
     * @param appInfo
     * @param authEnum
     * @param file
     * @throws Exception
     */
    @Override
    @Transactional
    public void saveAuthInfo(AppInfo appInfo, AuthEnum authEnum, byte[] file) throws Exception {
        List<OrgInfo> orgInfoList = solarService.getOrgList();
        List<TSAuth> tsAuthList = null;
        Map<String, String> orgCodesMap = null;
        Set<TBOrg> tbOrgSet = null;
        if (!CollectionUtils.isEmpty(orgInfoList)) {
            tsAuthList = new ArrayList<>();
            tbOrgSet = new HashSet<>();
            orgCodesMap = new HashMap<>();
        }
        Map<String, Object> mapParameter = ossUtil.getAliYunOssPublicDomain().getMap();
        boolean oss = (boolean) mapParameter.get(SystemConstant.OSS);
        for (OrgInfo o : orgInfoList) {
            orgCodesMap.put(o.getCode(), o.getCode());
            if (authEnum == AuthEnum.OFF_LINE) {
                if (Objects.isNull(file)) {
                    tsAuthList.add(new TSAuth(o.getId(), solarProperties.getLicense(), authEnum, appInfo.getControl().getExpireTime()));
                } else {
                    tsAuthList.add(new TSAuth(o.getId(), file, authEnum, appInfo.getControl().getExpireTime()));
                }
            } else {
                tsAuthList.add(new TSAuth(o.getId(), solarProperties.getAccessKey(), solarProperties.getAccessSecret(), authEnum, appInfo.getControl().getExpireTime()));
            }

            QueryWrapper<TBOrg> tbOrgQueryWrapper = new QueryWrapper<>();
            tbOrgQueryWrapper.lambda().eq(TBOrg::getCode, o.getCode());
            TBOrg tbOrg = tbOrgService.getOne(tbOrgQueryWrapper);
            if (Objects.isNull(tbOrg)) {//不存在则创建学校
                tbOrg = new TBOrg(o.getId(), o.getCode(), o.getName(), o.getAccessKey(), o.getAccessSecret());
                if (Objects.nonNull(o.getLogo()) && (!o.getLogo().startsWith("https:") || !o.getLogo().startsWith("http"))) {
                    File fileTemp = null;
                    try {
                        fileTemp = SystemConstant.getFileTempVar(SystemConstant.JPG_PREFIX);
                        SystemConstant.base64ToImage(o.getLogo(), fileTemp.getPath());
                        if (oss) {
                            StringJoiner stringJoiner = SystemConstant.getDirName(UploadFileEnum.file, true);
                            stringJoiner.add(SystemConstant.getNanoId()).add(SystemConstant.JPG_PREFIX);
                            ossUtil.upload(false, stringJoiner.toString(), fileTemp);
                            tbOrg.setLogo(ossUtil.getPrivateUrl(stringJoiner.toString()));
                        } else {
                            String filePath = SystemConstant.TEMP_FILES_DIR + File.separator + SystemConstant.getNanoId() + SystemConstant.JPG_PREFIX;
                            File logoFile = new File(filePath);
                            if (!logoFile.getParentFile().exists()) {
                                // 不存在则创建父目录及子文件
                                logoFile.getParentFile().mkdirs();
                                logoFile.createNewFile();
                            }
                            FileCopyUtils.copy(fileTemp, logoFile);
                            tbOrg.setLogo(filePath);
                        }
                    } catch (Exception e) {
                        log.error(SystemConstant.LOG_ERROR, e);
                    } finally {
                        if (Objects.nonNull(fileTemp)) {
                            fileTemp.delete();
                        }
                    }
                } else {
                    tbOrg.setLogo(o.getLogoUrl());
                }
                tbOrgSet.add(tbOrg);
                tbOrg.setAccessKey(o.getAccessKey());
                tbOrg.setAccessSecret(o.getAccessSecret());
                tbOrg.setLogo(Objects.nonNull(o.getLogoUrl()) ? o.getLogoUrl() : tbOrg.getLogo());
                tbOrgSet.add(tbOrg);
            } else {
                tbOrgSet.add(tbOrg);
            }
        }

        if (!CollectionUtils.isEmpty(tsAuthList) && !CollectionUtils.isEmpty(orgCodesMap)) {
            tsAuthService.remove(new QueryWrapper<TSAuth>().lambda().ge(TSAuth::getId, 0L));
            tsAuthService.saveOrUpdateBatch(tsAuthList);

            if (!CollectionUtils.isEmpty(tbOrgSet)) {
                for (TBOrg tbOrg : tbOrgSet) {
                    TEOrgSummary teOrgSummary = teOrgSummaryService.getOne(new QueryWrapper<TEOrgSummary>().lambda().eq(TEOrgSummary::getOrgId, tbOrg.getId()));
                    if (Objects.isNull(teOrgSummary)) {
                        teOrgSummaryService.orgSummary(tbOrg.getId());
                    }
                }
                tbOrgService.saveOrUpdateBatch(tbOrgSet);
                themisCacheService.removeOrgIdCache();
                themisCacheService.removeOrgCodeCache();
            }

            TEOrgSummary teOrgSummary = teOrgSummaryService.getOne(new QueryWrapper<TEOrgSummary>().lambda().eq(TEOrgSummary::getOrgId, 0L));
            if (Objects.isNull(teOrgSummary)) {
                teOrgSummaryService.orgSummary(0L);
            }
            AuthInfoService authInfoService = SpringContextHolder.getBean(AuthInfoService.class);
            authInfoService.updateSchoolEnable(orgCodesMap);
        }
    }

    /**
     * 更新学校启用/禁用
     *
     * @param orgCodesMap
     */
    @Override
    public void updateSchoolEnable(Map<String, String> orgCodesMap) {
        List<TBOrg> tbOrgList = tbOrgService.list();
        if (!CollectionUtils.isEmpty(tbOrgList)) {
            for (TBOrg t : tbOrgList) {
                if (orgCodesMap.containsKey(t.getCode())) {
                    t.setEnable(1);
                } else {
                    t.setEnable(0);
                }
            }
            tbOrgService.saveOrUpdateBatch(tbOrgList);
            themisCacheService.removeOrgIdCache();
            themisCacheService.removeOrgCodeCache();
        }
    }
}
