package com.openhis.web.pharmacymanage.appservice.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.core.common.utils.poi.ExcelUtil;
import com.openhis.web.inventorymanage.dto.ReceiptPageDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.core.domain.entity.SysDictData;
import com.core.system.service.ISysDictTypeService;
import com.openhis.administration.domain.Practitioner;
import com.openhis.administration.service.IPractitionerService;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.enums.DispenseStatus;
import com.openhis.common.enums.EncounterClass;
import com.openhis.common.enums.PublicationStatus;
import com.openhis.common.enums.RequestStatus;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.web.pharmacymanage.appservice.IMedicationDetailsAppService;
import com.openhis.web.pharmacymanage.dto.MedDetailedAccountPageDto;
import com.openhis.web.pharmacymanage.dto.MedDetailsInitDto;
import com.openhis.web.pharmacymanage.dto.MedDetailsSearchParam;
import com.openhis.web.pharmacymanage.mapper.MedicationDetailsMapper;
import com.openhis.web.reportmanage.utils.ExcelFillerUtil;

/**
 * 发药明细 应用实现类
 *
 * @author yuanzs
 * @date 2025/4/14
 */
@Service
public class MedicationDetailsAppServiceImpl implements IMedicationDetailsAppService {

    @Autowired
    private MedicationDetailsMapper medicationDetailsMapper;

    @Autowired
    private ISysDictTypeService sysDictTypeService;

    @Autowired
    private IPractitionerService iPractitionerService;

    /**
     * 获取页面初始化信息
     */


    @Override
    public R<?> init() {

        MedDetailsInitDto initDto = new MedDetailsInitDto();

        // 查询医疗参与者列表
        List<Practitioner> list = iPractitionerService.getList();
        initDto.setPractitionerList(list);
        // 获取状态
        List<MedDetailsInitDto.statusEnumOption> statusEnumOptions = Stream.of(PublicationStatus.values())
            .map(status -> new MedDetailsInitDto.statusEnumOption(status.getValue(), status.getInfo()))
            .collect(Collectors.toList());

        // 结算状态
        initDto.setStatusSettlementOptions(statusEnumOptions)
            // 出院状态
            .setStatusDischargeOptions(statusEnumOptions);

        return R.ok(initDto);

    }

    /**
     * 门诊人员发药明细表
     *
     * @param medDetailsSearchParam 查询条件
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @param searchKey 模糊查询关键字
     * @param request 请求数据
     * @return 门诊人员发药明细表
     */
    @Override
    public R<?> getAmbPractitionerDetailPage(MedDetailsSearchParam medDetailsSearchParam, Integer pageNo,
        Integer pageSize, String searchKey, HttpServletRequest request) {
        Integer flg = medDetailsSearchParam.getFlag();
        medDetailsSearchParam.setFlag(null);
        // 构建查询条件
        QueryWrapper<MedDetailsSearchParam> queryWrapper = HisQueryUtils.buildQueryWrapper(medDetailsSearchParam,
            searchKey, new HashSet<>(Arrays.asList("patient_name", "medication_name", "bus_no", "py_str")), request);

        Page<MedDetailedAccountPageDto> medDetailsPage =
            medicationDetailsMapper.selectAmbPractitionerDetailPage(new Page<>(pageNo, pageSize), queryWrapper,
                EncounterClass.AMB.getValue(), DispenseStatus.COMPLETED.getValue(), RequestStatus.COMPLETED.getValue(),
                DispenseStatus.REFUNDED.getValue(), 1, flg, CommonConstants.TableName.MED_MEDICATION_DEFINITION,
                CommonConstants.TableName.ADM_DEVICE_DEFINITION);

        return R.ok(medDetailsPage);

    }

