package com.ruoyi.os.controller;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.healthcare.HealthcareOsDiagnosisStatus;
import com.ruoyi.common.enums.healthcare.HealthcareOsDictionaryName;
import com.ruoyi.common.exception.UtilException;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.inventory.domain.HealthcareDrugArchive;
import com.ruoyi.os.domain.CountDiagnosisVO;
import com.ruoyi.os.domain.DrugArchivesVO;
import com.ruoyi.os.domain.HealthcareOsPatientDiagnosis;
import com.ruoyi.os.domain.HealthcareOsPrescriptionDetails;
import com.ruoyi.os.domain.PatientMedicalRecordsVO;
import com.ruoyi.os.service.IPatientDiagnosisService;

/**
 * 诊断(病历)信息Controller
 *
 * @author 何顺
 * @date 2024-09-17
 * @author 邵政文
 * @date 2025-05-14
 */
@RestController
@RequestMapping("/outpatientService/patientDiagnosis")
public class PatientDiagnosisController extends BaseController {

    @Autowired
    private IPatientDiagnosisService iPatientDiagnosisService;

    private static final int MONEY_SCALE = 2;
    private static final BigDecimal HUNDRED = new BigDecimal("100");

    // IPatientDiagnosisService

    /**
     * 查询病历信息列表 PatientDiagnosisController
     * 返回 os_patient_diagnosis
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:list')")
    @GetMapping("/list")
    public TableDataInfo list(HealthcareOsPatientDiagnosis healthcareOsPatientDiagnosis) {
        startPage();
        return getDataTable(iPatientDiagnosisService.queryMedicalRecordList(healthcareOsPatientDiagnosis));
    }

    /**
     * 导出接诊记录数据
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:export')")
    @Log(title = "接诊记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, PatientMedicalRecordsVO patientMedicalRecordsVO) {
        patientMedicalRecordsVO.setDictionariesNamePatientType("healthcare_os_patient_type");
        patientMedicalRecordsVO.setDictionariesNameGender("sys_user_sex");
        patientMedicalRecordsVO.setDictionariesNameIsInsured("healthcare_os_insured");
        patientMedicalRecordsVO.setDictionariesNameStatus("healthcare_os_diagnosis_status");

        // 获取所有患者处方详情列表
        List<PatientMedicalRecordsVO> list = iPatientDiagnosisService
                .gainPrescriptionDetailsList(patientMedicalRecordsVO);

        // 计算报销费用:医保时按总价 × 报销比率/100;非医保或比率为空时为0
        fillExportFields(list);

        ExcelUtil<PatientMedicalRecordsVO> util = new ExcelUtil<PatientMedicalRecordsVO>(PatientMedicalRecordsVO.class);
        util.exportExcel(response, list, "接诊记录数据");
    }

    /**
     * 导出发药记录数据
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:totalPriceExport')")
    @Log(title = "发药记录", businessType = BusinessType.EXPORT)
    @PostMapping("/totalPriceExport")
    public void totalPriceExport(HttpServletResponse response, PatientMedicalRecordsVO patientMedicalRecordsVO) {
        // healthcare_os_patient_type
        patientMedicalRecordsVO.setDictionariesNamePatientType("healthcare_os_patient_type");
        patientMedicalRecordsVO.setDictionariesNameGender("sys_user_sex");
        patientMedicalRecordsVO.setDictionariesNameIsInsured("healthcare_os_insured");
        patientMedicalRecordsVO.setDictionariesNameStatus("healthcare_os_diagnosis_status");
        patientMedicalRecordsVO.setStatus(HealthcareOsDiagnosisStatus.SENT_ALREADY.getDescription());
        List<PatientMedicalRecordsVO> list = iPatientDiagnosisService
                .gainPrescriptionDetailsList(patientMedicalRecordsVO);

        // 同步计算报销费用与患者应缴金额(总价格)
        fillExportFields(list);

        ExcelUtil<PatientMedicalRecordsVO> util = new ExcelUtil<PatientMedicalRecordsVO>(PatientMedicalRecordsVO.class);
        util.exportExcel(response, list, "接诊记录数据");
    }

    /**
     * 查询患者病历详情
     * 杩斿洖 PatientMedicalRecordsVO
     * 鍙傛暟 id
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:getInfo')")
    @GetMapping("/getInfo/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(iPatientDiagnosisService.gainPatientDiagnosisInformation(id));
    }

    /**
     * 修改 患者病历详情
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:update')")
    @PostMapping("/update")
    public AjaxResult update(@RequestBody PatientMedicalRecordsVO patientMedicalRecordsVO) {
        // 修改 患者病历详情信息
        iPatientDiagnosisService.updateDiagnosis(patientMedicalRecordsVO);
        // 修改 患者诊断状态
        return toAjax(iPatientDiagnosisService.updateStatus(patientMedicalRecordsVO.getPatientDiagnosisId(),
                HealthcareOsDiagnosisStatus.READY_TO_GO.getDescription()));
    }

    /**
     * 保存 修改 患者 诊断 信息 saveDiagnosis
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:saveUpdate')")
    @PostMapping("/saveUpdate")
    public AjaxResult saveUpdate(@RequestBody PatientMedicalRecordsVO patientMedicalRecordsVO) {
        //
        return toAjax(iPatientDiagnosisService.saveUpdateDiagnosis(patientMedicalRecordsVO));
    }

    /**
     * 发药更正:仅调整是否医保与报销比率等基础字段
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:adjustBasic')")
    @Log(title = "发药更正", businessType = BusinessType.UPDATE)
    @PostMapping("/adjustBasic")
    public AjaxResult adjustBasic(@RequestBody PatientMedicalRecordsVO patientMedicalRecordsVO) {
        return toAjax(iPatientDiagnosisService.adjustBasicFields(patientMedicalRecordsVO));
    }

    /**
     * 修改患者诊断状态( 修改为 已发药)
     * MedicationAlreadyIssued
     * MedicationAlreadyIssued new Long(1)
     * deliverMedicine
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:deliverMedicine')")
    @GetMapping("/deliverMedicine/{id}")
    public AjaxResult deliverMedicine(@PathVariable("id") Long id) {
        return toAjax(
                iPatientDiagnosisService.updateStatus(id, HealthcareOsDiagnosisStatus.SENT_ALREADY.getDescription()));
    }

    /**
     * 修改患者诊断状态( 修改为 已退药)
     * Returned medication
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:returnedMedication')")
    @GetMapping("/returnedMedication/{id}")
    public AjaxResult returnedMedication(@PathVariable("id") Long id) {
        // 获取 患者 诊断 信息
        return toAjax(iPatientDiagnosisService.updateStatus(id, HealthcareOsDiagnosisStatus.REJECT.getDescription()));
    }

    /**
     * 添加患者诊断信息
     *
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:add')")
    @PostMapping("/add")
    public AjaxResult add(@RequestBody PatientMedicalRecordsVO patientMedicalRecordsVO) {

        return toAjax(iPatientDiagnosisService.addDiagnosis(patientMedicalRecordsVO));
    }

    /**
     * 保存 患者 诊断 信息 saveDiagnosis
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:save')")
    @PostMapping("/save")
    public AjaxResult save(@RequestBody PatientMedicalRecordsVO patientMedicalRecordsVO) {
        //
        return toAjax(iPatientDiagnosisService.saveDiagnosis(patientMedicalRecordsVO));
    }

    /**
     * 保存 变成 待发 修改 库存 患者 诊断 信息
     * 淇濆瓨淇敼搴撳瓨
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:saveAddDiagnosis')")
    @PostMapping("/saveAddDiagnosis")
    public AjaxResult saveAddDiagnosis(@RequestBody PatientMedicalRecordsVO patientMedicalRecordsVO) {
        //
        return toAjax(iPatientDiagnosisService.saveAddDiagnosis(patientMedicalRecordsVO));
    }

    /**
     * 删除 患者 诊断 信息
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:remove')")
    @GetMapping("/remove/{id}")
    public AjaxResult remove(@PathVariable("id") Long id) {
        //
        return toAjax(iPatientDiagnosisService.removeDiagnosis(id));
    }

    /**
     * 获取 药品 列表 gainDrugList
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:gainDrugList')")
    @PostMapping("/gainDrugList")
    public TableDataInfo gainDrugList(DrugArchivesVO drugArchivesVO) {
        return getDataTable(iPatientDiagnosisService.gainDrugList(drugArchivesVO));
    }

    /**
     * 获取 药品 价格 列表 gainDrugList Price
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:gainDrugPriceList')")
    @GetMapping("/gainDrugPriceList")
    public TableDataInfo gainDrugPriceList(String name) {
        HealthcareDrugArchive archive = new HealthcareDrugArchive();
        archive.setMedicineName(name);
        return getDataTable(iPatientDiagnosisService.gainDrugPriceList(archive));
    }

    /**
     * 获取 药品 名称 列表
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:gainMedicineNameList')")
    @GetMapping("/gainMedicineNameList")
    public TableDataInfo gainMedicineNameList() {
        return getDataTable(iPatientDiagnosisService.gainMedicineNameList(new HealthcareDrugArchive()));
    }

    /**
     * 获取药品名称(参数)
     * 鍙傛暟 鑽搧 鍚嶇О
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:gainMedicineNameList')")
    @GetMapping("/gainMedicineNameUntList")
    public TableDataInfo gainMedicineNameUntList() {
        HealthcareDrugArchive drugArchive = new HealthcareDrugArchive();
        return getDataTable(iPatientDiagnosisService.gainMedicineNameList(drugArchive));
    }

    /**
     * 获取 药品 档案 列表
     * 鑽搧 鍚嶇О 鏄?鍞竴鐨?
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:gainMedicineArchiveList')")
    @GetMapping("/gainMedicineArchiveList")
    public TableDataInfo gainMedicineArchiveList(DrugArchivesVO drugArchivesVO) {
        startPage();
        return getDataTable(iPatientDiagnosisService.gainMedicineArchiveList(drugArchivesVO));
    }

    /**
     * 获取 药品 库存 详细 列表
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:gainDrugInventoryList')")
    @GetMapping("/gainDrugInventoryList")
    public TableDataInfo gainDrugInventoryList(DrugArchivesVO drugArchivesVO) {
        //
        startPage();
        return getDataTable(iPatientDiagnosisService.gainDrugInventoryList(drugArchivesVO));
    }

    /**
     *
     */
    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:gainPatientDiagnosisListXml')")
    @GetMapping("/gainPatientDiagnosisListXml")
    public TableDataInfo gainPatientDiagnosisListXml() {
        //
        PatientMedicalRecordsVO patientMedicalRecordsVO = new PatientMedicalRecordsVO();
        // healthcare_os_patient_type
        patientMedicalRecordsVO.setDictionariesNamePatientType("healthcare_os_patient_type");
        patientMedicalRecordsVO.setDictionariesNameGender("sys_user_sex");
        patientMedicalRecordsVO.setDictionariesNameIsInsured("healthcare_os_insured");
        patientMedicalRecordsVO.setDictionariesNameStatus("healthcare_os_diagnosis_status");
        return getDataTable(iPatientDiagnosisService.gainPrescriptionDetailsList(patientMedicalRecordsVO));
    }

