package com.ywt.mg.services;

import com.ywt.gapi.ResultCode;
import com.ywt.gapi.base.file.ReadFileRequest;
import com.ywt.gapi.base.file.ReadFileResponse;
import com.ywt.mg.configs.Constants;
import com.ywt.mg.core.PagedList;
import com.ywt.mg.core.SqlHelper;
import com.ywt.mg.core.utils.*;
import com.ywt.mg.core.utils.serializers.JsonSerializer;
import com.ywt.mg.domain.entities.*;
import com.ywt.mg.domain.models.ConstantDef;
import com.ywt.mg.domain.models.ExcelDataMap;
import com.ywt.mg.domain.models.ExcelStyleMap;
import com.ywt.mg.domain.models.enums.DownloadRecordStatusEnum;
import com.ywt.mg.domain.models.enums.TosEnum;
import com.ywt.mg.domain.models.pojo.CustomExcelItem;
import com.ywt.mg.domain.models.pojo.ExcelCollectPojo;
import com.ywt.mg.domain.ywtDrugEntities.Pharmacy;
import com.ywt.mg.domain.ywtDrugEntities.PharmacyRepository;
import com.ywt.mg.params.downloadRecord.DownloadFileRequest;
import com.ywt.mg.params.downloadRecord.QueryDownloadRecordListRequest;
import com.ywt.mg.params.offline.DownloadOfflineListNewRequest;
import com.ywt.mg.web.BaseResponse;
import com.ywt.mg.web.DataResponse;
import com.ywt.mg.web.PageDataResponse;
import com.ywt.mg.web.common.ExcelDownloadSrv;
import com.ywt.mg.web.common.FileSrv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.stereotype.Service;
import sun.rmi.runtime.Log;
import sun.security.provider.MD5;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 下载记录相关方法
 *
 * @author daiyihua
 */
@Service
public class DownloadRecordService {

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

    @Autowired
    private DownloadRecordRepository downloadRecordRepository;

    @Autowired
    private AuthService authService;

    @Autowired
    private SqlHelper sqlHelper;

    @Autowired
    private FileSrv fileSrv;

    @Autowired
    private ExcelDownloadSrv excelDownloadSrv;

    /**
     * 得到（重复点击情况下的下载记录）或插入一条新的下载记录
     *
     * @param id        表ID，需要生成
     * @param name      名称（前端路径）（格式： 公司后台-一级菜单-二级菜单）
     * @param fileName  文件名称
     * @param paramJson 下载参数的json
     * @param paramUrl  下载参数url
     * @return 下载记录
     */
    public DownloadRecord getOrInsertDownloadRecordByHosp(int id, String name, String fileName, String paramUrl, String paramJson) {
        int pharmacyId = 0, hospitalId = 0, currentAdminId = 0;
        String pharmacyName = "", hospitalName = "", currentAdminName = "";
        MGAdmins currentAdmin = authService.getCurrentAdmin();
        if (!Checker.isNone(currentAdmin)) {
            currentAdminId = currentAdmin.getId();
            currentAdminName = currentAdmin.getAccount();
        }
        Pharmacy pharmacy = authService.getCurrentPharmacy();
        if (!Checker.isNone(pharmacy)) {
            pharmacyId = pharmacy.getId();
            pharmacyName = pharmacy.getName();
        }
        Hospital hospital = authService.getCurrentHospitalByCache();
        if (!Checker.isNone(hospital)) {
            hospitalId = hospital.getId();
            hospitalName = hospital.getName();
        }
        Map map = new HashMap();
        map.put("param", paramJson);
        map.put("adminId", currentAdminId);
        map.put("hospitalId", hospitalId);
        map.put("pharmacyId", pharmacyId);
        String paramMd5 = StringHelper.md5(JsonSerializer.toJson(map));
        // todo: 判断是否有同样的下载
//        DownloadRecord record = downloadRecordRepository.findCreatingLeastOne(currentAdminId, paramMd5, paramUrl);
//        if (!Checker.isNone(record)) {
//            return record;
//        }
        DownloadRecord record;
        record = new DownloadRecord();
        record.setId(id);
        record.setName(name);
        record.setFileName(fileName);
        record.setPharmacyId(pharmacyId);
        record.setPharmacyName(pharmacyName);
        record.setHospitalId(hospitalId);
        record.setHospitalName(hospitalName);
        record.setAdminId(currentAdminId);
        record.setAdminName(currentAdminName);
        record.setCreateTime(new Date());
        record.setDeleted(false);
        record.setParamMd5(paramMd5);
        record.setParamJson(paramJson);
        record.setParamUrl(paramUrl);
        record.setStatus(DownloadRecordStatusEnum.Default.getValue());
        record.setUpdateTime(new Date());
        downloadRecordRepository.saveAndFlush(record);
        return record;
    }


