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

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import com.core.common.core.domain.R;
import com.core.common.enums.TenantOptionDict;
import com.core.web.util.TenantOptionUtil;
import com.openhis.financial.domain.PaymentReconciliation;
import com.openhis.web.chargemanage.dto.OutpatientRegistrationAddParam;
import com.openhis.web.chargemanage.dto.OutpatientRegistrationSettleParam;
import com.openhis.web.paymentmanage.appservice.IChargeBillService;
import com.openhis.web.paymentmanage.appservice.IEleInvoiceService;
import com.openhis.web.paymentmanage.appservice.IPaymentRecService;
import com.openhis.web.paymentmanage.dto.CancelPaymentDto;
import com.openhis.web.paymentmanage.dto.CancelPaymentInpatientDto;
import com.openhis.web.paymentmanage.dto.NenuBpcPayDto;
import com.openhis.yb.dto.PaymentDto;
import com.openhis.yb.dto.PaymentInpatientDto;
import com.openhis.yb.dto.PrePaymentDto;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 付款管理
 *
 * @author SunJQ
 * @date 2025-03-29
 */
@RestController
@RequestMapping("/payment/payment")
@Slf4j
@AllArgsConstructor
public class PaymentReconciliationController {

    @Autowired
    private IPaymentRecService paymentReconciliationService;

    @Autowired
    private IEleInvoiceService eleInvoiceService;

    @Autowired
    private IChargeBillService iChargeBillService;

    /**
     * 预付款
     *
     * @param prePaymentDto 付款实体
     */
    @PostMapping("/precharge")
    public R<?> savePrePayment(@Validated @RequestBody PrePaymentDto prePaymentDto) {
        return paymentReconciliationService.prePayment(prePaymentDto);
    }

    /**
     * 取消预付款（该接口未被调用）
     *
     * @param encounterId 就诊id
     * @return 操作结果
     */
    @PostMapping("/unprecharge")
    public R<?> unPrePayment(Long encounterId) {
        return paymentReconciliationService.unPrePayment(encounterId);
    }

    /**
     * 付款
     *
     * @param paymentDto 付款实体
     */
    @PostMapping("/charge")
    public R<?> savePayment(@Validated @RequestBody PaymentDto paymentDto) {
        R<?> result = paymentReconciliationService.savePayment(paymentDto);
        // 付款成功后，开具发票
        if (result.getCode() == 200) {
            PaymentReconciliation paymentRecon = null;
            if (PaymentReconciliation.class.isAssignableFrom(result.getData().getClass())) {
                paymentRecon = (PaymentReconciliation)result.getData();
            }
            Map detail = iChargeBillService.getDetail(paymentRecon.getId());
            if ("0".equals(TenantOptionUtil.getOptionContent(TenantOptionDict.INVOICE_SWITCH))) {
                return R.ok(detail);
            } else {
                R<?> eleResult = eleInvoiceService.invoiceMZMake(paymentRecon.getId(), paymentDto.getEncounterId());
                if (eleResult.getCode() != 200) {
                    // 因收费成功前端需要关闭弹窗，此处信息仅用于提示所以返回ok
                    return R.ok(detail, " 收费成功，电子发票开具失败 :" + eleResult.getMsg());
                }
            }

            // Map detail = iChargeBillService.getDetail(paymentRecon.getId());
        }
        return result;
    }

    /**
     * 取消付款
     *
     * @param cancelPaymentDto 付款实体
     */
    @PostMapping("/uncharge")
    public R<?> cancelPayment(@RequestBody CancelPaymentDto cancelPaymentDto) {
        R<?> result = paymentReconciliationService.cancelPayment(cancelPaymentDto);
        // 取消付款成功后，开具发票
        if (result.getCode() == 200) {
            PaymentReconciliation paymentRecon = null;
            if (PaymentReconciliation.class.isAssignableFrom(result.getData().getClass())) {
                paymentRecon = (PaymentReconciliation)result.getData();
            }
            if ("0".equals(TenantOptionUtil.getOptionContent(TenantOptionDict.INVOICE_SWITCH))) {
                return result;
            } else {
                R<?> eleResult =
                    eleInvoiceService.invoiceWriteoff(paymentRecon.getRelationId(), cancelPaymentDto.getReason());
                if (eleResult.getCode() != 200) {
                    // 因取消付款成功前端需要关闭弹窗，此处信息仅用于提示所以返回ok
                    return R.ok(null, " 取消付款成功，电子发票开具失败 :" + eleResult.getMsg());
                }
            }

        }
        return result;
    }

    /**
     * 支付列表
     *
     * @param searchKey 模糊查寻
     * @param pageNo 页号
     * @param pageSize 页容量
     * @param request 请求体
     * @return 查询结果
     */
    @GetMapping("/page")
    public R<?> paymentPage(@RequestParam(value = "searchKey", defaultValue = "") String searchKey,
        @RequestParam(value = "kinsEnum", defaultValue = "") Integer kinsEnum,
        @RequestParam(value = "invoiceNo", defaultValue = "") String invoiceNo,
        @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
        @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest request) {
        return R.ok(paymentReconciliationService.getPage(searchKey, kinsEnum, invoiceNo, pageNo, pageSize, request));
    }