    @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:gainPatientDiagnosisListTotalPriceXml')")
    @GetMapping("/gainPatientDiagnosisListTotalPriceXml")
    public TableDataInfo gainPatientDiagnosisListTotalPriceXml() {
        //
        PatientMedicalRecordsVO patientMedicalRecordsVO = new PatientMedicalRecordsVO();
        // healthcare_os_patient_type
        patientMedicalRecordsVO.setDictionariesNamePatientType("healthcare_os_patient_type");
        patientMedicalRecordsVO.setDictionariesNameGender("sys_user_sex");
        patientMedicalRecordsVO.setDictionariesNameIsInsured("healthcare_os_insured");
        patientMedicalRecordsVO.setDictionariesNameStatus("healthcare_os_diagnosis_status");
        //
        patientMedicalRecordsVO.setStatus(HealthcareOsDiagnosisStatus.SENT_ALREADY.getDescription());
        return getDataTable(iPatientDiagnosisService.gainPrescriptionDetailsList(patientMedicalRecordsVO));
    }

    /**
     * obtain symptom statistics number
     * 鑾峰彇 鐥囩姸 缁熻 鏁伴噺
     */
    // @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:obtainSymptomStatisticsNumber')")
    @GetMapping("/obtainSymptomStatisticsNumber")
    public TableDataInfo obtainSymptomStatisticsNumber(CountDiagnosisVO countDiagnosisVO) {
        //
        countDiagnosisVO = stringToDate(countDiagnosisVO);
        //
        countDiagnosisVO.setDictionariesNameSymptom(HealthcareOsDictionaryName.OS_SYMPTOM);
        //
        return getDataTable(iPatientDiagnosisService.obtainSymptomStatisticsNumber(countDiagnosisVO));
    }

