/*
 * Copyright ©2023 CJB-CNIT Team. All rights reserved
 */
package com.openhis.web.ybmanage.controller;

import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

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

import com.core.common.annotation.Anonymous;
import com.openhis.web.ybmanage.dto.*;
import com.openhis.yb.domain.InpatientDischarge;
import com.openhis.yb.domain.InpatientReg;
import com.openhis.yb.dto.Catalogue1312Output;
import com.openhis.yb.dto.Clinic2208UnSetlInfoOutput;
import com.openhis.yb.dto.Financial3203AWebParam;
import com.openhis.yb.dto.Info1101Output;
import com.openhis.yb.dto.PatientInfoDto;
import com.openhis.yb.dto.Result;
import com.openhis.yb.dto.Settlement3201WebParam;
import com.openhis.yb.dto.Settlement3202WebParam;
import com.openhis.yb.dto.Settlement3209AWebParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.core.common.core.domain.R;
import com.core.common.exception.ServiceException;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.StringUtils;
import com.openhis.administration.domain.Encounter;
import com.openhis.administration.domain.Patient;
import com.openhis.administration.service.IEncounterService;
import com.openhis.administration.service.IPatientService;
import com.openhis.clinical.domain.ConditionDefinition;
import com.openhis.clinical.service.IConditionDefinitionService;
import com.openhis.common.constant.CommonConstants;
import com.openhis.financial.domain.Contract;
import com.openhis.financial.service.IContractService;
import com.openhis.web.ybmanage.service.IYbService;
import com.openhis.yb.domain.FinancialApplyRecord;
import com.openhis.yb.domain.InfoPerson;
import com.openhis.yb.dto.*;
import com.openhis.yb.service.IPerinfoService;
import com.openhis.yb.service.YbDao;
import com.openhis.yb.service.YbHttpUtils;
import com.openhis.yb.util.CommonConstant;

/**
 * 医保接口
 *
 * @author SunJQ
 * @date 2025-04-11
 */
@RestController
@RequestMapping("/yb-request")
public class YbController {

    @Autowired
    YbDao ybDao;
    @Autowired
    YbHttpUtils ybHttpUtils;
    @Autowired
    IPatientService patientService;
    @Autowired
    IPerinfoService iPerinfoService;
    @Autowired
    IEncounterService iEncounterService;
    @Autowired
    IContractService iContractService;
    @Autowired
    IConditionDefinitionService iConditionDefinitionService;
    @Autowired
    ResourceLoader resourceLoader;
    @Autowired
    IYbService ybService;

    /**
     * 【9001】
     *
     * @param practitionerId 参与者Id
     * @param mac 加密后的mac地址
     * @return 结果
     */
    @PostMapping("/sign")
    public R<?> sign(String practitionerId, String mac, String ip) {
        Sign signParam = ybDao.getSignParam(practitionerId, mac, ip);
        if (signParam == null) {
            throw new ServiceException("未生成签到参数");
        }
        List<Contract> contractList = iContractService.getContractListByYb();
        List<Sign9001Result> signResultList = new ArrayList<>();
        for (Contract contract : contractList) {
            Sign9001Result signResult = ybHttpUtils.sign(signParam, contract);
            if (signResult != null) {
                ybDao.saveSign(signParam, signResult);
                signResultList.add(signResult);
            }
        }
        if (contractList.size() == signResultList.size()) {
            return R.ok("签到成功");
        } else {
            return R.fail("签到失败");
        }
    }

    /**
     * 【1101】
     *
     * @param certType 就诊id
     * @param certNo 租户id
     * @return 结果
     */
    @PostMapping("/per-info")
    public R<?> getPerInfo(String certType, String certNo, String psnCertType) {
        Info1101ReadcardParam readcard = ybDao.getReadCard(certType, certNo);
        Info1101Output perInfo = ybHttpUtils.getPerInfo(readcard);
        if (perInfo != null) {
            ybDao.saveReadcardAndPerinfo(readcard, perInfo);
            PatientInfoDto patient = ybDao.getPatent(perInfo);
            return R.ok(patient);
        } else {
            return R.fail("未查询到患者信息");
        }
    }

    /**
     * 【5301】获取人员慢病
     *
     * @param encounterId 就诊id
     * @return 结果
     */
    @GetMapping("/getConditionDefinition")
    public R<?> getSpecialDia(Long encounterId) {

        Encounter encounter = iEncounterService.getById(encounterId);
        if (encounter == null) {
            throw new ServiceException("未获取到就诊信息");
        }
        Patient patient = patientService.getById(encounter.getPatientId());
        if (patient == null) {
            throw new ServiceException("未获取到患者信息");
        }
        InfoPerson perinfo =
            iPerinfoService.getPerInfoByIdCard(patient.getIdCard(), SecurityUtils.getLoginUser().getTenantId());
        if (perinfo == null) {
            throw new ServiceException("未连接医保获取患者信息");
        }
        Info1101Output info1101Output = JSON.parseObject(perinfo.getResult1101(), Info1101Output.class);
        List<Info5301SpecialConditionResult> feedetail = info1101Output.getFeedetail();

        Date currentDate = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<Info5301SpecialConditionResult> currentRangeResults = new ArrayList<>();
        for (Info5301SpecialConditionResult info5301SpecialConditionResult : feedetail) {
            try {
                Date begndate = dateFormat.parse(info5301SpecialConditionResult.getBegndate());
                Date enddate = dateFormat.parse(info5301SpecialConditionResult.getEnddate());

                // 检查当前日期是否在 begndate 和 enddate 之间
                if (currentDate.compareTo(begndate) >= 0 && currentDate.compareTo(enddate) <= 0) {
                    currentRangeResults.add(info5301SpecialConditionResult);
                }
            } catch (ParseException e) {
                e.printStackTrace(); // 处理日期解析异常
            }
        }
        List<ConditionDefinition> conditionDefinitions = null;
        if (!currentRangeResults.isEmpty()) {
            conditionDefinitions = iConditionDefinitionService.list(
                new LambdaUpdateWrapper<ConditionDefinition>().in(ConditionDefinition::getYbNo, currentRangeResults
                    .stream().map(Info5301SpecialConditionResult::getOpspDiseCode).collect(Collectors.toList())));
        }
        return R.ok(conditionDefinitions);
    }

