package com.yihu.hos.crawler.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yihu.hos.core.compress.Zipper;
import com.yihu.hos.core.encrypt.MD5;
import com.yihu.hos.core.encrypt.RSA;
import com.yihu.hos.core.file.FileUtil;
import com.yihu.hos.core.httpclient.HttpHelper;
import com.yihu.hos.core.httpclient.HttpResponse;
import com.yihu.hos.core.log.Logger;
import com.yihu.hos.core.log.LoggerFactory;
import com.yihu.hos.crawler.model.config.SysConfig;
import com.yihu.hos.crawler.model.patient.Patient;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import java.io.File;
import java.security.Key;
import java.util.*;

/**
 * 档案上传
 *
 * @author Air
 * @version 1.0
 * @created 2015.07.06 15:58
 */
public class OldPatientCDAUpload {

    private static Logger logger = LoggerFactory.getLogger(OldPatientCDAUpload.class);

    public static String uploadMethod;

    /**
     * @param patient
     * @return
     * @modify 2015.09.15 airhead 修订删除目录
     * @modify 2015.09.19 airhead 修复无文档问题及错误信息
     */
    public boolean upload(Patient patient,String token) {
        ZipFile zipFile = zip(patient);
        try {
            if (zipFile == null || zipFile.file == null) {
                logger.info("压缩病人档案失败,病人文档未生成,patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo());
                return false;
            }
            boolean result = upload(patient, zipFile,token);
            if (!result) {
                logger.info("上传病人档案失败,patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo());
                FileUtil.deleteDirectory(new File(zipFile.directory));
                return false;
            }

            result = FileUtil.deleteDirectory(new File(zipFile.directory));
            if (!result) {
                logger.info("删除临时文件失败,patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo());
            }
        } catch (Exception e) {
            FileUtil.deleteDirectory(new File(zipFile.directory));
        }
        return true;
    }

    /**
     * @param patient
     * @return
     * @modify 从data目录生成zip数据
     */
    public ZipFile zip(Patient patient) {
        try {
            PatientCDAIndex patientCDAIndex = new PatientCDAIndex(patient);
            String dataDirectory = patientCDAIndex.getDataDirectory();
            String filePath = patientCDAIndex.createIndex(PatientCDAIndex.IndexType.ZIP, PatientCDAIndex.FileType.ZIP);
            UUID uuidPwd = UUID.randomUUID();
            String pwd = uuidPwd.toString();
            Key key = RSA.genPublicKey(SysConfig.getInstance().getPublicKeyMap().get(patient.getOrgCode()));
            if (key == null) {
                logger.info("压缩文件错误,无公钥信息.");
                FileUtil.deleteDirectory(new File( patientCDAIndex.getDirectory()));
                return null;
            }

            ZipFile zipFile = new ZipFile();
            zipFile.encryptPwd = RSA.encrypt(pwd, key);

            Zipper zipper = new Zipper();
            zipFile.file = zipper.zipFile(new File(dataDirectory), filePath, pwd);
            zipFile.dataDirectory = dataDirectory;
            zipFile.directory = patientCDAIndex.getDirectory();

            return zipFile;
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("从data目录生成zip数据时，压缩文件异常", e);
        }

        return null;
    }

    private boolean upload(Patient patient,  ZipFile zipFile, String token) {
        try {
            String uploadMethod = HttpHelper.defaultHttpUrl + "/packages";
            String fileMd5= MD5.getMd5ByFile(zipFile.file);
            List<NameValuePair> formParams = new ArrayList<>();
            formParams.add(new BasicNameValuePair("md5", fileMd5));
            formParams.add(new BasicNameValuePair("package_crypto", zipFile.encryptPwd));
            formParams.add(new BasicNameValuePair("org_code", patient.getOrgCode()));
            formParams.add(new BasicNameValuePair("token", token));
            Map<String, Object> header = new HashMap<>();
            header.put("Authorization", "Basic " + HttpHelper.clientKey);
            HttpResponse response = HttpHelper.postFile(uploadMethod, formParams, zipFile.file.getAbsolutePath(), header);
            if (response == null) {
                logger.info( "上传病人档案请求失败,patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo());
                return false;
            }

            if (response.getStatusCode() != 200) {
                logger.info( "上传病人档案请求失败,错误代码:" + response.getStatusCode() + ",patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo());
                return false;
            }

            ObjectMapper mapper = new ObjectMapper();
            JsonNode rootNode = mapper.readValue(response.getBody(), JsonNode.class);
            JsonNode codeNode = rootNode.get("code");
            String result = codeNode.asText();
            if (!result.equals("0")) {
                logger.info("上传病人档案失败,错误代码:" + result + ",patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo());
                return false;
            } else {
                logger.info( "上传病人档案成功,patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo());
                return true;
            }

        } catch (Exception e) {
            e.printStackTrace();
            logger.info( "上传病人档案异常,patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo());
            return false;
        }
    }

    private class ZipFile {
        public File file;
        public String encryptPwd;
        public String directory;
        public String dataDirectory;
    }

}