    public DownloadRecord getOrInsertDownloadRecord(int id, String name, String fileName, String paramUrl, String paramJson) {
        int pharmacyId = 0, hospitalId = 0, currentAdminId = 0;
        String pharmacyName = "", hospitalName = "", currentAdminName = "";
        MGAdmins currentAdmin = authService.getCurrentAdmin();
        if (!Checker.isNone(currentAdmin)) {
            currentAdminId = currentAdmin.getId();
            currentAdminName = currentAdmin.getAccount();
        }
        Pharmacy pharmacy = authService.getCurrentPharmacy();
        if (!Checker.isNone(pharmacy)) {
            pharmacyId = pharmacy.getId();
            pharmacyName = pharmacy.getName();
        }
//        Hospital hospital = authService.getCurrentHospitalByCache();
//        if (!Checker.isNone(hospital)) {
////            hospitalId = hospital.getId();
//            hospitalName = hospital.getName();
//        }
        Map map = new HashMap();
        map.put("param", paramJson);
        map.put("adminId", currentAdminId);
        map.put("hospitalId", hospitalId);
        map.put("pharmacyId", pharmacyId);
        String paramMd5 = StringHelper.md5(JsonSerializer.toJson(map));
        // todo: 判断是否有同样的下载
//        DownloadRecord record = downloadRecordRepository.findCreatingLeastOne(currentAdminId, paramMd5, paramUrl);
//        if (!Checker.isNone(record)) {
//            return record;
//        }
        DownloadRecord record;
        record = new DownloadRecord();
        record.setId(id);
        record.setName(name);
        record.setFileName(fileName);
        record.setPharmacyId(pharmacyId);
        record.setPharmacyName(pharmacyName);
        record.setHospitalId(hospitalId);
        record.setHospitalName(hospitalName);
        record.setAdminId(currentAdminId);
        record.setAdminName(currentAdminName);
        record.setCreateTime(new Date());
        record.setDeleted(false);
        record.setParamMd5(paramMd5);
        record.setParamJson(paramJson);
        record.setParamUrl(paramUrl);
        record.setStatus(DownloadRecordStatusEnum.Default.getValue());
        record.setUpdateTime(new Date());
        downloadRecordRepository.saveAndFlush(record);
        return record;
    }


    public void saveUrlAndStatus(int id, String url, int status) {
        DownloadRecord record = downloadRecordRepository.findOne(id);
        if (!Checker.isNone(record)) {
            record.setUrl(url);
            record.setStatus(status);
            if (status == DownloadRecordStatusEnum.SUCCESS.getValue()) {
                Date finishTime = new Date();
                record.setFinishTime(finishTime);
                try {
                    int diff = (int) (finishTime.getTime() - record.getCreateTime().getTime());
                    record.setDifftime(diff);
                } catch (Exception e) {
                    logger.error("DownloadRecordService # saveUrlAndStatus 时间戳处理失败", e.getMessage(), e);
                }
            }
            downloadRecordRepository.saveAndFlush(record);
        }
    }

    public BaseResponse queryDownloadRecordList(QueryDownloadRecordListRequest request) throws Exception {
        PageDataResponse<Object> pageDataResponse = new PageDataResponse<>();
        PagedList<DownloadRecord> downloadRecordPagedList = queryDownloadRecordListCommon(request);
        //做转换处理
        if (!Checker.isNone(downloadRecordPagedList.getItems())) {
            List<Map<String, Object>> datas = CollectionUtil.toList(downloadRecordPagedList.getItems(), p -> {
                Map<String, Object> item = new HashMap<>(16);

                item.put("id", p.getId());
                item.put("name", p.getName());
                item.put("createTime", FormatUtil.createTimeFormatDetail(p.getCreateTime()));
                item.put("status", p.getStatus());
                item.put("statusStr", DownloadRecordStatusEnum.getDisplayName(p.getStatus()));
                if(p.getStatus() == DownloadRecordStatusEnum.Default.getValue()){
                    item.put("updateTime", "获取中...");
                } else {
                    item.put("updateTime", FormatUtil.createTimeFormatDetail(p.getUpdateTime()));
                }
                return item;
            });
            pageDataResponse.setData(datas);
        } else {
            pageDataResponse.setData(downloadRecordPagedList.getItems());
        }
        int count = downloadRecordPagedList.getTotal();
        pageDataResponse.setPageIndex(request.getPageIndex());
        pageDataResponse.setPageSize(request.getPageSize());
        pageDataResponse.setTotalCount(count);
        return pageDataResponse.succeed("处理成功");
    }

