package thyyxxk.webserver.controller.medicalinsurance;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.dao.his.medicalinsurance.SetlOverLimitDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.medicalinsurance.manage.setloverlimit.ExcelData;
import thyyxxk.webserver.entity.medicalinsurance.manage.setloverlimit.OverLimitItem;
import thyyxxk.webserver.entity.medicalinsurance.manage.setloverlimit.SetlOverLimitEntity;
import thyyxxk.webserver.utils.ResultVoUtil;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/setlOverLimitAnalyze")
public class SetlOverLimitAnalyze {
    private final SetlOverLimitDao dao;

    @Autowired
    public SetlOverLimitAnalyze(SetlOverLimitDao dao) {
        this.dao = dao;
    }

    @PostMapping("/execute")
    public ResultVo<List<SetlOverLimitEntity>> execute(@RequestBody MultipartFile file) throws IOException {
        List<ExcelData> dataList = getOriginExcelData(file);
        if (dataList.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "未解析到数据。");
        }
        removeZfxd(dataList);
        Map<String, SetlOverLimitEntity> entityMap = new HashMap<>();
        List<SetlOverLimitEntity> result = new ArrayList<>();
        for (ExcelData data : dataList) {
            String key = data.getSetlId() + "^" + data.getDrugHisCode();
            if (entityMap.containsKey(key)) {
                makeDrugItem(data, entityMap.get(key));
            } else {
                SetlOverLimitEntity entity = makeEntity(data);
                makeDrugItem(data, entity);
                entityMap.put(key, entity);
                result.add(entity);
            }
        }
        for (SetlOverLimitEntity entity : result) {
            entity.getItems().sort(Comparator.comparing(OverLimitItem::getDetailSn));
        }
        groupByChargeDate(result);
        for (SetlOverLimitEntity entity : result) {
            BigDecimal sum = BigDecimal.ZERO;
            for (OverLimitItem item : entity.getItems()) {
                sum = sum.add(item.getPayAmt());
            }
            entity.setTotalAmt(sum);
            entity.setRefundAmt(sum.multiply(BigDecimal.ONE.subtract(entity.getSelfPayProp())));
        }
        return ResultVoUtil.success(result);
    }

    private void groupByChargeDate(List<SetlOverLimitEntity> list) {
        for (SetlOverLimitEntity entity : list) {
            List<OverLimitItem> items = entity.getItems();
            List<String> dateList = new ArrayList<>();
            for (int i = items.size() - 1; i >= 0; i--) {
                OverLimitItem item = items.get(i);
                if (!dateList.contains(item.getChargeDate()) && dateList.size() < entity.getOffset()) {
                    dateList.add(item.getChargeDate());
                }
            }
            items.removeIf(o -> !dateList.contains(o.getChargeDate()));
        }
    }

    private List<ExcelData> getOriginExcelData(MultipartFile file) {
        InputStream is = null;
        Workbook workbook;
        List<ExcelData> dataList = new ArrayList<>();
        DataFormatter df = new DataFormatter();
        try {
            is = file.getInputStream();
            workbook = WorkbookFactory.create(is);
            Sheet sheet = workbook.getSheetAt(0);
            int rowStart = 1;
            for (int i = rowStart; i <= sheet.getLastRowNum(); i++) {
                Row row = sheet.getRow(i);
                ExcelData data = new ExcelData();
                data.setDetailSn(Integer.parseInt(row.getCell(0).getStringCellValue()));
                data.setMdtrtId(df.formatCellValue(row.getCell(9)));
                data.setPatNo(row.getCell(10).getStringCellValue());
                data.setPatName(row.getCell(12).getStringCellValue());
                data.setDeptName(row.getCell(20).getStringCellValue());
                data.setBeginTime(row.getCell(21).getStringCellValue().split(" ")[0]);
                data.setEndTime(row.getCell(22).getStringCellValue().split(" ")[0]);
                data.setSetlId(df.formatCellValue(row.getCell(27)));
                data.setRuleDes(row.getCell(30).getStringCellValue());
                data.setPrice(BigDecimal.valueOf(row.getCell(31).getNumericCellValue()));
                data.setQuantity(BigDecimal.valueOf(row.getCell(32).getNumericCellValue()));
                data.setPayAmt(BigDecimal.valueOf(row.getCell(33).getNumericCellValue()));
                data.setDrugCode(row.getCell(36).getStringCellValue());
                data.setDrugName(row.getCell(37).getStringCellValue());
                data.setDoctorName(row.getCell(39).getStringCellValue());
                data.setDrugHisCode(row.getCell(40).getStringCellValue());
                data.setDrugHisName(row.getCell(41).getStringCellValue());
                data.setChargeDate(row.getCell(42).getStringCellValue().split(" ")[0]);
                data.setSelfPayProp(BigDecimal.valueOf(row.getCell(46).getNumericCellValue()));
                dataList.add(data);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != is) {
                try {
                    is.close();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        }
        return dataList;
    }

    private void removeZfxd(List<ExcelData> dataList) {
        List<String> tempList = new ArrayList<>();
        for (ExcelData data : dataList) {
            if (data.getQuantity().compareTo(BigDecimal.ZERO) < 0) {
                data.setRm(true);
                SetlOverLimitEntity entity = dao.getRawEntity(data.getSetlId());
                entity.setDetailSn(data.getDetailSn());
                Integer ori = dao.getOriDetailSn(entity);
                if (null != ori) {
                    String k = data.getSetlId() + "^" + data.getDrugHisCode() + "^" + data.getPatNo() + "^" + ori;
                    tempList.add(k);
                }
            }
        }
        dataList.removeIf(ExcelData::isRm);
        dataList.removeIf(data -> tempList.contains(data.getSetlId() + "^" + data.getDrugHisCode() + "^" + data.getPatNo() + "^" + data.getDetailSn()));
    }

    private SetlOverLimitEntity makeEntity(ExcelData data) {
        SetlOverLimitEntity entity = dao.getRawEntity(data.getSetlId());
        entity.setBeginTime(data.getBeginTime());
        entity.setEndTime(data.getEndTime());
        entity.setRuleDes(data.getRuleDes());
        entity.setDrugCode(data.getDrugCode());
        entity.setDrugName(data.getDrugName());
        entity.setDrugHisCode(data.getDrugHisCode());
        entity.setDrugHisName(data.getDrugHisName());
        entity.setSelfPayProp(data.getSelfPayProp());
        String des = entity.getRuleDes().replaceAll("天", "");
        String mid = des.split("不能超过")[1];
        String[] nums = mid.split(",实际使用");
        entity.setMax(Integer.parseInt(nums[0]));
        entity.setReal(Integer.parseInt(nums[1]));
        entity.setOffset(entity.getReal() - entity.getMax());
        return entity;
    }

    private void makeDrugItem(ExcelData data, SetlOverLimitEntity entity) {
        if (null == entity.getItems()) {
            entity.setItems(new ArrayList<>());
        }
        fillDrugItem(data, entity);
    }

    private void fillDrugItem(ExcelData data, SetlOverLimitEntity entity) {
        OverLimitItem drugItem = new OverLimitItem();
        drugItem.setLedgerSn(entity.getLedgerSn());
        drugItem.setDeptName(data.getDeptName());
        drugItem.setDoctorName(data.getDoctorName());
        drugItem.setDetailSn(data.getDetailSn());
        drugItem.setPrice(data.getPrice());
        drugItem.setQuantity(data.getQuantity());
        drugItem.setPayAmt(data.getPayAmt());
        drugItem.setChargeDate(data.getChargeDate());
        entity.getItems().add(drugItem);
    }
}