    /**
     * 支付详情
     *
     * @param paymentDto 付款信息
     * @return 查询结果
     */
    @PostMapping("/detail")
    public R<?> paymentDetail(@RequestBody PaymentDto paymentDto) {
        return R.ok(paymentReconciliationService.getDetail(paymentDto));
    }

    /**
     * 挂号收费（挂号收费先医保挂号，收费成功后再本系统挂号）
     *
     * @param outpatientRegistrationAddParam 挂号信息
     * @return 操做结果
     */
    @PostMapping("/reg-pre-pay")
    public R<?> regPrePay(@Valid @RequestBody OutpatientRegistrationAddParam outpatientRegistrationAddParam) {
        return paymentReconciliationService.regPrePay(outpatientRegistrationAddParam);
    }

    /**
     * 挂号收费（挂号收费先医保挂号，收费成功后再本系统挂号）
     *
     * @param outpatientRegistrationSettleParam 挂号信息
     * @return 操做结果
     */
    @PostMapping("/reg-pay")
    public R<?> regPay(@Valid @RequestBody OutpatientRegistrationSettleParam outpatientRegistrationAddParam) {
        R<?> result = paymentReconciliationService.regPay(outpatientRegistrationAddParam,
            outpatientRegistrationAddParam.getChrgBchno(), outpatientRegistrationAddParam.getPaymentDetails());
        // 付款成功后，开具发票
        if (result.getCode() == 200) {
            PaymentReconciliation paymentRecon = null;
            if (PaymentReconciliation.class.isAssignableFrom(result.getData().getClass())) {
                paymentRecon = (PaymentReconciliation)result.getData();
            }
            Map detail = iChargeBillService.getDetail(paymentRecon.getId());
            Long encounterId = paymentRecon.getEncounterId();
            if ("0".equals(TenantOptionUtil.getOptionContent(TenantOptionDict.INVOICE_SWITCH))) {
                return R.ok(detail);
            } else {
                R<?> eleResult = eleInvoiceService.invoiceRegMake(paymentRecon.getId(), encounterId);
                if (eleResult.getCode() != 200) {
                    // 因收费成功前端需要关闭弹窗，此处信息仅用于提示所以返回ok
                    return R.ok(detail, " 收费成功，电子发票开具失败 :" + eleResult.getMsg());
                }
            }
        }
        return result;
    }

    /**
     * 【住院预结算】
     *
     * @param prePaymentDto 预结算参数
     * @return 操作结果
     */
    @PostMapping("/inpa-pre-pay")

    public R<?> inpatientPrePay(@RequestBody PrePaymentDto prePaymentDto) {
        return R.ok(paymentReconciliationService.inpatientPreSettle(prePaymentDto));
    }

    /**
     * 【住院结算】
     *
     * @param paymentDto 预结算参数
     * @return 操作结果
     */
    @PostMapping("/inpa-pay")
    public R<?> inpatientPay(@RequestBody PaymentInpatientDto paymentDto) {
        R<?> r = paymentReconciliationService.inpatientSettle(paymentDto);
        // 付款成功后，开具发票
        if (r.getCode() == 200) {
            PaymentReconciliation paymentRecon = null;
            if (PaymentReconciliation.class.isAssignableFrom(r.getData().getClass())) {
                paymentRecon = (PaymentReconciliation)r.getData();
            }
            Long encounterId = paymentRecon.getEncounterId();
            R<?> eleResult = eleInvoiceService.invoiceZYMake(paymentRecon.getId(), encounterId);
            Map detail = iChargeBillService.getDetail(paymentRecon.getId());
            if (eleResult.getCode() != 200) {
                // 因收费成功前端需要关闭弹窗，此处信息仅用于提示所以返回ok
                return R.ok(detail, " 收费成功，电子发票开具失败 :" + eleResult.getMsg());
            }
            return R.ok(detail);
        }
        return R.ok("收费未成功，请确认实际收款情况");
    }

    /**
     * 【取消住院结算】
     *
     * @param cancelPaymentInpatientDto 退款参数
     * @return 操作结果
     */
    @PostMapping("/inpa-un-pay")
    public R<?> inpatientUnPay(@RequestBody CancelPaymentInpatientDto cancelPaymentInpatientDto) {
        R<?> r = paymentReconciliationService.inpatientUnPay(cancelPaymentInpatientDto.getId());
        // 付款成功后，开具发票
        if (r.getCode() == 200) {
            PaymentReconciliation paymentRecon = null;
            if (PaymentReconciliation.class.isAssignableFrom(r.getData().getClass())) {
                paymentRecon = (PaymentReconciliation)r.getData();
            }
            R<?> eleResult =
                eleInvoiceService.invoiceWriteoff(paymentRecon.getRelationId(), cancelPaymentInpatientDto.getReason());
            if (eleResult.getCode() != 200) {
                // 因取消付款成功前端需要关闭弹窗，此处信息仅用于提示所以返回ok
                return R.ok(null, " 取消付款成功，电子发票开具失败 :" + eleResult.getMsg());
            }
        }
        return R.ok("取消结算失败，请确认");
    }

    /**
     * 师大bpc支付
     *
     * @param nenuBpcPayDto 付款参数
     * @return 操作结果
     */
    @PostMapping("/nenu-bpc-pay")
    public R<?> nenuBpcPay(@RequestBody NenuBpcPayDto nenuBpcPayDto) {
        return R.ok(paymentReconciliationService.nenuBpcPay(nenuBpcPayDto));
    }
}