    /**
     * 【3301】目录对照
     *
     * @param tableName 就诊id
     * @param id 付款id
     * @return 结果
     */
    @PostMapping("/directory-cross-check")
    public R<?> directoryCheck(String tableName, Long id) {
        MedicalDirectory3301Param medicalDirectory3301Param = ybDao.getMedicalDirectory3301Param(tableName, id);
        ArrayList<MedicalDirectory3301Param> list = new ArrayList<>();
        list.add(medicalDirectory3301Param);
        MedicalDirectory3301ListParam medicalDirectory3301ListParam = new MedicalDirectory3301ListParam();
        medicalDirectory3301ListParam.setData(list);
        Result resultInfo = ybHttpUtils.directoryCheck(medicalDirectory3301ListParam);
        if (resultInfo.getCode().equals(CommonConstant.SC_OK_200)) {
            ybDao.saveDirectoryHistory(tableName, id, 3301, medicalDirectory3301Param);
        }
        return R.ok();
    }

    /**
     * 【3302】目录对照撤销
     *
     * @param tableName 就诊id
     * @param id 付款id
     * @return 结果
     */
    @PostMapping("/directory-un-check")
    public R<?> directoryUnCheck(String tableName, Long id) {

        MedicalDirectory3302Param medicalDirectory3302Param = ybDao.getMedicalDirectory3302Param(tableName, id);
        Result resultInfo = ybHttpUtils.directoryUnCheck(medicalDirectory3302Param);
        if (resultInfo.getCode().equals(CommonConstant.SC_OK_200)) {
            ybDao.saveDirectoryHistory(tableName, id, 3302, medicalDirectory3302Param);
        }

        return R.ok();
    }

    /**
     * 【3201】对总账
     *
     * @param settlement3201WebParam 3201入参条件
     * @return 结果
     */
    @PostMapping("/reconcile")
    public R<?> reconcileGeneralLedger(@RequestBody Settlement3201WebParam settlement3201WebParam) {
        Financial3201Param financial3201Param = ybDao.getFinancial3201Param(settlement3201WebParam);
        Result result = ybHttpUtils.reconcileGeneralLedger(financial3201Param);
        if (result.getCode().equals(CommonConstant.SC_OK_200)) {
            // System.out.println(JSON.parseObject(JSON.toJSONString(result.getResult())));
            Financial3201Output financial3201Output =
                JSON.parseObject(JSON.toJSONString(result.getResult()), Financial3201Output.class);
            ybDao.saveReconcileGeneralLedger(financial3201Output, financial3201Param);
            if ("0".equals(financial3201Output.getStmtRslt())) {
                return R.ok("OK");
            }
            return R.ok(financial3201Output.getStmtRsltDscr());
        }
        return R.fail("医保app通讯失败");
    }

    /**
     * 【3201】对总账列表
     *
     * @param settlement3201WebParam 3201入参条件
     * @return 结果
     */
    @GetMapping("/reconcile-list")
    public R<?> reconcileGeneralLedgerList(Settlement3201WebParam settlement3201WebParam) {
        return R.ok(ybDao.reconcileGeneralLedgerDetail(settlement3201WebParam));
    }

    /**
     * 【3201】手动对账(吉林省)
     *
     * @param financialHand3203WebParam 3201 入参条件
     * @return 结果
     */
    @PostMapping("/hand-operated-apply-reconcile-accounts")
    public R<?> handOperatedApplyReconcileAccounts(@RequestBody FinancialHand3201WebParam financialHand3203WebParam) {

        Financial3201Param financial3201Param = new Financial3201Param();

        financial3201Param.setInsutype(financialHand3203WebParam.getInsutype())
            .setClrType(financialHand3203WebParam.getClrType()).setSetlOptins(financialHand3203WebParam.getClrOptins())
            .setStmtBegndate(financialHand3203WebParam.getBegndate())
            .setStmtEnddate(financialHand3203WebParam.getEnddate())
            .setMedfeeSumamt(financialHand3203WebParam.getMedfeeSumamt().doubleValue())
            .setFundPaySumamt(financialHand3203WebParam.getFundAppySum().doubleValue())
            .setAcctPay(financialHand3203WebParam.getAcctPay().doubleValue())
            .setFixmedinsSetlCnt(Integer.parseInt(financialHand3203WebParam.getSetlCnt()))
            .setInsuplcAdmdvs(SecurityUtils.getLoginUser().getOptionJson().getString("admvs"));

        Result result = ybHttpUtils.reconcileGeneralLedger(financial3201Param);
        if (result.getCode().equals(CommonConstant.SC_OK_200)) {
            // System.out.println(JSON.parseObject(JSON.toJSONString(result.getResult())));
            Financial3201Output financial3201Output =
                JSON.parseObject(JSON.toJSONString(result.getResult()), Financial3201Output.class);
            ybDao.saveReconcileGeneralLedger(financial3201Output, financial3201Param);
            if ("0".equals(financial3201Output.getStmtRslt())) {
                return R.ok("OK");
            }
            return R.ok(financial3201Output.getStmtRsltDscr());
        }
        return R.fail("医保app通讯失败");
    }

    /**
     * 【3202】对明细账
     *
     * @param settlement3202WebParam 3202查询数据
     * @return 结果
     */
    @PostMapping("/reconcile-detail-list")
    public R<?> reconcileGeneralLedgerDetail(@RequestBody Settlement3202WebParam settlement3202WebParam) {
        List<Financial3202FileParam> financial3202FileParams = ybDao.paymentCompareYbSettle(settlement3202WebParam);

        // FinancialSettlement3202Param financial3202Param =
        // ybDao.getFinancialSettlement3202Param(settlement3202WebParam);
        // FinancialSettlement3202Result resultInfo = ybHttpUtils.reconcileGeneralLedgerDetail(financial3202Param);

        return R.ok(financial3202FileParams);
    }

