package cn.com.victorysoft.business.indicator.service;

import cn.com.victorysoft.business.indicator.dao.QualityCheckDao;
import cn.com.victorysoft.business.indicator.entity.ObjectTypes;
import cn.com.victorysoft.business.indicator.entity.QualityCheck;
import cn.com.victorysoft.business.indicator.entity.WaterStation;
import cn.com.victorysoft.business.indicator.param.QualityCheckDelete;
import cn.com.victorysoft.business.indicator.param.QualityCheckParam;
import cn.com.victorysoft.business.indicator.param.QualityCheckSearchParam;
import cn.com.victorysoft.business.indicator.param.WaterStationParam;
import cn.com.victorysoft.business.sys.dto.Result;
import cn.com.victorysoft.business.sys.entity.ExportResult;
import cn.com.victorysoft.business.sys.entity.WellBasic;
import cn.com.victorysoft.business.sys.param.*;
import cn.com.victorysoft.business.sys.service.SysBaseService;
import cn.com.victorysoft.business.util.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class QualityCheckService {

    @Resource
    private QualityCheckDao qualityCheckDao;
    @Resource
    private SysBaseService sysBaseService;

    /**
     * 查询水质检测维护分页数据
     */
    public PageInfo<QualityCheck> selectPage(QualityCheckParam param) {
        PageUtils.startPage(param);
        return new PageInfo<>(qualityCheckDao.selectList(param));
    }

    /**
     * 查询阶段水质检测查询分页数据
     */
    public PageInfo<QualityCheck> selectSearchPage(QualityCheckSearchParam param) {
        PageUtils.startPage(param);
        List<QualityCheck> qualityChecks = this.selectSearchList(param);
        return new PageInfo<>(qualityChecks);
    }

    /**
     * 查询阶段水质检测查询分页数据
     */
    public List<QualityCheck> selectSearchList(QualityCheckSearchParam param) {

        List<QualityCheck> qualityChecks = qualityCheckDao.searchList(param);

        for (int i = 0; i < qualityChecks.size(); i++) {
            int o = i + 1 + param.getPageSize() * (param.getPageNum() - 1);
            QualityCheck qualityCheck = qualityChecks.get(i);
            qualityCheck.setSerialNumber(String.valueOf(o));
        }

        Map<String, BigDecimal> stringBigDecimalMap = qualityCheckDao.sumList(param);
        QualityCheck check1 = new QualityCheck();
        QualityCheck check2 = new QualityCheck();
        QualityCheck check3 = new QualityCheck();
        QualityCheck check4 = new QualityCheck();
        check1.setSerialNumber("标准值");
        check2.setSerialNumber("平均值");
        check3.setSerialNumber("达标率%");
        check4.setSerialNumber("不达标数平均值");
        if (stringBigDecimalMap != null) {
            check1.setOilStandard(stringBigDecimalMap.get("OIL1"));
            check1.setSuspensionStandard(stringBigDecimalMap.get("SUS1"));
            check1.setSrbStandard(stringBigDecimalMap.get("SRB1"));
            check1.setParticleStandard(stringBigDecimalMap.get("PAR1"));
            check1.setCorrosionStandard(stringBigDecimalMap.get("COR1"));
            check1.setAuxiliaryStandard(stringBigDecimalMap.get("AUX1"));
            check2.setOilStandard(stringBigDecimalMap.get("OIL2"));
            check2.setSuspensionStandard(stringBigDecimalMap.get("SUS2"));
            check2.setSrbStandard(stringBigDecimalMap.get("SRB2"));
            check2.setParticleStandard(stringBigDecimalMap.get("PAR2"));
            check2.setCorrosionStandard(stringBigDecimalMap.get("COR2"));
            check2.setAuxiliaryStandard(stringBigDecimalMap.get("AUX2"));
            check3.setOilStandard(stringBigDecimalMap.get("OIL3"));
            check3.setSuspensionStandard(stringBigDecimalMap.get("SUS3"));
            check3.setSrbStandard(stringBigDecimalMap.get("SRB3"));
            check3.setParticleStandard(stringBigDecimalMap.get("PAR3"));
            check3.setCorrosionStandard(stringBigDecimalMap.get("COR3"));
            check3.setAuxiliaryStandard(stringBigDecimalMap.get("AUX3"));
            check4.setOilStandard(stringBigDecimalMap.get("OIL4"));
            check4.setSuspensionStandard(stringBigDecimalMap.get("SUS4"));
            check4.setSrbStandard(stringBigDecimalMap.get("SRB4"));
            check4.setParticleStandard(stringBigDecimalMap.get("PAR4"));
            check4.setCorrosionStandard(stringBigDecimalMap.get("COR4"));
            check4.setAuxiliaryStandard(stringBigDecimalMap.get("AUX4"));
        }
        qualityChecks.add(check1);
        qualityChecks.add(check2);
        qualityChecks.add(check3);
        qualityChecks.add(check4);

        return qualityChecks;
    }

    public List<ObjectTypes> selectTypes() {
        return qualityCheckDao.selectObjectType();
    }

    /**
     * 根据单位查询下属抽油机井号
     *
     * @param param 单位/油田/区块/井号参数
     * @return 井号列表，只返回20条
     */
    public List<WellBasic> selectWaterWellTop20(UnitFieldBlockWellParam param) {
        PageHelper.startPage(1, 20);
        return qualityCheckDao.selectWaterWells(param);
    }

    public List<WaterStation> selectWaterStation(WaterStationParam param) {
        return qualityCheckDao.selectWaterStations(param);
    }

    public int insert(QualityCheck param) {
        param.setCreateOn(new Date());
        return qualityCheckDao.insert(param);
    }

    public QualityCheck selectByPrimaryKey(QualityCheck key) {
        return qualityCheckDao.selectByPrimaryKey(key);
    }

    public int updateData(QualityCheck param) {

        return qualityCheckDao.updateData(param);
    }

    public int deleteByDate(QualityCheckDelete param) {
        return qualityCheckDao.deleteByDate(param);
    }

    /**
     * 模板下载
     */
    public void downloadTemplate(String fileName, HttpServletResponse response) throws IOException {
        InputStream in = new ClassPathResource("/import/" + fileName).getInputStream();
        XSSFWorkbook workbook = new XSSFWorkbook(in);
        fileName = URLEncoder.encode(fileName, "UTF-8");
        response.reset();
        response.setContentType("application/binary;charset=utf-8");
        response.setHeader("Content-disposition", "attachment; filename=" + fileName);
        OutputStream os = response.getOutputStream();
        workbook.write(os);
        os.flush();
    }

    /**
     * 导入
     */
    @SneakyThrows
    @Transactional
    public Result upload(MultipartFile file) {
        // 更新的变量
        List<ObjectTypes> objectTypes = this.selectTypes();
        Map<String, ObjectTypes> objectTypesMap = objectTypes.stream()
                .collect(Collectors.toMap(ObjectTypes::getFlagName, v -> v));
        try {
            List<List<Object>> list = ExcelUtils.readExcel(file, 0);
            // 从第三行开始解析
            for (int i = 2; i < list.size(); i++) {
                String objectTypeName = "";
                String objectName = "";
                String dateStr = "";
                try {
                    List<Object> row = list.get(i);
                    objectTypeName = row.get(0).toString();
                    objectName = row.get(1).toString();
                    dateStr = row.get(2).toString();
                    Date date = null;
                    try {
                        date = (Date) row.get(2);
                    } catch (ClassCastException e) {
                        if (dateStr.contains(" ")) {
                            if (dateStr.contains("-")) {
                                date = DateUtils.parseDate(dateStr, "yyyy-MM-dd HH:mm:ss");
                            }else {
                                date = DateUtils.parseDate(dateStr, "yyyy/MM/dd HH:mm:ss");
                            }
                        }else {
                            if (dateStr.contains("-")) {
                                date = DateUtils.parseDate(dateStr, "yyyy-MM-dd");
                            }else {
                                date = DateUtils.parseDate(dateStr, "yyyy/MM/dd");
                            }
                        }
                    }
                    if (date == null) {
                        throw new RuntimeException("第" + i + "行取样日期错误");
                    }
                    // 截掉时间
                    date = DateUtils.truncate(date, Calendar.DATE);
                    // 查询对象类型
                    ObjectTypes type = objectTypesMap.get(objectTypeName);
                    if (type == null) {
                        throw new RuntimeException("第" + i + "行取样点类型错误");
                    }
                    // 查询单位代码
                    String unitcode = null;
                    WaterStation waterStation = qualityCheckDao.selectStationByName(objectName);
                    WellBasic wellBasic = sysBaseService.selectWellBasic(objectName);
                    if (waterStation != null) {
                        unitcode = waterStation.getAreaCode();
                    }else if (wellBasic != null) {
                        unitcode = wellBasic.getUnitcode();
                    }
                    if (StringUtils.isEmpty(unitcode)) {
                        throw new RuntimeException("第" + i + "行取样点错误");
                    }

                    QualityCheck qualityCheck = new QualityCheck();
                    qualityCheck.setObjectType(type.getFlagCode());
                    qualityCheck.setObjectName(objectName);
                    qualityCheck.setRecordDate(date);
                    qualityCheck.setUnitCode(unitcode);
                    qualityCheck.setOilStandard(getBigDecimal(row, 3));
                    qualityCheck.setOilActual(getBigDecimal(row, 4));
                    qualityCheck.setSuspensionStandard(getBigDecimal(row, 5));
                    qualityCheck.setSuspensionActual(getBigDecimal(row, 6));
                    qualityCheck.setSrbStandard(getBigDecimal(row, 7));
                    qualityCheck.setSrbActual(getBigDecimal(row, 8));
                    qualityCheck.setParticleStandard(getBigDecimal(row, 9));
                    qualityCheck.setParticleActual(getBigDecimal(row, 10));
                    qualityCheck.setCorrosionStandard(getBigDecimal(row, 11));
                    qualityCheck.setCorrosionActual(getBigDecimal(row, 12));
                    qualityCheck.setAuxiliaryStandard(getBigDecimal(row, 13));
                    qualityCheck.setAuxiliaryActual(getBigDecimal(row, 14));
                    qualityCheck.setAuxiliaryName(getString(row, 15));

                    QualityCheck exists = this.selectByPrimaryKey(qualityCheck);
                    if (null != exists) {
                        throw new RuntimeException("第" + i + "行记录已存在");
                    }
                    this.insert(qualityCheck);
                }catch (Exception e) {
                    log.error("导入失败", e);
                }
            }
        }catch (Exception e) {
            log.error("文件解析失败", e);
            return Result.fail("导入失败");
        }

        return Result.success();
    }

    /**
     * 规范化字符串
     */
    private String standard(String str) {
        String destination = "";
        Pattern p = Pattern.compile("\\s*|\t|\r|\n");
        Matcher m = p.matcher(str);
        destination = m.replaceAll("");
        // 去掉最后的逗号
        String lastChar = destination.substring(destination.length() - 1);
        if (",".equals(lastChar)) {
            destination = destination.substring(0, destination.length() - 1);
        }
        return destination;
    }

    private BigDecimal getBigDecimal(List<Object> row, int index) {
        if (index >= row.size()) return null;
        Object value = row.get(index);
        if (value == null) return null;
        return new BigDecimal(standard(value.toString()));
    }

    private String getString(List<Object> row, int index) {
        if (index >= row.size()) return null;
        Object value = row.get(index);
        if (value == null) return null;
        return value.toString();
    }

}