    /**
     * obtain symptom statistics number
     * 获取 症状 统计 数量 月份
     */
    // @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:obtainSymptomStatisticsNumberMonth')")
    @GetMapping("/obtainSymptomStatisticsNumberMonth")
    public TableDataInfo obtainSymptomStatisticsNumberMonth(CountDiagnosisVO countDiagnosisVO) {
        //
        countDiagnosisVO = stringToDate(countDiagnosisVO);
        //
        countDiagnosisVO.setDictionariesNameSymptom(HealthcareOsDictionaryName.OS_SYMPTOM);
        //
        return getDataTable(iPatientDiagnosisService.obtainSymptomStatisticsNumberMonth(countDiagnosisVO));
    }

    /**
     * 按患者ID统计历史医保报销累计金额(仅统计已发药)
     */
    // @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:historyReimbursement')")
    @GetMapping("/getHistoryReimbursement/{patientId}")
    public AjaxResult getHistoryReimbursement(@PathVariable("patientId") Long patientId) {
        return AjaxResult
                .success(iPatientDiagnosisService.getHistoryReimbursementByPatientId(patientId, new java.util.Date()));
    }

    // @PreAuthorize("@ss.hasPermi('os:patientDiagnosis:historyReimbursement')")
    @GetMapping("/getHistoryReimbursementByYear")
    public AjaxResult getHistoryReimbursementByYear(
            @RequestParam("patientId") Long patientId,
            @RequestParam(value = "yearDate", required = false) java.util.Date yearDate) {
        return AjaxResult.success(iPatientDiagnosisService.getHistoryReimbursementByPatientId(patientId, yearDate));
    }