    /**
     * 发药明细导出
     *
     * @param medDetailsSearchParam 查询条件
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @param searchKey 模糊查询关键字
     * @param response 响应数据
     * @param request 请求数据
     *
     */
    @Override
    public void makeExcelFile(MedDetailsSearchParam medDetailsSearchParam, Integer pageNo, Integer pageSize,
        String searchKey, HttpServletResponse response, HttpServletRequest request) {
        R<?> result = this.getAmbPractitionerDetailPage(medDetailsSearchParam, 1, 10000, searchKey, request);
        if (result != null && result.getData() != null) {
            // 先获取Page对象，再获取其中的记录列表
            Page<MedDetailedAccountPageDto> pageData = (Page<MedDetailedAccountPageDto>)result.getData();
            List<MedDetailedAccountPageDto> dataList = pageData.getRecords();

            // 获取字典数据
            for (MedDetailedAccountPageDto medDetailedAccountPageDto : dataList) {
                String unitCode = medDetailedAccountPageDto.getUnitCode();
                // 添加空值检查
                if (unitCode != null && sysDictTypeService != null) {
                    // 缓存字典数据，避免重复查询
                    List<SysDictData> unitCodelist = sysDictTypeService.selectDictDataByType("unit_code");
                    if (unitCodelist != null) {
                        for (SysDictData dictData : unitCodelist) {
                            if (dictData != null && dictData.getDictValue() != null
                                && dictData.getDictValue().equals(unitCode)) {
                                medDetailedAccountPageDto.setUnitCode_dictText(dictData.getDictLabel());
                                break;
                            }
                        }
                    }
                }
            }

            // 将发药数量与单位拼接
            for (MedDetailedAccountPageDto medDetailedAccountPageDto : dataList) {
                String unitCode_dictText = medDetailedAccountPageDto.getUnitCode_dictText();
                Integer dispenseQuantity = medDetailedAccountPageDto.getDispenseQuantity();
                // 将发药数量与单位拼接
                medDetailedAccountPageDto.setDispenseQuantitystr(dispenseQuantity + unitCode_dictText);
            }

            // 将退药数量与单位拼接
            for (MedDetailedAccountPageDto medDetailedAccountPageDto : dataList) {
                String unitCode_dictText = medDetailedAccountPageDto.getUnitCode_dictText();
                Integer refundQuantity = medDetailedAccountPageDto.getRefundQuantity();
                // 添加完整的空值检查和默认值处理
                String unitText = (unitCode_dictText != null) ? unitCode_dictText : "";
                if (refundQuantity == null) {
                    medDetailedAccountPageDto.setRefundQuantitystr("0.00" + unitCode_dictText);
                } else if (refundQuantity == 0) {
                    medDetailedAccountPageDto.setRefundQuantitystr("0.00" + unitCode_dictText);
                } else {
                    medDetailedAccountPageDto.setRefundQuantitystr(refundQuantity.toString() + unitCode_dictText);
                }
            }

            // 将退药金额
            for (MedDetailedAccountPageDto medDetailedAccountPageDto : dataList) {
                BigDecimal refundPrice = medDetailedAccountPageDto.getRefundPrice();
                if (refundPrice == null) {
                    medDetailedAccountPageDto.setRefundPricestr("0.00" );
                } else if (refundPrice.signum() == 0) {
                    medDetailedAccountPageDto.setRefundPricestr("0.00" );
                } else {
                    refundPrice = refundPrice.setScale(6, RoundingMode.HALF_UP);
                    medDetailedAccountPageDto.setRefundPricestr(refundPrice.toString() );
                }

            }

            //发药金额
            for (MedDetailedAccountPageDto medDetailedAccountPageDto : dataList) {
                BigDecimal dispensePrice = medDetailedAccountPageDto.getDispensePrice();
                if (dispensePrice == null) {
                    medDetailedAccountPageDto.setDispensePricestr("0.00" );
                } else if (dispensePrice.signum() == 0) {
                    medDetailedAccountPageDto.setDispensePricestr("0.00" );
                } else {
                    dispensePrice = dispensePrice.setScale(6, RoundingMode.HALF_UP);
                    medDetailedAccountPageDto.setDispensePricestr(dispensePrice.toString() );
                }

            }
            // 添加项目类别
            for (MedDetailedAccountPageDto medDetailedAccountPageDto : dataList) {
                String itemTable = medDetailedAccountPageDto.getItemTable();
                if (itemTable != null) {
                    if(itemTable.equals("med_medication_definition")){
                        medDetailedAccountPageDto.setItemTable("药品");
                    }
                    if(itemTable.equals("adm_device_definition")){
                        medDetailedAccountPageDto.setItemTable("耗材");
                    }
                }
                else{
                    medDetailedAccountPageDto.setItemTable("未知类型");
                }
            }

            //判断项目类别  

            try {
                // 准备表头（key对应DTO的字段名）
                //Map<String, String> headers = new LinkedHashMap<>();
//                headers.put("practitionerName", "发药人");
//                headers.put("dispenseNo", "发药单号");
//                headers.put("medicationName", "药品项目");
//                headers.put("itemTable", "项目类别");
//                headers.put("busNo", "药品编码");
//                headers.put("ybNo", "医保编码");
//                headers.put("totalVolume", "规格");
//                headers.put("dispenseQuantitystr", "发药数量");
//                headers.put("dispensePricestr", "发药金额");
//                headers.put("refundQuantitystr", "退药数量");
//                headers.put("refundPricestr", "退药金额");
//                headers.put("lotNumber", "生产批号");
//                headers.put("manufacturerText", "厂家/产地");
//                headers.put("supplierName", "供应商");
//                headers.put("dispenseTime", "发药时间");
                // 导出到Excel
//                ExcelFillerUtil.makeExcelFile(response, dataList, headers, "发药明细", null);
                // 导出到Excel
                ExcelUtil<MedDetailedAccountPageDto> util = new ExcelUtil<MedDetailedAccountPageDto>(MedDetailedAccountPageDto.class);
                util.exportExcel(response,dataList,"发药明细");
            } catch (Exception e) {
                e.printStackTrace();
                System.out.printf("导出Excel失败：" + e.getMessage());
            }
        }
    }

    /**
     * 门诊发药明细流水账
     *
     * @param medDetailsSearchParam 查询条件
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @param searchKey 模糊查询关键字
     * @param request 请求数据
     * @return 门诊发药明细流水账
     */
    @Override
    public R<?> getAmbMedicationDispenseDetailPage(MedDetailsSearchParam medDetailsSearchParam, Integer pageNo,
        Integer pageSize, String searchKey, HttpServletRequest request) {

        Integer flg = medDetailsSearchParam.getFlag();
        medDetailsSearchParam.setFlag(null);

        // 构建查询条件
        QueryWrapper<MedDetailsSearchParam> queryWrapper = HisQueryUtils.buildQueryWrapper(medDetailsSearchParam,
            searchKey, new HashSet<>(Arrays.asList("patient_name", "medication_name", "bus_no", "py_str")), request);

        Page<MedDetailedAccountPageDto> medDetailsPage =
            medicationDetailsMapper.selectAmbPractitionerDetailPage(new Page<>(pageNo, pageSize), queryWrapper,
                EncounterClass.AMB.getValue(), DispenseStatus.COMPLETED.getValue(), RequestStatus.COMPLETED.getValue(),
                DispenseStatus.REFUNDED.getValue(), 2, flg, CommonConstants.TableName.MED_MEDICATION_DEFINITION,
                CommonConstants.TableName.ADM_DEVICE_DEFINITION);

        return R.ok(medDetailsPage);

    }

}
