package com.brframework.webapppatch.service.impl;

import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.brframework.commondb.core.AbstractEntityService;
import com.brframework.commondb.core.CommonRepository;
import com.brframework.commondistributed.annotation.DistributedLock;
import com.brframework.commonweb.exception.HandleException;
import com.brframework.webapppatch.dao.PatchVersionDao;
import com.brframework.webapppatch.entity.AppVersion;
import com.brframework.webapppatch.entity.PatchBranch;
import com.brframework.webapppatch.entity.PatchVersion;
import com.brframework.webapppatch.service.PatchBranchService;
import com.brframework.webapppatch.service.PatchGrayUserService;
import com.brframework.webapppatch.service.PatchVersionService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.time.LocalDateTime;

/**
 * 版本
 * @author xu
 * @date 2019/11/14 10:32
 */
@Service
public class PatchVersionServiceImpl extends AbstractEntityService<PatchVersion, Long, Object>
        implements PatchVersionService {
    @Autowired
    PatchVersionDao patchVersionDao;

    @Autowired
    PatchGrayUserService patchGrayUserService;

    @Autowired
    PatchBranchService patchBranchService;

    @Override
    public CommonRepository<Long, PatchVersion> getRepository() {
        return patchVersionDao;
    }

    @Override
    @DistributedLock(key = "'PatchVersionServiceImpl-createVersion'", waitFor = false)
    public void createVersion(String os, String branch, String versionMessage,
                              String versionUrl, String patchUrl, String bundleUrl,
                              Integer updateType, Integer updateStatus) {
        os = os.toUpperCase();

        PatchBranch patchBranch = patchBranchService.findByBranchName(branch);
        if(patchBranch == null){
            throw new HandleException("不存在分支" + branch + ", 请到管理控制台创建");
        }

        //创建新版本时，当前最新的版本必须处于发布或失败的状态下
        PatchVersion nowVersion = patchVersionDao.findTop1ByOsAndBranchOrderByVersionDesc(os, branch);
        if(nowVersion != null){
            if(nowVersion.getUpdateStatus().equals(PatchVersion.UPDATE_STATUS_DEPLOY) ||
                    nowVersion.getUpdateStatus().equals(PatchVersion.UPDATE_STATUS_GRAY)){
                throw new HandleException("分支【" + branch + "】" +
                        "最新版本【" + nowVersion.getVersion()  +"】正处于部署或灰度状态，请到管理控制台设置发布或失败");
            }
        }

        //获取文件的大小及md5
        HttpResponse versionResponse = HttpUtil.createRequest(Method.HEAD, versionUrl).execute();
        HttpResponse patchResponse = HttpUtil.createRequest(Method.GET, patchUrl).execute();
        HttpResponse bundleResponse = HttpUtil.createRequest(Method.GET, bundleUrl).execute();
        String bundleHash = MD5.create().digestHex(bundleResponse.bodyStream());
        String patchHash = MD5.create().digestHex(patchResponse.bodyStream());
        PatchVersion patchVersion = new PatchVersion();
        patchVersion.setCreateDate(LocalDateTime.now());

        patchVersion.setOs(os);
        patchVersion.setBranch(branch);
        patchVersion.setVersionMessage(versionMessage);
        patchVersion.setVersionUrl(versionUrl);
        patchVersion.setPatchUrl(patchUrl);
        patchVersion.setUpdateType(updateType);
        patchVersion.setUpdateStatus(updateStatus);
        patchVersion.setVersion(getBranchMaxVersion(os, branch));
        patchVersion.setFileSize(Long.parseLong(versionResponse.header("Content-Length")));
        patchVersion.setPatchFileSize(Long.parseLong(patchResponse.header("Content-Length")));
        patchVersion.setHash("-----");
        patchVersion.setBundleHash(bundleHash);
        patchVersion.setAssetsHash("-----");
        patchVersion.setPatchHash(patchHash);

        save(patchVersion);
    }

    @Override
    public Integer getBranchMaxVersion(String os, String branch) {
        os = os.toUpperCase();
        PatchVersion version = patchVersionDao.findTop1ByOsAndBranchOrderByVersionDesc(os, branch);
        if(version == null){
            return 2;
        }
        return version.getVersion() + 1;
    }

    @Override
    @DistributedLock(key = "'PatchVersionServiceImpl-UpdateStatus' + #id", waitFor = false)
    public void setVersionGray(Long id) {
        PatchVersion patchVersion = accessObject(id);
        if(!patchVersion.getUpdateStatus().equals(PatchVersion.UPDATE_STATUS_DEPLOY)){
            throw new HandleException("当前版本不能进入灰度发布");
        }
        patchVersion.setUpdateStatus(PatchVersion.UPDATE_STATUS_GRAY);
        save(patchVersion);
    }

    @Override
    @DistributedLock(key = "'PatchVersionServiceImpl-UpdateStatus' + #id", waitFor = false)
    public void setVersionRelease(Long id) {
        PatchVersion patchVersion = accessObject(id);
        if(!patchVersion.getUpdateStatus().equals(PatchVersion.UPDATE_STATUS_GRAY)){
            throw new HandleException("当前版本还不能进行发布");
        }
        patchVersion.setUpdateStatus(PatchVersion.UPDATE_STATUS_RELEASE);
        save(patchVersion);
    }

    @Override
    @DistributedLock(key = "'PatchVersionServiceImpl-UpdateStatus' + #id", waitFor = false)
    public void setVersionDefeated(Long id) {
        PatchVersion patchVersion = accessObject(id);
        if(patchVersion.getUpdateStatus().equals(PatchVersion.UPDATE_STATUS_RELEASE)){
            throw new HandleException("当前版本不能失败");
        }
        patchVersion.setUpdateStatus(PatchVersion.UPDATE_STATUS_DEFEATED);
        save(patchVersion);
    }

    @Override
    public PatchVersion getVersion(String os, String branch, String username) {
        os = os.toUpperCase();
        PatchVersion nowVersion = patchVersionDao.findTop1ByOsAndBranchOrderByVersionDesc(os, branch);

        if(nowVersion == null){
            nowVersion = new PatchVersion();
            nowVersion.setVersion(-1);
            nowVersion.setVersionMessage("版本不存在");
            return nowVersion;
        }

        if(nowVersion.getUpdateStatus().equals(PatchVersion.UPDATE_STATUS_RELEASE)){
            //最新版本处于发布状态
            return nowVersion;
        } else if(nowVersion.getUpdateStatus().equals(PatchVersion.UPDATE_STATUS_GRAY)){
            //最新版本处于灰度状态
            if(StringUtils.isNotEmpty(username) && patchGrayUserService.isGrayUser(username)){
                return nowVersion;
            }
        }

        //最后一个发布的版本
        return patchVersionDao.findTop1ByOsAndBranchAndUpdateStatusOrderByVersionDesc(os, branch, PatchVersion.UPDATE_STATUS_RELEASE);
    }

    @Override
    @Transactional
    public void removeByBranch(String branch) {
        patchVersionDao.deleteByBranch(branch);
    }
}