    /**
     * 处理 字符串 转换 date
     */
    public CountDiagnosisVO stringToDate(CountDiagnosisVO countDiagnosisVO) {
        if (countDiagnosisVO.getParams() != null) {
            Map<String, Object> params = countDiagnosisVO.getParams();
            String startTime = countDiagnosisVO.getParams().get("startTime").toString();
            String endTime = countDiagnosisVO.getParams().get("endTime").toString();
            SimpleDateFormat formTime = new SimpleDateFormat("yyyy-MM-dd");
            try {
                params.put("startTime", formTime.parse(startTime));
                params.put("endTime", formTime.parse(endTime));
                //
                countDiagnosisVO.setParams(params);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return countDiagnosisVO;
    }

    /**
     * 使用 进行 库存 判断 ( 根据 前端 传递的 数据 进行 判断 )
     * 进行 库存 的 判断 参数 药品 的 库存 数量 参数 不能为空
     */
    private void judgeStock(PatientMedicalRecordsVO patientMedicalRecordsVO) {
        patientMedicalRecordsVO.getPrescriptionDetailsList().forEach(item -> {
            item.forEach(prescriptionDetail -> {
                if (prescriptionDetail.getUnitQuantity() > prescriptionDetail.getInventoryCount()) {
                    // 发送 异常 信息
                    throw new UtilException("库存不足:" + prescriptionDetail.getMedicineName());
                }
            });
        });

    }

    /**
     *
     * 根据前端传回的身份证和姓名进行医保校验,判断该学生医保是否即用
     */
    @GetMapping("/verify")
    public AjaxResult verifyInsuranceStatus(
            @RequestParam String idCard,
            @RequestParam String name) {
        int status = iPatientDiagnosisService.verifyInsuranceStatus(idCard, name);
        return success(status);
    }

    private void fillExportFields(List<PatientMedicalRecordsVO> list) {
        for (PatientMedicalRecordsVO record : list) {
            BigDecimal total = calculateTotalPrice(record);
            BigDecimal totalScaled = scaleMoney(total);
            BigDecimal value = record.getValue();
            boolean insured = record.getIsInsured() != null && record.getIsInsured() == 0L;

            record.setPrescriptionUsage(buildPrescriptionUsage(record));
            record.setPrescriptionTotalAmount(totalScaled);

            if (insured && value != null && value.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal rate = value.divide(HUNDRED, 4, BigDecimal.ROUND_HALF_UP);
                BigDecimal calcR = totalScaled.multiply(rate);
                BigDecimal receivableAmount = totalScaled.subtract(calcR).setScale(MONEY_SCALE, BigDecimal.ROUND_CEILING);
                BigDecimal reimburse = totalScaled.subtract(receivableAmount);
                record.setReceivableAmount(receivableAmount);
                record.setEstimatedReimbursement(reimburse);
            } else {
                record.setEstimatedReimbursement(BigDecimal.ZERO.setScale(MONEY_SCALE, BigDecimal.ROUND_CEILING));
                record.setReceivableAmount(totalScaled);
            }
        }
    }

    private BigDecimal calculateTotalPrice(PatientMedicalRecordsVO record) {
        List<List<HealthcareOsPrescriptionDetails>> detailsList = record.getPrescriptionDetailsList();
        if (detailsList == null) {
            return record.getTotalPrice();
        }
        BigDecimal sum = BigDecimal.ZERO;
        boolean hasAny = false;
        for (List<HealthcareOsPrescriptionDetails> group : detailsList) {
            if (group == null) {
                continue;
            }
            for (HealthcareOsPrescriptionDetails detail : group) {
                if (detail == null) {
                    continue;
                }
                BigDecimal lineTotal = detail.getTotalPrice();
                if (lineTotal == null) {
                    Integer qty = detail.getTotalQuantity();
                    BigDecimal unitPrice = detail.getUnitPrice();
                    if (qty != null && unitPrice != null) {
                        lineTotal = unitPrice.multiply(new BigDecimal(qty));
                    }
                }
                if (lineTotal != null) {
                    lineTotal = scaleMoney(lineTotal);
                    sum = sum.add(lineTotal);
                    hasAny = true;
                }
            }
        }
        return hasAny ? sum : record.getTotalPrice();
    }

    private String buildPrescriptionUsage(PatientMedicalRecordsVO record) {
        List<List<HealthcareOsPrescriptionDetails>> detailsList = record.getPrescriptionDetailsList();
        if (detailsList == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (List<HealthcareOsPrescriptionDetails> group : detailsList) {
            if (group == null) {
                continue;
            }
            for (HealthcareOsPrescriptionDetails detail : group) {
                if (detail == null) {
                    continue;
                }
                String name = detail.getMedicineName();
                Integer qty = detail.getTotalQuantity();
                String unit = resolveUnitLabel(detail.getPackageUnit());
                if (unit.isEmpty()) {
                    unit = resolveUnitLabel(detail.getSplitUnit());
                }
                StringBuilder item = new StringBuilder();
                if (name != null && !name.trim().isEmpty()) {
                    item.append(name.trim());
                }
                if (qty != null) {
                    if (item.length() > 0) {
                        item.append(" ");
                    }
                    item.append(qty);
                    if (unit != null && !unit.trim().isEmpty()) {
                        item.append(unit.trim());
                    }
                }
                if (item.length() == 0) {
                    continue;
                }
                if (sb.length() > 0) {
                    sb.append("； ");
                }
                sb.append(item);
            }
        }
        return sb.toString();
    }

    private BigDecimal scaleMoney(BigDecimal value) {
        if (value == null) {
            return BigDecimal.ZERO.setScale(MONEY_SCALE, BigDecimal.ROUND_CEILING);
        }
        return value.setScale(MONEY_SCALE, BigDecimal.ROUND_CEILING);
    }

    private String resolveUnitLabel(String unit) {
        if (unit == null) {
            return "";
        }
        String raw = unit.trim();
        if (raw.isEmpty()) {
            return "";
        }
        if (raw.matches("^\\d+$")) {
            String label = DictUtils.getDictLabel("healthcare_packaging_unit", raw, "");
            return label == null ? "" : label.trim();
        }
        return raw;
    }
}