    /**
     * 【3202】生成txt文件
     *
     * @param financial3202WebParam 3202查询数据
     * @return 结果
     */
    @PostMapping("/reconcile-detail-txt")
    public void reconcileGeneralLedgerDetailTxt(@RequestBody Financial3202WebParam financial3202WebParam,
        HttpServletResponse response) throws IOException {
        List<Financial3202FileParam> financial3202FileParams =
            ybDao.paymentCompareYbSettle(financial3202WebParam.getSettlementIdList());
        // String filePath = SecurityUtils.getLoginUser().getOptionJson().getString("filePath")+new
        // Date().getTime()+".txt";
        // String filePath = "C:\\Users\\bjbUser\\Desktop\\"+new Date().getTime()+".txt";
        // try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
        // for (Financial3202FileParam item : financial3202FileParams) {
        // // 假设每个实体都有toString()方法返回逗号分隔的属性
        // // 或者你可以自定义获取属性的方式
        // System.out.println(item.toString());
        // String line = item.getTxt();
        // writer.write(line);
        // writer.newLine();
        // }
        // }
        // return R.ok("生成txt文件成功，文件路径："+filePath);

        // 2. 设置响应头（强制下载，指定文件名）
        String fileName = "financial_report_" + System.currentTimeMillis() + ".txt";
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition",
            "attachment; filename=\"" + URLEncoder.encode(fileName, "UTF-8").replace("+", "%20") + "\"");

