package com.eitc.patient.help;

import com.eitc.common.constant.Constants;
import com.eitc.common.core.domain.model.LoginUser;
import com.eitc.common.core.redis.RedisCache;
import com.eitc.common.monitor.FileSizeMonitor;
import com.eitc.common.utils.CommonUtils;
import com.eitc.common.utils.InterfaceVerificationUtil;
import com.eitc.common.utils.MessageUtils;
import com.eitc.common.utils.ShellUtils;
import com.eitc.common.utils.StringUtils;
import com.eitc.common.utils.http.HttpUtils;
import com.eitc.framework.manager.AsyncManager;
import com.eitc.framework.manager.factory.AsyncFactory;
import com.eitc.framework.web.service.TokenService;
import com.eitc.patient.vo.ClinicInfoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;










/**
 * 诊所信息的帮助类，可以做一些业务逻辑处理，一保证控制类的代码清晰简单
 *
 */


@Component
public class ClinicInfoHelper {

    @Resource
    private RestTemplate restTemplate;

    @Value("${Total.ip}")
    private String fileUrl;
    @Value("${Total.ipport}")
    private String fileUrlNoport;
    /**
     * 退出处理类
     */
    @Autowired
    private TokenService tokenService;


    @Autowired
    private RedisCache redisCache;

    /**
     * 获取履约信息
     * @return
     * @throws Exception
     */
    public Boolean getFulfillmentInformation(ClinicInfoVO clinicInfo, HttpServletRequest request){
        Map<String, Object> uriVariables = new HashMap<>();
//        final String plainText = "{\"phone\":\"12345678901\",\"serverCode\":\"ED39BA70-393D-4B28-ADE6-68184C0D6BAC\",\"clinicIp\":\"192.168.3.17\"}";
//        SM4Utils.encryptHex_CBC(plainText,uriVariables);
        String saSignStr = InterfaceVerificationUtil.getSaSignStr(uriVariables);
        ResponseExtractor<Boolean> responseExtractor = clientHttpResponse -> {
            // 设置响应头，直接用第三方文件服务的响应头
            clientHttpResponse.getHeaders().forEach((name, values) -> {
                if (name.equals("creatTime")) {
                    clinicInfo.setCreatTime(values.get(0));
                    return;
                }
                if (name.equals("expireTime")) {
                    clinicInfo.setExpireTime(values.get(0));
                }
                if (name.equals("quota")) {
                    clinicInfo.setQuota(values.get(0));
                }
                if (name.equals("versionRefer")) {
                    clinicInfo.setVersionRefer(CommonUtils.unicodeToChinese(values.get(0)));
                }
                if (name.equals("statusInt")) {
                    clinicInfo.setStatusInt(values.get(0));
                }
                if (name.equals("phone")) {
                    clinicInfo.setPhone(values.get(0));
                }
                if (name.equals("versionRepair")) {
                    clinicInfo.setVersionRepair(clinicInfo.getVersionRepairNew());
                    clinicInfo.setVersionRepairNew(values.get(0));
                }
                if (name.equals("versionInfo")) {
                    clinicInfo.setVersionInfo(clinicInfo.getVersionInfoNew());
                    clinicInfo.setVersionInfoNew(values.get(0));
                }
                if (name.equals("msg")) {
                    if (values.get(0).equals("1")){
                        // 如果需要续费 那么就退出登录，到登录界面进行续费提示
                        LoginUser loginUser = tokenService.getLoginUser(request);
                        if (StringUtils.isNotNull(loginUser))
                        {
                            String userName = loginUser.getUsername();
                            // 删除用户缓存记录
                            tokenService.delLoginUser(loginUser.getToken());
                            // 记录用户退出日志
                            AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
                        }
                        throw new RuntimeException("系统已到期，请续费！");
                    }
                }
            });
            return true;
        };
        String url = fileUrl+"api/sys/clinict/getClinictListInfo" + "?" + saSignStr;
        Boolean execute = restTemplate.execute(url, HttpMethod.GET, null, responseExtractor, uriVariables);
        return execute;

    }

    /**
     * 下载文件
     * @return
     * @throws Exception
     */
    public void pullTheUpgradePackage(Integer version){
        String url = fileUrl+"api/sys/clinict/downloadLocal?";
        Map<String, Object> uriVariables = new HashMap<>();
        uriVariables.put("version",version);
        // 这个是为了防止恶意请求来做的参数增加
        String saSignStr = InterfaceVerificationUtil.getSaSignStr(uriVariables);

        ResponseExtractor<Boolean> responseExtractor = clientHttpResponse -> {
            // 设置响应头，直接用第三方文件服务的响应头
            AtomicLong fileLength = new AtomicLong();
            AtomicReference<String> vCode = new AtomicReference<>("");
            AtomicReference<String> repairCode = new AtomicReference<>("");
            // 获取请求头信息
            clientHttpResponse.getHeaders().forEach((name, values) -> {
                if (name.equals("Content-Length")) {
                    fileLength.set(Long.parseLong(values.get(0)));
                }
                if (name.equals("vCode")) {
                    vCode.set(values.get(0));
                }
                if (name.equals("Content-Length")) {
                    repairCode.set(values.get(0));
                }
                if (name.equals("Content-Type")) {
                    if (!values.get(0).equals("application/octet-stream")){
                        throw new RuntimeException("文件下载失败");
                    }
                }
            });

            String versionStr = vCode.get();
            if (version == 2){
                versionStr = repairCode.get();
            }
            String path = "/home/uppackage/server_" + versionStr + ".tar"; // 文件的URL地址
//            String path = "F:\\Desktop\\test\\server_"+versionStr+".tar"; // 文件的URL地址
            try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get(path)))) {
                // 这是我想监控文件下载多少而做的线程监控 可以做进度条给前端
                FileSizeMonitor monitor = new FileSizeMonitor(new File(path),fileLength.get());
                monitor.startMonitoring();
                StreamUtils.copy(clientHttpResponse.getBody(), bufferedOutputStream);
            } catch (IOException e) {
                // 处理异常，比如文件找不到或读写错误
                System.err.println("文件下载失败: " + e.getMessage());
                throw new RuntimeException("文件下载失败" + e.getMessage());
            }
            return true;
        };
        restTemplate.execute(url+saSignStr, HttpMethod.GET, null, responseExtractor, uriVariables);


    }

    /**
     * 手动升级接口逻辑
     */
    public void identifyTheUpgrade() throws UnknownHostException {
        InetAddress hostAddr = InetAddress.getLocalHost();
        String hostIp = hostAddr.getHostAddress();
        System.out.println("hostIp:"+hostIp);
        redisCache.deleteObject("downloadStatus");
        HttpUtils.sendGet(fileUrlNoport+":8099/jar/identifyTheUpgrade");
    }

    /**
     * 读取redis 检测是否要升级 下载包完成之后会在redis 中存个状态
     * @return
     */
    public Integer getVersionChanges() {
        Integer downloadStatus = 0;
        if (redisCache.hasKey("downloadStatus") ){
            downloadStatus = redisCache.getCacheObject("downloadStatus");
        }
        return downloadStatus;

    }
}
