package com.ywt.outpatient.controllers.taihe;

import com.ywt.biz.common.enums.SexEnum;
import com.ywt.biz.common.util.DateUtil;
import com.ywt.biz.common.util.StringHelper;
import com.ywt.gapi.Result;
import com.ywt.gapi.ResultCode;
import com.ywt.gapi.order.*;
import com.ywt.gapi.taihe.outpaitent.TaiheOutpatientService;
import com.ywt.gapi.third.taihe.*;
import com.ywt.outpatient.core.BaseResponse;
import com.ywt.outpatient.core.utils.BizUtil;
import com.ywt.outpatient.service.web.MedicalCardService;
import com.ywt.outpatient.service.web.taihe.TaiheUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@RestController("/taihe/outpatient")
@RequestMapping({"/taihe/outpatient"})
public class OutpatientController {
    private static Logger logger = LoggerFactory.getLogger(OutpatientController.class);

    @Autowired
    private TaiheUserService taiheUserService;

    @DubboReference
    private OrderService orderServiceBlockingStub;

    @DubboReference
    private TaiheService taiheServiceBlockingStub;

    @DubboReference
    private TaiheOutpatientService taiheOutpatientServiceBlockingStub;

    @Autowired
    private MedicalCardService medicalCardService;

    /**
     * 获取门诊缴费列表
     *
     * @param type 1-待支付  2-已支付
     * @return
     */
    @RequestMapping({"/getPaymentList"})
    public @ResponseBody
    BaseResponse getPaymentList(@RequestParam(name = "pageIndex") int pageIndex,
                                @RequestParam(name = "pageSize") int pageSize,
                                @RequestParam(name = "type") int type,
                                @RequestParam(name = "hisPatientId") String hisPatientId) {
        BaseResponse response = new BaseResponse();

        if (type != 1 && type != 2) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "invalid type");
        }

        if (StringHelper.isNullOrWhiteSpace(hisPatientId)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "invalid hisPatientId");
        }

        if (pageIndex < 1) {
            pageIndex = 1;
        }

        if (pageSize < 1 || pageSize > 100) {
            pageSize = 20;
        }

        try {
            int userId = taiheUserService.getCurrentUserIdWrapped();
            int hospitalId = BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
            medicalCardService.verifyMedicalCard(userId, hospitalId, hisPatientId, 0);
            GetOutpatientOrderListRequest req = GetOutpatientOrderListRequest.newBuilder()
                    .setType(type)
                    .setHisPatientId(hisPatientId)
                    .setPageIndex(pageIndex)
                    .setPageSize(pageSize)
                    .setUserId(userId)
                    .build();
            GetOutpatientOrderListResponse res = orderServiceBlockingStub.getOutpatientOrderList(req);
            Result result = res.getResult();

            if (result.getCode() == ResultCode.SUCCEED) {
                List<Map<String, Object>> lst = new LinkedList<>();
                Map<String, Object> map;

                for (OutpatientOrder order : res.getOrderList()) {
                    map = new HashMap<>();
                    map.put("orderId", order.getOrderId());
                    map.put("orderNo", order.getOrderNo());
                    map.put("createTime", DateUtil.convertTimestampToDateString(order.getCreateTime(), "yyyy年MM月dd日 HH:mm"));
                    map.put("hospitalId", order.getHospitalId());
                    map.put("hospitalName", order.getHospitalName());
                    map.put("deptCode", order.getDeptCode());
                    map.put("deptName", order.getDeptName());
                    map.put("doctorCode", order.getDoctorCode());
                    map.put("doctorName", order.getDoctorName());
                    map.put("total", order.getTotal() / 100d);
                    map.put("reimbursement", order.getReimbursement() / 100d);
                    map.put("individual", order.getIndividual() / 100d);
                    map.put("paymentStatus", order.getPaymentStatus());
                    map.put("outpatientStatus", order.getOutpatientStatus());
                    map.put("userId", order.getUserId());
                    map.put("hisPatientId", order.getHisPatientId());
                    map.put("payName", order.getPayName());

                    lst.add(map);
                }

                Map<String, Object> data = new HashMap<>();
                data.put("list", lst);
                data.put("count", res.getCount());
                data.put("totalPage", res.getTotalPage());

                return response.succeed(data);
            }

            return response.failed(BaseResponse.APP_ERROR, result.getInfo());
        } catch (Exception e) {
            logger.error("getPaymentList(): {}", e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 门诊缴费单详情
     *
     * @param orderId 订单Id
     * @return
     */
    @RequestMapping({"/getOutpatientDetail"})
    public @ResponseBody
    BaseResponse getOutpatientDetail(@RequestParam(name = "orderId") int orderId) {
        BaseResponse response = new BaseResponse();
        if (orderId < 1) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "invalid orderId");
        }

        try {
            com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailRequest req =
                    com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailRequest.newBuilder()
                            .setOrderId(orderId).build();
            com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailResponse res = taiheOutpatientServiceBlockingStub.getOutpatientDetail(req);

            if (res.getCode() != ResultCode.SUCCEED_VALUE) {
                return response.failedWithAppError(res.getMsg());
            }

            com.ywt.gapi.taihe.outpaitent.OutpatientOrder order = res.getOrder();
            Map<String, Object> map = new HashMap<>();
            map.put("orderId", order.getOrderId());
            map.put("orderNo", order.getOrderNo());
            map.put("createTime", DateUtil.convertTimestampToDateString(order.getCreateTime(), "yyyy年MM月dd日 HH:mm"));
            map.put("hospitalId", order.getHospitalId());
            map.put("hospitalName", order.getHospitalName());
            map.put("deptCode", order.getDeptCode());
            map.put("deptName", order.getDeptName());
            map.put("doctorCode", order.getDoctorCode());
            map.put("doctorName", order.getDoctorName());
            map.put("total", order.getTotal() / 100d);
            map.put("reimbursement", order.getReimbursement() / 100d);
            map.put("individual", order.getIndividual() / 100d);
            map.put("amount", order.getIndividual());
            map.put("paymentStatus", order.getPaymentStatus());
            map.put("outpatientStatus", order.getOutpatientStatus());
            map.put("userId", order.getUserId());
            map.put("hisPatientId", order.getHisPatientId());
            map.put("payName", order.getPayName());
            map.put("patientName", order.getPatientName());
            map.put("patientAge", order.getPatientAge());
            map.put("patientSex", SexEnum.getSexDisplayName(order.getPatientSex()));
            return response.succeed(map);
        } catch (Exception e) {
            logger.error("getOutpatientDetail(): {}", e.getMessage(), e);
            return response.failed(BaseResponse.APP_EXCEPTION, e.getMessage());
        }
    }

    /**
     * 医保试算接口
     *
     * @param orderId       订单Id
     * @param insuranceType 医保类型
     * @return
     */
    @RequestMapping({"/calInsurance"})
    public @ResponseBody
    BaseResponse calInsurance(@RequestParam(name = "orderId") int orderId,
                              @RequestParam(name = "insuranceType") int insuranceType) {
        BaseResponse response = new BaseResponse();

        if (orderId < 1) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "invalid orderId");
        }

        String insureKey;
        String insureBizType;
        String insureTreatmentType;

        switch (insuranceType) {
            case 1:
                //职工医保
                insureKey = "101";
                insureBizType = "11";
                insureTreatmentType = "110";
                break;
            case 2:
                //生育医保(一般产检)
                insureKey = "102";
                insureBizType = "51";
                insureTreatmentType = "551";
                break;
            case 3:
                //居民医保
                insureKey = "101";
                insureBizType = "11";
                insureTreatmentType = "110";
                break;
            case 4:
                //门诊慢性病医保(糖尿病)
                insureKey = "103";
                insureBizType = "13";
                insureTreatmentType = "131";
                break;
            case 5:
                //慢性病医保(高血压)
                insureKey = "103";
                insureBizType = "13";
                insureTreatmentType = "132";
                break;
            default:
                return response.failed(BaseResponse.PARAMETER_ERROR, "invalid insuranceType");
        }

        try {
            GetOutpatientDetailRequest getDetailReq = GetOutpatientDetailRequest.newBuilder()
                    .setOrderId(orderId)
                    .build();
            GetOutpatientDetailResponse getDetailRes = orderServiceBlockingStub.getOutpatientDetail(getDetailReq);
            Result getDetailResult = getDetailRes.getResult();

            if (getDetailResult.getCode() != ResultCode.SUCCEED) {
                return response.failed(BaseResponse.APP_ERROR, getDetailResult.getInfo());
            }

            OutpatientOrder outpatientOrder = getDetailRes.getOrder();
            CalInsuranceRequest req = CalInsuranceRequest.newBuilder()
                    .setPatientId(outpatientOrder.getHisPatientId())
                    .setPrescriptionDate(DateUtil.convertTimestampToDateString(outpatientOrder.getPrescriptionDate()))
                    .setHisOrdNum(outpatientOrder.getHisOrderNo())
                    .setInsureKey(insureKey)
                    .setInsureBizType(insureBizType)
                    .setInsureTreatmentType(insureTreatmentType)
                    .setHospitalId(BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped()))
                    .build();
            CalInsuranceResponse res = taiheServiceBlockingStub.calInsurance(req);

            if (res.getCode() == ResultCode.SUCCEED_VALUE) {

                Map<String, Object> map = new HashMap<>();
                map.put("total", res.getTotal() / 100d);
                map.put("reimbursement", res.getReimbursement() / 100d);
                map.put("individual", res.getIndividual() / 100d);
                map.put("amount", res.getIndividual());

                return response.succeed("处理成功", map);
            }

            return response.failed(BaseResponse.APP_ERROR, res.getMsg());
        } catch (Exception e) {
            logger.error("calInsurance({}, {}): {}", orderId, insuranceType, e.getMessage(), e);
            return response.failed(BaseResponse.APP_EXCEPTION, e.getMessage());
        }
    }

    /**
     * 查询治疗指引
     *
     * @param orderId 订单Id
     * @return
     */
    @RequestMapping({"/getTreatmentGuide"})
    public @ResponseBody
    BaseResponse getTreatmentGuide(@RequestParam(name = "orderId") int orderId) {
        BaseResponse response = new BaseResponse();

        if (orderId < 1) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "invalid orderId");
        }

        try {
            GetOutpatientDetailRequest req = GetOutpatientDetailRequest.newBuilder()
                    .setOrderId(orderId)
                    .build();
            GetOutpatientDetailResponse res = orderServiceBlockingStub.getOutpatientDetail(req);
            Result result = res.getResult();

            if (result.getCode() != ResultCode.SUCCEED) {
                return response.failed(BaseResponse.APP_ERROR, result.getInfo());
            }

            GetTreatmentGuideRequest guideRequest = GetTreatmentGuideRequest.newBuilder()
                    .setHisOrderNo(res.getOrder().getHisOrderNo())
                    .setHospitalId(BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped()))
                    .build();
            GetTreatmentGuideResponse guideResponse = taiheServiceBlockingStub.getTreatmentGuide(guideRequest);

            if (guideResponse.getCode() != ResultCode.SUCCEED_VALUE) {
                return response.failed(BaseResponse.APP_ERROR, guideResponse.getMsg());
            }

            GetTreatmentGuideResponse.DrugApply drugApply = guideResponse.getDrugApply();
            List<GetTreatmentGuideResponse.InspectionApply> inspectionApplyList = guideResponse.getInspectionApplyList();
            List<GetTreatmentGuideResponse.InspectionApply> laboratoryApplyList = guideResponse.getLaboratoryApplyList();

            Map<String, Object> drugMap = new HashMap<>();
            List<Map<String, Object>> inspectionList = new LinkedList<>();
            List<Map<String, Object>> laboratoryList = new LinkedList<>();

            if (drugApply != null) {
                List<Map<String, Object>> drugList = new LinkedList<>();

                if (drugApply.getDrugItemList() != null && drugApply.getDrugItemList().size() > 0) {
                    for (GetTreatmentGuideResponse.DrugItem drugItem : drugApply.getDrugItemList()) {
                        Map<String, Object> itemMap = new HashMap<>();
                        itemMap.put("name", drugItem.getName());
                        itemMap.put("desc", drugItem.getDesc());
                        drugList.add(itemMap);
                    }
                }

                drugMap.put("doctorName", drugApply.getDoctorName());
                drugMap.put("statusName", drugApply.getStatusName());
                drugMap.put("title", drugApply.getTitle());
                drugMap.put("patientName", drugApply.getPatientName());
                drugMap.put("serialNo", drugApply.getSerialNo());
                drugMap.put("applyDate", drugApply.getApplyDate());
                drugMap.put("guide", drugApply.getAddr());
                drugMap.put("list", drugList);
            }

            if (inspectionApplyList != null && inspectionApplyList.size() > 0) {
                for (GetTreatmentGuideResponse.InspectionApply apply : inspectionApplyList) {
                    Map<String, Object> itemMap = new HashMap<>();
                    itemMap.put("doctorName", apply.getDoctorName());
                    itemMap.put("statusName", apply.getStatusName());
                    itemMap.put("itemName", apply.getItemName());
                    itemMap.put("title", apply.getTitle());
                    itemMap.put("patientName", apply.getPatientName());
                    itemMap.put("serialNo", apply.getSerialNo());
                    itemMap.put("applyDate", apply.getApplyDate());
                    itemMap.put("desc", apply.getDesc());
                    itemMap.put("guide", apply.getGuide());

                    inspectionList.add(itemMap);
                }
            }

            if (laboratoryApplyList != null && laboratoryApplyList.size() > 0) {
                for (GetTreatmentGuideResponse.InspectionApply apply : laboratoryApplyList) {
                    Map<String, Object> itemMap = new HashMap<>();
                    itemMap.put("doctorName", apply.getDoctorName());
                    itemMap.put("statusName", apply.getStatusName());
                    itemMap.put("itemName", apply.getItemName());
                    itemMap.put("title", apply.getTitle());
                    itemMap.put("patientName", apply.getPatientName());
                    itemMap.put("serialNo", apply.getSerialNo());
                    itemMap.put("applyDate", apply.getApplyDate());
                    itemMap.put("desc", apply.getDesc());
                    itemMap.put("guide", apply.getGuide());

                    laboratoryList.add(itemMap);
                }
            }

            Map<String, Object> data = new HashMap<>();
            data.put("drug", drugMap);
            data.put("inspectionList", inspectionList);
            data.put("laboratoryList", laboratoryList);

            return response.succeed(data);
        } catch (Exception e) {
            logger.error("getTreatmentGuide(): {}", e.getMessage(), e);
            return response.error();
        }
    }

}