    private PagedList<DownloadRecord> queryDownloadRecordListCommon(QueryDownloadRecordListRequest request) throws ParseException {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " ( 1=1 ) ";
        whereSql += "and (deleted = 0)";

        int hospitalId = request.getHospitalId();
        if (hospitalId >= 0) {
            whereSql += " and ( hospital_id = ?)";
            paramList.add(hospitalId);
        }
        int adminId = request.getAdminId();
        if (adminId > 0) {
            whereSql += " and ( admin_id = ?)";
            paramList.add(adminId);
        }
        int status = Checker.getIntegerValue(request.getStatus());
        if(status == 1){
//            whereSql += " and ( status = ?)";
//            paramList.add(status);
        } else {
            whereSql += " and ( status = 0 or status = 1)";
        }
        String formatDate = "yyyy-MM-dd";
        SimpleDateFormat format = new SimpleDateFormat(formatDate);
        String endTime = getCurrentDate();
        if (!Checker.isNull(endTime)) {
            whereSql += " and ( create_time < ?)";
            Date date = format.parse(endTime);
            //把日期往后增加一天.整数往后推,负数往前移动
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(date);
            calendar.add(calendar.DATE, 1);
            date = calendar.getTime();   //这个时间就是日期往后推一天的结果

            paramList.add(date);
//            paramList.add(date);
        }
//        Date date = new Date();
//        Calendar calendar = new GregorianCalendar();
//        calendar.setTime(date);
//        calendar.add(calendar.DATE, 1);


        String startTime = DateUtil.getPastDate(7);
        if (!Checker.isNull(startTime)) {
            whereSql += " and ( create_time >= ?)";
            Date date = format.parse(startTime);
            paramList.add(date);
//            paramList.add(date);
        }

        int pageIndex = request.getPageIndex();
        int pageSize = request.getPageSize();
        return sqlHelper.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", DownloadRecord.class, paramList.toArray());
    }