        // 3. 直接通过输出流写入数据（避免创建临时文件）
        try (OutputStream os = response.getOutputStream();
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8))) {

            for (Financial3202FileParam item : financial3202FileParams) {
                writer.write(item.getTxt()); // 写入每行数据
                writer.newLine(); // 换行
            }
            writer.flush();
        }
        System.out.println(fileName);
        // return R.ok("生成txt文件成功，文件名称："+fileName);
    }

    /**
     *
     * @param file 文件流
     * @param filename 文件名
     * @return
     */
    @PostMapping(value = "/file-up")
    public R<?> uploadFile(@RequestPart("file") MultipartFile file, @RequestParam("filename") String filename) {
        // 1. 基础校验
        if (file.isEmpty()) {
            return R.fail("文件不能为空");
        }
        if (!file.getOriginalFilename().endsWith(".zip")) {
            return R.fail("仅支持ZIP格式文件");
        }

        // 2. 调用Service处理业务逻辑
        try {
            ResponseEntity<String> fileResult = ybHttpUtils.upload9101(file, filename);
            return R.ok(fileResult);
        } catch (Exception e) {
            return R.fail("处理失败: " + e.getMessage());
        }
    }

    /**
     * 触发3202接口
     * 
     * @param settlementIdList 3202查询数据
     * @return
     * @throws IOException
     */
    @PostMapping("/reconcile-general")
    public R<?> reconcileGeneral(List<String> settlementIdList, String filePath, String fileQuryNo, String setlOptins,
        String clrType) {
        // todo:这里需要考虑3302接口的参数是后台合计还是由前台传入，因为这个参数还要和txt文件对应（既需要txt中的数据还需要db表中的一些数据），
        // String filePath = SecurityUtils.getLoginUser().getOptionJson().getString("filePath")+new
        // Date().getTime()+".txt";
        List<Financial3202FileParam> financial3202FileParamList = new ArrayList<>();
        Resource resource = resourceLoader.getResource(filePath); // 或使用 "file:" 读取绝对路径

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (!line.trim().isEmpty()) {
                    String[] fields = line.split("\t"); // 按 Tab 分割字段
                    if (fields.length == 7) {
                        BigDecimal medfeeSumamt = new BigDecimal(fields[3]);
                        BigDecimal fundPaySumamt = new BigDecimal(fields[4]);
                        BigDecimal acctPay = new BigDecimal(fields[5]);
                        Financial3202FileParam person = new Financial3202FileParam(fields[0], fields[1], fields[2],
                            medfeeSumamt, fundPaySumamt, acctPay, fields[6]);
                        financial3202FileParamList.add(person);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new ServiceException("IO异常，异常信息：" + e.getMessage());
        }

        BigDecimal medfeeSumamt = BigDecimal.ZERO;// 医疗费总额
        BigDecimal fundPaySumamt = BigDecimal.ZERO;// 基金支付
        // Integer fixmedinsSetlCnt = 0;//结算笔数

        if (financial3202FileParamList.isEmpty()) {
            throw new ServiceException("未获取txt文件中实体");
        }
        for (Financial3202FileParam financial3202FileParam : financial3202FileParamList) {
            medfeeSumamt = medfeeSumamt.add(financial3202FileParam.getMedfeeSumamt());
            fundPaySumamt = fundPaySumamt.add(financial3202FileParam.getFundPaySumamt());
        }

        FinancialSettlement3202Param financialSettlement3202Param =
            ybDao.getFinancialSettlement3202Param(settlementIdList, medfeeSumamt, fundPaySumamt);
        if (financialSettlement3202Param == null) {
            throw new ServiceException("未生成3202参数");
        }
        financialSettlement3202Param.setClrType(clrType).setFileQuryNo(fileQuryNo)
            .setRefdSetlFlag(financial3202FileParamList.get(0).getRefdSetlFlag()).setSetlOptins(setlOptins);

        FinancialSettlement3202Result financialSettlement3202Result =
            ybHttpUtils.reconcileGeneralLedgerDetail(financialSettlement3202Param);
        if (financialSettlement3202Result == null) {
            throw new ServiceException("未收到3202参数");
        }

        return R.ok(financialSettlement3202Result);
    }

    /**
     * 【3209A】第三方数据查询
     *
     * @param settlement3209AWebParam 3209A入参条件
     * @return 结果
     */
    @PostMapping("/three-part-search-err")
    public R<?> threePartSearch(Settlement3209AWebParam settlement3209AWebParam) {

        FinancialSettlement3209AParam financialSettlement3209AParam =
            ybDao.getFinancialSettlement3209AParam(settlement3209AWebParam);
        List<FinancialSettlement3209AResult> list = ybHttpUtils.threePartSearch(financialSettlement3209AParam);

        return R.ok();
    }

    /**
     * 【3203A】清算申请(吉林省)
     *
     * @param financial3203AWebParam 3203A入参条件
     * @return 结果
     */
    @PostMapping("/apply-financial-clearing")
    public R<?> applyFinancialClearing(@RequestBody Financial3203AWebParam financial3203AWebParam) {
        Financial3203AParam financial3203AParam = ybDao.getFinancial3203AParam(financial3203AWebParam);
        String s = ybHttpUtils.applyFinancialClearing(financial3203AParam);
        if (!StringUtils.isEmpty(s)) {
            Result<?> result = JSON.parseObject(s, Result.class);
            if (result != null) {
                if (result.getCode() == 200) {
                    ybDao.save3203AFinancialClearingApplycation(financial3203AParam,
                        String.valueOf(result.getResult()));
                    return R.ok(result);
                }
            }
        }
        return R.fail(s);
    }

    /**
     * 【3203A】清算申请(吉林省)
     *
     * @param financialClearing3203AWebParam 3203A入参条件
     * @return 结果
     */
    @PostMapping("/auto-apply-financial-clearing")
    public R<?> autoApplyFinancialClearing(@RequestBody FinancialClearing3203AWebParam financialClearing3203AWebParam) {

        Settlement3202WebParam settlement3202WebParam = new Settlement3202WebParam();
        settlement3202WebParam.setStmtBegnDate(String.valueOf(financialClearing3203AWebParam.getStmtBegnDate()));
        settlement3202WebParam.setStmtEndDate(String.valueOf(financialClearing3203AWebParam.getStmtEndDate()));
        settlement3202WebParam.setClrType(financialClearing3203AWebParam.getClrType());
        settlement3202WebParam.setSetlOptins(financialClearing3203AWebParam.getSetlOptins());
        List<Financial3202FileParam> financial3202FileParams = ybDao.paymentCompareYbSettle(settlement3202WebParam);

        Financial3203AParam financial3203AParam = ybDao.getFinancial3203AParam(financial3202FileParams,
            String.valueOf(financialClearing3203AWebParam.getStmtBegnDate()),
            String.valueOf(financialClearing3203AWebParam.getStmtEndDate()),
            financialClearing3203AWebParam.getClrType(), financialClearing3203AWebParam.getSetlOptins());
        String s = ybHttpUtils.applyFinancialClearing(financial3203AParam);
        if (!StringUtils.isEmpty(s)) {
            Result<?> result = JSON.parseObject(s, Result.class);
            if (result != null) {
                if (result.getCode() == 200) {
                    ybDao.save3203AFinancialClearingApplycation(financial3203AParam,
                        String.valueOf(result.getResult()));
                    return R.ok(result);
                }
            }
        }
        return R.fail(s);
    }

    /**
     * 【3203A】手动清算申请(吉林省)
     *
     * @param financialHand3203AWebParam 3203A入参条件
     * @return 结果
     */
    @PostMapping("/hand-operated-apply-financial-clearing")
    public R<?> handOperatedApplyFinancialClearing(@RequestBody FinancialHand3203AWebParam financialHand3203AWebParam) {

        Financial3203AParam financial3203AParam = new Financial3203AParam();

        financial3203AParam.setClrType(financialHand3203AWebParam.getClrType());
        financial3203AParam.setMedfeeSumamt(financialHand3203AWebParam.getMedfeeSumamt());
        financial3203AParam.setMedSumfee(financialHand3203AWebParam.getMedSumfee());
        financial3203AParam.setAcctPay(financialHand3203AWebParam.getAcctPay());
        financial3203AParam.setCashPayamt(financialHand3203AWebParam.getCashPayamt());
        financial3203AParam.setFundAppySum(financialHand3203AWebParam.getFundAppySum());
        financial3203AParam.setClrOptins(financialHand3203AWebParam.getClrOptins());

        ybDao.getFinancial3203AParamForTime(financial3203AParam,
            String.valueOf(financialHand3203AWebParam.getBegndate()),
            String.valueOf(financialHand3203AWebParam.getEnddate()));
        String s = ybHttpUtils.applyFinancialClearing(financial3203AParam);
        if (!StringUtils.isEmpty(s)) {
            Result<?> result = JSON.parseObject(s, Result.class);
            if (result != null) {
                if (result.getCode() == 200) {
                    ybDao.save3203AFinancialClearingApplycation(financial3203AParam,
                        String.valueOf(result.getResult()));
                    return R.ok(result);
                }
            }
        }
        return R.fail(s);
    }

    /**
     * 清算申请记录(吉林省)
     *
     * @param
     * @return 结果
     */
    @GetMapping("/apply-financial-clearing-list")
    public R<?> getApplyFinancialClearingList(@RequestParam(value = "searchKey", defaultValue = "") String searchKey,
        @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
        @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest request) {
        return R.ok(ybDao.getFinancial3203APage(searchKey, pageNo, pageSize, request));
    }

    /**
     * 【3204A】清算申请撤销(吉林省)
     *
     * @param clrAppyEvtId 3203A入参条件
     * @return 结果
     */
    @GetMapping("/apply-un-clearing")
    public R<?> cancelFinancialClearing(String clrAppyEvtId, String clrOptins) {
        Financial3204Param financial3204Param = new Financial3204Param();
        FinancialApplyRecord financialApplyRecord = ybDao.getFinancial3204ParamByClrAppyEvtId(clrAppyEvtId);
        financial3204Param.setClrOptins(clrOptins).setClrAppyEvtId(financialApplyRecord.getOutResult());
        Result resultInfo = ybHttpUtils.cancelFinancialClearing(financial3204Param);
        if (resultInfo.getCode().equals(CommonConstant.SC_OK_200)) {
            ybDao.save3204AFinancialClearingApplycation(clrAppyEvtId, clrOptins);
            return R.ok("撤销成功");
        }
        return R.fail("撤销失败");
    }

    /**
     * 【3205A】清算申请状态查询
     *
     * @param clearing3205AWebParma 3205A入参条件
     * @return 结果
     */
    @PostMapping("/get-clearing-status")
    public R<?> getFinancialClearingStatus(Clearing3205AWebParma clearing3205AWebParma) {

        Clearing3205AParma clearing3205AParma = ybDao.getClearing3205AParma(clearing3205AWebParma);
        Clearing3205AResult clearing3205AResult = ybHttpUtils.getFinancialClearingStatus(clearing3205AParma);

        return R.ok(clearing3205AResult);
    }

    /**
     * 【3501】商品盘存上传
     *
     * @param id 供应申请id
     * @return 结果
     */
    @PostMapping("/upload-inventory-count")
    public R<?> uploadInventoryCount(Long id) {

        MedicalInventory3501Param medicalInventory3501Param =
            ybDao.getMedicalInventory3501Param(id, SecurityUtils.getLoginUser().getTenantId());
        Result resultInfo = ybHttpUtils.uploadInventoryCount(medicalInventory3501Param);
        if (resultInfo.getCode().equals(CommonConstant.SC_OK_200)) {
            ybDao.saveInventoryCheckRecord(medicalInventory3501Param, resultInfo.getMessage());
            return R.ok();
        }
        ybDao.saveInventoryCheckRecord(medicalInventory3501Param, resultInfo.getMessage());
        return R.fail();
    }

    /**
     * 【3502】商品信息变更
     *
     * @param id 供应申请id
     * @param invChgType 变更类型 参考枚举
     * @return 结果
     */
    @PostMapping("/upload-inventory")
    public R<?> updateInventoryCount(Long id, String invChgType) {

        MedicalInventory3502Param medicalInventory3502Param =
            ybDao.getMedicalInventory3502Param(id, invChgType, SecurityUtils.getLoginUser().getTenantId());
        Result resultInfo = ybHttpUtils.updateInventoryCount(medicalInventory3502Param);
        if (resultInfo.getCode().equals(CommonConstant.SC_OK_200)) {
            ybDao.saveInventoryChangeRecord(medicalInventory3502Param, resultInfo.getMessage());
            return R.ok();
        }
        return R.fail();
    }

    /**
     * 【3503】商品采购
     *
     * @param id 供应申请id
     * @return 结果
     */
    @PostMapping("/procurement")
    public R<?> procurement(Long id) {

        Medical3503Param medical3503Param = ybDao.getMedical3503Param(id, SecurityUtils.getLoginUser().getTenantId());
        Result resultInfo = ybHttpUtils.procurement(medical3503Param);
        if (resultInfo.getCode().equals(CommonConstant.SC_OK_200)) {
            ybDao.saveInventoryPurchaseRecord(medical3503Param, resultInfo.getMessage());
            return R.ok();
        }
        return R.fail();
    }

    /**
     * 【3504】商品采购退货
     *
     * @param id 供应申请id
     * @return 结果
     */
    @PostMapping("/procurement-cancel")
    public R<?> cancelProcurement(Long id) {

        MedicalPurchase3504Param medicalPurchase3504Param =
            ybDao.getMedicalPurchase3504Param(id, SecurityUtils.getLoginUser().getTenantId());
        Result resultInfo = ybHttpUtils.cancelProcurement(medicalPurchase3504Param);
        if (resultInfo.getCode().equals(CommonConstant.SC_OK_200)) {
            ybDao.saveInventoryPurchaseReturnRecord(medicalPurchase3504Param, resultInfo.getMessage());
            return R.ok();
        }
        return R.fail();
    }

    /**
     * 【3505】商品销售
     *
     * @param id 供应申请id
     * @return 结果
     */
    @PostMapping("/merchandise")
    public R<?> merchandise(Long id, String ListType) {
        Medical3505Param medical3505Param =
            ybDao.getMedical3505Param(id, ListType, SecurityUtils.getLoginUser().getTenantId());
        Result result = ybHttpUtils.merchandise(medical3505Param);
        Medical3505Result medical3505Result =
            JSON.parseObject(JSON.toJSONString(result.getMessage()), Medical3505Result.class);
        if ("1".equals(medical3505Result.getRetRslt())) {
            ybDao.saveInventorySaleRecord(medical3505Param, medical3505Result.getMsgRslt());
            return R.ok();
        }
        ybDao.saveInventorySaleRecord(medical3505Param, medical3505Result.getMsgRslt());
        return R.fail();
    }

    /**
     * 【3506】商品销售退货
     *
     * @param id 供应申请id
     * @return 结果
     */
    @PostMapping("/cancel-merchandise")
    public R<?> cancelMerchandise(Long id, String ListType) {
        Medical3506Param medical3506Param =
            ybDao.getMedical3506Param(id, ListType, SecurityUtils.getLoginUser().getTenantId());
        Result result = ybHttpUtils.cancelMerchandise(medical3506Param);
        Medical3505Result medical3505Result =
            JSON.parseObject(JSON.toJSONString(result.getMessage()), Medical3505Result.class);
        if ("1".equals(medical3505Result.getRetRslt())) {
            ybDao.saveInventorySaleReturnRecord(medical3506Param, medical3505Result.getMsgRslt());
            return R.ok();
        }
        ybDao.saveInventorySaleReturnRecord(medical3506Param, medical3505Result.getMsgRslt());
        return R.fail();
    }

    /**
     * 【3507】商品信息删除
     *
     * @param id 供应申请id
     * @return 结果
     */
    @PostMapping("/del-goods")
    public R<?> deleteGoodsInfo(Long id, String ListType) {
        Medical3507Param medical3507Param = ybDao.getMedical3507Param(id, ListType);
        Result resultBody = ybHttpUtils.deleteGoodsInfo(medical3507Param);
        if (resultBody.getCode().equals(CommonConstant.SC_OK_200)) {
            ybDao.saveInventoryDelRecord(medical3507Param);
            return R.ok();
        }
        return R.fail();
    }

    /**
     * 【3206A】清算机构查询
     *
     * @return 结果
     */
    @GetMapping("/select-clroptins")
    public R<?> getClrOptins(String pageNum, String pageSize, String fixmedinsCode) {
        Clearing3206AParam clearing3206AParam = new Clearing3206AParam();
        clearing3206AParam.setPageNum(Integer.parseInt(pageNum)).setPageSize(Integer.parseInt(pageSize))
            .setFixmedinsCode(fixmedinsCode);
        Result resultBody = ybHttpUtils.getClrOptins(clearing3206AParam);
        if (resultBody.getCode().equals(CommonConstant.SC_OK_200)) {
            // ybDao.saveInventoryDelRecord(medical3507Param);
            // resultBody.
            return R.ok();
        }
        return R.fail(resultBody);
    }

    /**
     * 【1312】-医保目录信息查询
     *
     * @param hilistCode 医保目录编码
     * @param dateStr 更新时间
     * @return 结果
     */
    @PostMapping("/query-yb-catalogue")
    public R<?> queryYbCatalogue(@RequestParam String hilistCode, @RequestParam String dateStr) {
        Catalogue1312QueryParam catalogue1312QueryParam = new Catalogue1312QueryParam();
        catalogue1312QueryParam.setHilistCode(hilistCode);
        catalogue1312QueryParam.setInsuplcAdmdvs(
            SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.INSUPLC_ADMDVS));
        // 直接解析（默认 ISO 格式）
        LocalDate localDate = LocalDate.parse(dateStr);
        // 转换为 Date
        Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
        catalogue1312QueryParam.setUpdtTime(date);
        catalogue1312QueryParam.setPageNum(1);
        catalogue1312QueryParam.setPageSize(10);
        catalogue1312QueryParam.setDecryptFlag("0"); // 不需要解密
        List<Catalogue1312Output> outputList = ybHttpUtils.queryYbCatalogue(catalogue1312QueryParam);
        return R.ok(outputList);
    }

    /**
     * 【1312】-医保目录信息批量查询
     *
     * @param dateStr 更新时间
     * @return 结果
     */
    @PostMapping("/batch-query-yb-catalogue")
    public R<?> batchQueryYbCatalogue(@RequestParam String dateStr) {
        // 准备公共参数
        String insuplcAdmdvs = "229900";
        LocalDate localDate = LocalDate.parse(dateStr);
        Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());

        // 存储所有查询结果
        List<Catalogue1312Output> allResults = new ArrayList<>();
        String str =
            "XC09CAT039A001010300800, XR05XXA175E001010100760, XR03DAA113B002020103257, XC01DAX072A001010500202, XM01ABS120E007010178232, XA10BKD256A001010179096, XA11DAW036A001010103059, XA03FAX226B002010103973, XC08CAA187A001010101678, XM01AEB173X002010100734, ZA12BAF0349010200941, ZA06CBF0034010403496, XC10AXY310B002010178217, XC10ABF021E001010180487, XJ01MAN076A001010204747, XN02BAL023B001060104288, XN02BBQ128A001010103304, XC07AGA031A001010378991, ZA04AAN0111010100169, ZB01BAS0537030100490, XR07AXY034B001010103783, XJ01FAA051E001010201651, XB05XAL211B002050402180, XR06AXL226A001010100784, XJ01XDA231B002020302180, XG03FBC051A001020178890, XR06ADY136B002010101962, XB02BXF031B002010103216, XC08CAZ067A001010702697, XC07ABM062A010020183802, XJ05APL052N001030102120, XM04AAF670A001010401729, ZA04BAK0055010302943, XS01KAB146G010010109920, XC10AAR069A001040104641, ZA12BAS0986010100961, XR05CBA101E005030500066, XJ01MAZ074A001011303307, XB05XAL208B002020203204, XB01AXA223B002010105791, XC01CAJ097B002020100137, XJ01DDT088B001010102918, ZG01BAX0326010105184, XA05BAF632B002010179084, XJ01FAL262A006010801478, XJ01FFK071B002040101017, ZA12BAF0349010100941, ZD02AAF0202010105046, XG03DAH056B002010100874, XB03AED181E001010304032, XA03BAX232B002010104494, XA03FAJ085B002020103257, XB03BAW037B002020203216, ZA06CAF0030020105478, XA10ADM080B002010107103, XA10AEG025B002020181708, ZG01AAS0084010103814, XA11HAW041B002010103257, XC08CAZ067A001010203447, XN01BBA064B002010178765, ZA06CAF0030020205478, XC09DXS255A001030378679, XC02CXY168B002010200239, ZA02BAQ0408010103151, XD10AFH016F001010103223, ZA13BAD0263010103391, ZA12DAQ0082010102767, XC10ABB079A001010101499, ZA02AAH0434010100941, XC01CAS071B002010401984, XA02BCA211E005010104192, ZA04BAP0062010101193, XJ01CAA040E001030402699, XM01ABA196A012010103198, XA10BFA025A001020100002, XA06AGK111S003010101954, ZA12BAG0375010102537, ZA10DAA0094010103357, XJ01DCT162A001010204658, XA11DAW036B002010103257, XR05XXF134A001010103453, XA02ADL183A005010300340, XC01CAS071B002010203204, XB05XAT018B002010202954, XJ01MAM134B002010105759, XB05BBP072B002170102180, XG03DBD084A001010178890, XC09DXS255A001030178679, XC02CXY168A001020179598, XJ01MAM134B002010102763, XC01CAQ120B002010201984, XA07FAD090E001010201161, XA10ABM079B002020107103, XA07AXX082A017010101162, ZG01BAY0711010501752, ZF03AAL0102010100169, XA10BAE021A001010104658, XM01AEB173E003010303370, XB05BBP072B002090102180, XJ01XDR005E001010103464, XR06AXL226A001010200841, XN07XXB025E001010304021, XB03AAF375A017010103454, XA11GAW043A001010100222, XR05CBA198A001010209703, ZA04BAK0055010102748, ZA02AAH0434010300941, XA12AXT201A001010101421, XC09CAE003A001010404647, XA05BAS149E001010200941, XA11GAW043B002020103216, ZA17AAZ0155010102018, ZG01BAY0716040405629, XS01AEZ074G010020109920, XC10AAA067A001020105847, ZG03AAS0381020101385, XS01KAB146G010020209920, XR07ABN040B002010100137, XC09CAT039A001010105805, XA07FAR055A001010203744, XA05BAF632A001010200106, ZA04BAX0048020105337, XJ06BBP063B002010102055, XA10BJS279B002020183568, XB03BBY050A001010300011, XJ06BBP063B001010109588, XJ05APL052B002020104127, XR05CBA198B002010201871, ZG02BAZ0126010102021, XJ01FAA051B001020302770, ZA09FAJ0473010105300, XR05FBF273A001010103304, XA03BAA068B002010103257, ZA12AAQ0060030100941, XC01AAQ133B002010301708, XM09AXF299B001010102557, XN02BED158A001010201162, XA03ADY181B002010201708, XB05BBP072B002040203063, ZZ01AAJ0464010105109, XG03DAH056E001010104735, XA10BDE082A001010304520, XA10ADD335B002020307103, XR05CBA198A001010109703, XB05BBP072B002170502180, XA02BCA211B001020104127, XB05XAL211B002070602180, XJ05ABA075A001010100503, XN07XXD130E002010102774, XS02AAZ074Q010010100547, XJ01MAM122A001010206988, XR03ACS048L028010101740, XC01BBL054B002020203204, XD06BBA075F002020104982, XA10AEG025B002040181708, ZA04BAY0496010102019, XA05BAH112B014020104139, XR03BAB165L023020100545, XH02ABD234B002020203257, XA06ADR050X001010101150, ZA14AAJ0168020105394, XH03AAZ057A001030279462, XB01ACA056A012020279489, XN05BAD088B002010100978, XC01DAX072B002020102902, XJ05AHA218E001010102770, XR06ADY136B002010201962, XS01AAH016G004020104127, XB05BBM115B001010204098, XR05FBF273A001010200228, XA03BAX232B002020103216, ZA04BAL0021020101749, XJ01DDT081B001010200513, XD07CBF231F002010100474, XC09AAY074A001020101747, XJ01MAM122A001010101003, XA05BAH112B001040101066, XN02BBF168B002010103257, ZA09CAL0264030100169, XD01ACM085F002020102529, XA12AAP077B002020402662, ZA09HAC0221010279263, XA07BCM081P001010203714, XG03FBC051A001010178890, ZA02AAH0441010502125, ZG01BAY0713010301752, ZA04BAF0468010103658, ZA09ABR0036010100166, XN07CAF072E001010102529, XP01ABJ070A001010101984, XB05XAL211B002020402180, XC03CAF056B002010203257, XR03ACT022L008010201429, XB03BAJ038A001010205337, XC08CAX211A010010100681, XA10ADJ247B002010107103, ZA05BAW0113010103287, XJ01DDT073E001010602703, XH02ABJ061B001010200933, XA11HAW041B002010203216, ZA02BAF0104010104670, XJ01MAZ083B002040202662, XB01ACL190A001020178814, XR07ABN040B002010304152, XC10AAA067A001010105847, XB05BBP072B002091102180, ZF03AAK0002030105506, XR07ABL271B002020100137, ZB01CAM0031040101954";
        String[] split = str.split(",");
        // 循环查询每个医保目录编码
        for (String s : split) {
            Catalogue1312QueryParam catalogue1312QueryParam = new Catalogue1312QueryParam();
            catalogue1312QueryParam.setHilistCode(s);
            catalogue1312QueryParam.setInsuplcAdmdvs(insuplcAdmdvs);
            catalogue1312QueryParam.setUpdtTime(date);
            catalogue1312QueryParam.setPageNum(1);
            catalogue1312QueryParam.setPageSize(10);
            catalogue1312QueryParam.setDecryptFlag("0"); // 不需要解密

            // 执行查询并收集结果
            List<Catalogue1312Output> outputList = ybHttpUtils.queryYbCatalogue(catalogue1312QueryParam);
            if (outputList != null && !outputList.isEmpty()) {
                List<Catalogue1312Output> list = outputList.stream().filter(Objects::nonNull)
                    .filter(x -> x.getMemo() != null).filter(x -> !"null".equals(x.getMemo()))
                    .filter(x -> !"历史数据迁移".equals(x.getMemo())).filter(x -> !"目录变更".equals(x.getMemo()))
                    .filter(x -> !"0".equals(x.getMemo())).filter(x -> !" ".equals(x.getMemo()))
                    .collect(Collectors.toMap(Catalogue1312Output::getHilistCode, // 以 hilistCode 作为 key
                        Function.identity(), // 保留原对象
                        (existing, replacement) -> existing // 如果重复，保留第一个
                    )).values().stream().toList();
                allResults.addAll(list);
            }
        }
        return R.ok(allResults);
    }

    /**
     * 【3101】明细审核事前事中分析服务
     *
     * @param encounterId 就诊ID
     * @return 结果
     */
    @GetMapping("/pre-mid-analysis")
    public R<?> yb3101PreMidAnalysis(@RequestParam("encounterId") Long encounterId,
        @RequestParam("trigScen") String trigScen) {
        return ybService.yb3101PreMidAnalysis(encounterId, trigScen);
    }

    /**
     * 【3103】事前事中服务反馈服务
     *
     * @param warnRsltId 违规标识
     * @param dspoWay 处理方式
     * @param dspoWayRea 处理原因
     * @return 结果
     */
    @GetMapping("/pre-mid-feedback")
    public R<?> yb3103PreMidFeedback(@RequestParam("warnRsltId") String warnRsltId,
        @RequestParam("dspoWay") String dspoWay,
        @RequestParam(value = "dspoWayRea", required = false) String dspoWayRea) {
        return ybService.yb3103PreMidFeedback(warnRsltId, dspoWay, dspoWayRea);
    }

    /**
     * 【4101A】医疗保障基金结算清单信息上传（新）
     *
     * @param paymentId 付款ID
     * @return 结果
     */
    @GetMapping("/upload-fund-settle")
    public R<?> yb4101aUploadFundSettle(@RequestParam("paymentId") Long paymentId) {
        return ybService.yb4101aUploadFundSettle(paymentId);
    }

    /**
     * 【5205】人员慢特病用药记录查询
     *
     * @param yb5205SpecialDiseaseWebParam 付款ID
     * @return 结果
     */
    @PostMapping("/special-disease-drug-record-search")
    public R<?>
        yb5205SpecialDiseaseDrugRecordSearch(@RequestBody Yb5205SpecialDiseaseWebParam yb5205SpecialDiseaseWebParam) {
        Yb5205InputSpecialDisease yb5205InputSpecialDisease =
            ybDao.yb5205SpecialDiseaseDrugRecordSearch(yb5205SpecialDiseaseWebParam.getPatientId(),
                yb5205SpecialDiseaseWebParam.getBegntime(), yb5205SpecialDiseaseWebParam.getEndtime());

        List<Yb5205OutputSpecialDisease> yb5205OutputSpecialDiseases =
            ybHttpUtils.yb5205SpecialDiseaseDrugRecordSearch(yb5205InputSpecialDisease);

        if (yb5205OutputSpecialDiseases == null) {
            return R.fail("获取失败");
        }

        return R.ok(yb5205OutputSpecialDiseases);
    }

    /**
     * 【2208】医保门诊退费
     *
     * @param psnNo 医保人员编号
     * @param mdtrtId 医保就诊id
     * @param settleId 医保结算id
     * @param insuplcAdmdvs 参保地
     * @param contractNo 合同编号
     * @return 结果
     */
    @GetMapping("/yb-return-settle")
    @Anonymous
    public R<?> ybReturnSettle(@RequestParam("psnNo") String psnNo, @RequestParam("mdtrtId") String mdtrtId,
        @RequestParam("settleId") String settleId, @RequestParam("insuplcAdmdvs") String insuplcAdmdvs,
        @RequestParam("contractNo") String contractNo){

        Clinic2208UnSetlInfoParam clinicSetl = new Clinic2208UnSetlInfoParam();
        clinicSetl.setPsnNo(psnNo).setMdtrtId(mdtrtId).setSetlId(settleId)
                .setInsuplcAdmdvs(insuplcAdmdvs);

        Clinic2208UnSetlInfoOutput clinic2208UnSetlInfoOutput = ybHttpUtils.unSettle(clinicSetl, iContractService.getContract(contractNo));

        return R.ok(clinic2208UnSetlInfoOutput);
    }

    /**
     * 【目录下载】
     *
     * @param address 接口
     * @return 结果
     */
    @GetMapping("/query-catalog")
    public R<?> queryCatalog(@RequestParam("address") String address, @RequestParam("v") String version) {

        CatalogFileInput catalogFileInput = new CatalogFileInput();
        catalogFileInput.setAddress(address);
        catalogFileInput.setVer(version);

        FileResult fileResult = ybHttpUtils.queryCatalog(catalogFileInput);

        fileResult = ybHttpUtils.downLoadFile(fileResult);

        if (fileResult == null) {
            return R.fail("获取失败");
        }

        return R.ok(fileResult);
    }

    /**
     * 【2401】入院办理
     * @return
     */
    @PostMapping("/inpatient-reg")
    public R<?> inpatientReg(Yb2401InpatientRegParamDto yb2401InpatientRegParamDto){

        Yb2401InputInpatientMdtrtInfo yb2401InputInpatientMdtrtInfo = ybDao.getYb2401InputInpatientMdtrtInfo(yb2401InpatientRegParamDto.getEncounterId());

        yb2401InputInpatientMdtrtInfo.setMdtrtCertType(yb2401InpatientRegParamDto.getYbMdtrtCertType());
        yb2401InputInpatientMdtrtInfo.setMdtrtCertNo(yb2401InpatientRegParamDto.getBusiCardInfo());

        InpatientReg inpatientReg = ybHttpUtils.inpatientReg(yb2401InputInpatientMdtrtInfo);

        if(inpatientReg!=null){

            inpatientReg.setInputParam(JSON.toJSONString(yb2401InputInpatientMdtrtInfo));
            ybDao.save2401InpatientReg(inpatientReg);
            return R.ok("医保入院办理成功！");

        }
        return R.fail("医保入院办理失败！");
    }

    /**
     * 【2402】入院办理
     * @return
     */
    @PostMapping("/inpatient-dis-charge")
    public R<?> inpatientCheckOut(Long encounterId){

        Contract contract = new Contract();
        Yb2402InputParam yb2402InputInpatientDscgInfo = ybDao.getYb2402InputInpatientDscgInfo(encounterId,contract);

        InpatientDischarge inpatientReg = ybHttpUtils.inpatientCheckOut(contract,yb2402InputInpatientDscgInfo);

        if(inpatientReg!=null){

            inpatientReg.setInputParam(JSON.toJSONString(yb2402InputInpatientDscgInfo));
            ybDao.save2402InpatientDscg(inpatientReg);
            return R.ok("医保出院办理成功！");

        }
        return R.fail("医保出院办理失败！");
    }

    /**
     * 【2403】入院办理
     * @return
     */
    @PostMapping("/update-inpatient-info")
    public R<?> updateInpatientInfo(Long encounterId){

        Yb2403InputParam yb2403InputParam = ybDao.getYb2403InputParam(encounterId);

        ybHttpUtils.updateInpatientInfo(yb2403InputParam);

        ybDao.save2403InputInpatient(yb2403InputParam);

        return R.fail("医保出院办理失败！");
    }
}