    public void downloadFile(DownloadFileRequest request, HttpServletResponse httpServletResponse) {
        int downloadRecordId = request.getDownloadRecordId();
        try {
            if (downloadRecordId <= 0) {
                return;
            }
            DownloadRecord record = downloadRecordRepository.findOne(downloadRecordId);
            if (!Checker.isNone(record)) {
                String fileName = record.getFileName();
                httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(), Constants.CHARSET_NAME));
                httpServletResponse.setContentType("application/vnd.ms-excel;charset=UTF-8");
                httpServletResponse.setHeader("Pragma", "no-cache");
                httpServletResponse.setHeader("Cache-Control", "no-cache");
                httpServletResponse.setDateHeader("Expires", 0);

                OutputStream out = httpServletResponse.getOutputStream();
                String url = Checker.getStringValue(record.getUrl());
                if (!Checker.isNone(url)) {
                    byte[] b = fileSrv.readFile(url);
                    if (!Checker.isNone(b)) {
                        if (!Checker.isNone(b)) {
                            out.write(b);
                        }
                    }
                    out.flush();
                    out.close();
                }
            }
        } catch (Exception e) {
            logger.error("DownloadRecordService#downloadFile(), downloadRecordId={}", downloadRecordId, e.getMessage(), e);
        }
    }

    /**
     * 创建文件 并且上传到 OSS，最后保存到本地数据库
     *
     * @param fileName         文件名称
     * @param downloadRecordId 对应 downloadRecord 表ID
     * @param map              数据map
     * @param itemList         统计map
     * @throws Exception
     */
    public void createFileAndUploadOssAndSaveToDataBase(String fileName, int downloadRecordId, ExcelDataMap map, List<ExcelCollectPojo> itemList) throws Exception {
        // 前缀（路径）
        String preLocalPath = ConstantDef.LOCAL_DOWNLOAD_FILE_PATH;
        // 后缀（下载时间和格式）
        String suffixFormat = FormatUtil.formatDate(new Date(), FormatUtil.FORMAT_DATE_SECOND_NUMBER) + ConstantDef.EXCEL_SUFFIX_FORMAT;
        // 写到本地，拼凑本地路径
        String localPath = preLocalPath + fileName + suffixFormat;

        // 生成本地文件
        ExcelStyleMap excelStyleMap = new ExcelStyleMap(new String[]{});
        OutputStream ba = excelDownloadSrv.generateAndReturnExcelFileWithNoStyleAndCollectLocal(fileName, localPath, map, excelStyleMap, itemList);

        // 本地文件上传到oss，文件名带后缀
        String ossPath = String.format(ConstantDef.BIG_DATA_EXCEL_FILE_PATH, FormatUtil.formatDate(new Date(), "yyyy-MM"));
        String ossFileName = fileName + suffixFormat;
        DataResponse dataResponse = fileSrv.localFileUploadToOss(localPath, ossFileName, ossPath, ba);
        if (dataResponse.getCode() == BaseResponse.SUCCEED) {
            // 上传成功，将上传状态和地址保存到数据库
            saveUrlAndStatus(downloadRecordId, dataResponse.getData().toString(), DownloadRecordStatusEnum.SUCCESS.getValue());
        } else {
            // 上传失败，将上传状态保存到数据库
            saveUrlAndStatus(downloadRecordId, "", DownloadRecordStatusEnum.FAILURE.getValue());
        }
        // 删除文件
        fileSrv.deleteFile(localPath);
    }


    /**
     * 创建文件 并且上传到 OSS，最后保存到本地数据库
     *
     * @param fileName         文件名称
     * @param downloadRecordId 对应 downloadRecord 表ID
     * @param map              数据map
     * @param itemList         统计map
     * @throws Exception
     */
    public void createMealFileAndUploadOssAndSaveToDataBase(String fileName, int downloadRecordId, ExcelDataMap map, List<CustomExcelItem> itemList) throws Exception {
        // 前缀（路径）
        String preLocalPath = ConstantDef.LOCAL_DOWNLOAD_FILE_PATH;
        // 后缀（下载时间和格式）
        String suffixFormat = FormatUtil.formatDate(new Date(), FormatUtil.FORMAT_DATE_SECOND_NUMBER) + ConstantDef.EXCEL_SUFFIX_FORMAT;
        // 写到本地，拼凑本地路径
        String localPath = preLocalPath + fileName + suffixFormat;

        // 生成本地文件
        ExcelStyleMap excelStyleMap = new ExcelStyleMap(new String[]{});
        OutputStream ba = excelDownloadSrv.generateAndReturnMealExcelFileWithNoStyleAndCollectLocal(fileName, localPath, map, excelStyleMap, itemList);

        // 本地文件上传到oss，文件名带后缀
        String ossPath = String.format(ConstantDef.BIG_DATA_EXCEL_FILE_PATH, FormatUtil.formatDate(new Date(), "yyyy-MM"));
        String ossFileName = fileName + suffixFormat;
        DataResponse dataResponse = fileSrv.localFileUploadToOss(localPath, ossFileName, ossPath, ba);
        if (dataResponse.getCode() == BaseResponse.SUCCEED) {
            // 上传成功，将上传状态和地址保存到数据库
            saveUrlAndStatus(downloadRecordId, dataResponse.getData().toString(), DownloadRecordStatusEnum.SUCCESS.getValue());
        } else {
            // 上传失败，将上传状态保存到数据库
            saveUrlAndStatus(downloadRecordId, "", DownloadRecordStatusEnum.FAILURE.getValue());
        }
        // 删除文件
        fileSrv.deleteFile(localPath);
    }


    private String getCurrentDate() {
        try {
            String value = DateUtil.formatDate(new Date(), DateUtil.DADE_FROMAT_YMD);
            return value;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public BaseResponse queryPharDownloadRecordList(QueryDownloadRecordListRequest request) throws Exception {
        PageDataResponse<Object> pageDataResponse = new PageDataResponse<>();
        PagedList<DownloadRecord> downloadRecordPagedList = queryPharDownloadRecordListCommon(request);
        //做转换处理
        if (!Checker.isNone(downloadRecordPagedList.getItems())) {
            List<Map<String, Object>> datas = CollectionUtil.toList(downloadRecordPagedList.getItems(), p -> {
                Map<String, Object> item = new HashMap<>(16);

                item.put("id", p.getId());
                item.put("name", p.getName());
                item.put("createTime", FormatUtil.createTimeFormatDetail(p.getCreateTime()));
                item.put("status", p.getStatus());
                item.put("statusStr", DownloadRecordStatusEnum.getDisplayName(p.getStatus()));
                if(p.getStatus() == DownloadRecordStatusEnum.Default.getValue()){
                    item.put("updateTime", "获取中...");
                } else {
                    item.put("updateTime", FormatUtil.createTimeFormatDetail(p.getUpdateTime()));
                }
                return item;
            });
            pageDataResponse.setData(datas);
        } else {
            pageDataResponse.setData(downloadRecordPagedList.getItems());
        }
        int count = downloadRecordPagedList.getTotal();
        pageDataResponse.setPageIndex(request.getPageIndex());
        pageDataResponse.setPageSize(request.getPageSize());
        pageDataResponse.setTotalCount(count);
        return pageDataResponse.succeed("处理成功");
    }


    private PagedList<DownloadRecord> queryPharDownloadRecordListCommon(QueryDownloadRecordListRequest request) throws ParseException {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " ( 1=1 ) ";
        whereSql += "and (deleted = 0)";
        whereSql += "and (hospital_id = -1)";

//        int hospitalId = request.getHospitalId();
//        if (hospitalId >= 0) {
//            whereSql += " and ( hospital_id = ?)";
//            paramList.add(hospitalId);
//        }
        int adminId = request.getAdminId();
        if (adminId > 0) {
            whereSql += " and ( admin_id = ?)";
            paramList.add(adminId);
        }
        int pharmacyId = authService.getCurrentPharmacyId();
        if (pharmacyId > 0) {
            whereSql += " and ( pharmacy_id = ?)";
            paramList.add(pharmacyId);
        }

        int status = Checker.getIntegerValue(request.getStatus());
        if(status == 1){
            whereSql += " and ( status = ?)";
            paramList.add(status);
        } else {
            whereSql += " and ( status = 0 or status = 1)";
        }
        String formatDate = "yyyy-MM-dd";
        SimpleDateFormat format = new SimpleDateFormat(formatDate);
        String endTime = getCurrentDate();
        if (!Checker.isNull(endTime)) {
            whereSql += " and ( create_time < ?)";
            Date date = format.parse(endTime);
            //把日期往后增加一天.整数往后推,负数往前移动
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(date);
            calendar.add(calendar.DATE, 1);
            date = calendar.getTime();   //这个时间就是日期往后推一天的结果

            paramList.add(date);
//            paramList.add(date);
        }
//        Date date = new Date();
//        Calendar calendar = new GregorianCalendar();
//        calendar.setTime(date);
//        calendar.add(calendar.DATE, 1);


        String startTime = DateUtil.getPastDate(7);
        if (!Checker.isNull(startTime)) {
            whereSql += " and ( create_time >= ?)";
            Date date = format.parse(startTime);
            paramList.add(date);
//            paramList.add(date);
        }

        int pageIndex = request.getPageIndex();
        int pageSize = request.getPageSize();
        return sqlHelper.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", DownloadRecord.class, paramList.toArray());
    }

    public DownloadRecord getOrInsertPharDownloadRecord(int id, String name, String fileName, String paramUrl, String paramJson) {
        int pharmacyId = 0, hospitalId = -1, currentAdminId = 0;
        String pharmacyName = "", hospitalName = "", currentAdminName = "";
        MGAdmins currentAdmin = authService.getCurrentAdmin();
        if (!Checker.isNone(currentAdmin)) {
            currentAdminId = currentAdmin.getId();
            currentAdminName = currentAdmin.getAccount();
        }
        Pharmacy pharmacy = authService.getCurrentPharmacy();
        if (!Checker.isNone(pharmacy)) {
            pharmacyId = pharmacy.getId();
            pharmacyName = pharmacy.getName();
        }
//        Hospital hospital = authService.getCurrentHospitalByCache();
//        if (!Checker.isNone(hospital)) {
////            hospitalId = hospital.getId();
//            hospitalName = hospital.getName();
//        }
        Map map = new HashMap();
        map.put("param", paramJson);
        map.put("adminId", currentAdminId);
        map.put("hospitalId", hospitalId);
        map.put("pharmacyId", pharmacyId);
        String paramMd5 = StringHelper.md5(JsonSerializer.toJson(map));
        // todo: 判断是否有同样的下载
//        DownloadRecord record = downloadRecordRepository.findCreatingLeastOne(currentAdminId, paramMd5, paramUrl);
//        if (!Checker.isNone(record)) {
//            return record;
//        }
        DownloadRecord record;
        record = new DownloadRecord();
        record.setId(id);
        record.setName(name);
        record.setFileName(fileName);
        record.setPharmacyId(pharmacyId);
        record.setPharmacyName(pharmacyName);
        record.setHospitalId(hospitalId);
        record.setHospitalName(hospitalName);
        record.setAdminId(currentAdminId);
        record.setAdminName(currentAdminName);
        record.setCreateTime(new Date());
        record.setDeleted(false);
        record.setParamMd5(paramMd5);
        record.setParamJson(paramJson);
        record.setParamUrl(paramUrl);
        record.setStatus(DownloadRecordStatusEnum.Default.getValue());
        record.setUpdateTime(new Date());
        downloadRecordRepository.saveAndFlush(record);
        return record;
    }
}
