package thyyxxk.webserver.service.zygl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.YesOrNo;
import thyyxxk.webserver.dao.his.medicaladvice.common.DictDataDao;
import thyyxxk.webserver.dao.his.zygl.AdmissionRegistrationDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.executeItem.NumberEnum;
import thyyxxk.webserver.entity.inpatient.ZyActpatient;
import thyyxxk.webserver.entity.inpatient.charge.Windows;
import thyyxxk.webserver.entity.medicaladvice.medicamanage.MzZyReq;
import thyyxxk.webserver.entity.zygl.APatientMi;
import thyyxxk.webserver.entity.zygl.APatientMiVo;
import thyyxxk.webserver.entity.zygl.MzPatientMi;
import thyyxxk.webserver.entity.zygl.PatientMiSfz;
import thyyxxk.webserver.entity.zygl.ZyXnhRecord;
import thyyxxk.webserver.utils.AssertUtil;
import thyyxxk.webserver.utils.CommonUtil;
import thyyxxk.webserver.utils.ResultVoUtil;
import thyyxxk.webserver.utils.TokenUtil;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * @Description: 入院登记
 * @Author:lihong
 * @Date: 2025/5/6
 */
@Service
@Slf4j
public class AdmissionRegistrationService {
    @Resource
    private AdmissionRegistrationDao dao;
    @Resource
    private APatientMiService aPatientMiService;
    @Resource
    private DictDataDao dictDataDao;
    @Resource
    private ZyConfigService zyConfigService;
    @Resource
    private ZyActpatientService zyActpatientService;
    @Resource
    private  RestTemplate template;

    @Value("${thmz-api-url}")
    private String thmzApiUrl;

    public List<Map<String, Object>> selectMarital() {
        return dao.selectMarital();
    }

    public List<Map<String, Object>> selectPsnCertType() {
        return dao.selectPsnCertType();
    }

    public List<Map<String, Object>> selectAllInpatientWard() {
        return dao.selectAllInpatientWard();
    }

    public List<Map<String, Object>> selectEmployeeMi() {
        return dao.selectEmployeeMi();
    }

    public List<Map<String, Object>> selectCountry() {
        return dao.selectCountry();
    }

    public List<Map<String, Object>> selectNation() {
        return dao.selectNation();
    }

    public List<Map<String, Object>> selectRelation() {
        return dao.selectRelation();
    }

    public List<Map<String, Object>> selectOccupation() {
        return dao.selectOccupation();
    }

    public List<Map<String, Object>> selectAdmissStatus() {
        return dao.selectAdmissStatus();
    }

    public List<Map<String, Object>> selectZyResponceType() {
        return dao.selectAllZyResponceType();
    }

    public List<Map<String, Object>> selectProvince() {
        return dao.selectProvince();
    }

    public List<Map<String, Object>> selectRegionByParentCode(String code) {
        return dao.selectRegionByParentCode(code);
    }

    public List<Map<String, Object>> querySmallDeptByCode(String code) {
        return dao.querySmallDeptByCode(code);
    }

    public List<Map<String, Object>> queryBedNumByCode(String code) {
        return dao.selectBedNumByCode(code);
    }

    /**
     * @description:
     * @author: lihong
     * @date: 2025/5/7 15:35
     * @param: inpatientNo
     * @return: thyyxxk.webserver.entity.zygl.APatientMiVo
     **/
    public APatientMiVo queryPatientAllInfoByInpatientNo(String inpatientNo) {
        APatientMiVo aPatientMiVo = dao.selectApatientMi(inpatientNo, null);
        if (aPatientMiVo == null) {
            return null;
        }
        BeanUtil.trimStrFields(aPatientMiVo);
        dealAPatientMiVo(aPatientMiVo);
        setZyFlag(aPatientMiVo);
        setMzZyReq(aPatientMiVo);
        return aPatientMiVo;
    }

    public List<APatientMiVo> queryPatientInfoByKeyWard(String keyWard) {
        List<APatientMiVo> aPatientMiVos = dao.selectPatientInfoByKeyWard(keyWard);
        if (CollUtil.isEmpty(aPatientMiVos)) {
            List<MzPatientMi> mzPatientMis = dao.selectMzPatientInfoByKeyWard(keyWard);
            if (CollUtil.isNotEmpty(mzPatientMis)) {
                CommonUtil.BeanTrim(mzPatientMis);
                List<APatientMiVo> aPatientMiVoList = new ArrayList<>();
                for (MzPatientMi mzPatientMi : mzPatientMis) {
                    APatientMiVo aPatientMiVo = APatientMiVo.builder()
                            .name(mzPatientMi.getName())
                            .mzNo(mzPatientMi.getPatientId())
                            .patientId(mzPatientMi.getPatientId())
                            .sex(Convert.toStr(mzPatientMi.getSex(), ""))
                            .birthDate(mzPatientMi.getBirthDay())
                            .homeTel(mzPatientMi.getPhoneNo())
                            .socialNo(mzPatientMi.getSocialNo())
                            .accountStreet(mzPatientMi.getDetail())
                            .inpatientNoType(0)
                            .provinceCode(mzPatientMi.getProvinceCode())
                            .cityCode(mzPatientMi.getCityCode())
                            .districtCode(mzPatientMi.getDistrictCode())
                            .birthPlace(mzPatientMi.getDistrictCode())
                            .homeStreet(mzPatientMi.getDetail())
                            .build();
                    dealAPatientMiVo(aPatientMiVo);
                    setMzZyReq(aPatientMiVo);
                    aPatientMiVoList.add(aPatientMiVo);
                    aPatientMiVos = aPatientMiVoList;
                }
            }
        } else {
            CommonUtil.BeanTrim(aPatientMiVos);
            for (APatientMiVo aPatientMiVo : aPatientMiVos) {
                dealAPatientMiVo(aPatientMiVo);
                setMzZyReq(aPatientMiVo);
                if (StrUtil.isNotBlank(aPatientMiVo.getInpatientNo())) {
                    setZyFlag(aPatientMiVo);
                }
            }
        }
        return aPatientMiVos;
    }

    private void dealAPatientMiVo(APatientMiVo aPatientMiVo) {
        if (aPatientMiVo == null) return;
        if (StrUtil.isBlank(aPatientMiVo.getPsnCertType()) || "01".equals(aPatientMiVo.getPsnCertType())) {
            aPatientMiVo.setPsnCertType("1");
        }
        if (StrUtil.isBlank(aPatientMiVo.getCountry())) {
            aPatientMiVo.setCountry("cn");
        }
        if (StrUtil.isBlank(aPatientMiVo.getNationCode())) {
            aPatientMiVo.setNationCode("HA");
        }
        if (StrUtil.isBlank(aPatientMiVo.getOccupationCode())) {
            aPatientMiVo.setOccupationCode("90");
        }
        if (StrUtil.isBlank(aPatientMiVo.getMarryCode())) {
            aPatientMiVo.setMarryCode("9");
        }
        if (NumberUtil.isNumber(aPatientMiVo.getBirthPlace()) && aPatientMiVo.getBirthPlace().length() == 6) {
            if (StringUtils.isBlank(aPatientMiVo.getProvinceCode())) {
                aPatientMiVo.setProvinceCode(aPatientMiVo.getBirthPlace().substring(0, 2) + "0000");
            }
            if (StringUtils.isBlank(aPatientMiVo.getCityCode())) {
                aPatientMiVo.setCityCode(aPatientMiVo.getBirthPlace().substring(0, 4) + "00");
            }
            if (StringUtils.isBlank(aPatientMiVo.getDistrictCode())) {
                aPatientMiVo.setDistrictCode(aPatientMiVo.getBirthPlace());
            }
            if (StringUtils.isBlank(aPatientMiVo.getHomeZipcode())) {
                aPatientMiVo.setHomeZipcode(aPatientMiVo.getBirthPlace().substring(0, 2) + "0000");
            }
            if (StringUtils.isBlank(aPatientMiVo.getHomeDistrict())) {
                aPatientMiVo.setHomeDistrict(aPatientMiVo.getBirthPlace().substring(0, 4) + "00");
            }
        }

    }

    private void setZyFlag(APatientMiVo aPatientMiVo) {
        int count = dao.selectCountZy(aPatientMiVo.getInpatientNo());
        if (count > 0) {
            aPatientMiVo.setZyFlag(1);
        }
    }

    private void setMzZyReq(APatientMiVo aPatientMiVo) {
        if (StrUtil.isNotBlank(aPatientMiVo.getMzNo())) {
            MzZyReq zyReq = dao.selectLastMzZyReq(aPatientMiVo.getMzNo());
            if (zyReq != null) {
                BeanUtil.trimStrFields(zyReq);
                aPatientMiVo.setMzZyReq(zyReq);
            }
        }
    }

    /**
     * @description: 保存 住院患者档案信息
     * @author: lihong
     * @date: 2025/5/8 9:55
     * @param: aPatientMiVo
     * @return: thyyxxk.webserver.entity.zygl.APatientMi
     **/
    public APatientMiVo saveAptientMi(APatientMiVo aPatientMiVo) {
        AssertUtil.isnotBlank(aPatientMiVo.getName(), "姓名不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getSex(), "性别不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getBirthDate(), "出生日期不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getPatientId(), "门诊号不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getHomeTel(), "手机号码不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getMarryCode(), "婚姻状态不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getOccupationCode(), "职业不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getCountry(), "国籍不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getNationCode(), "民族不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getPsnCertType(), "证件类型不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getSocialNo(), "证件号不能为空");
        AssertUtil.isnotBlank(aPatientMiVo.getAccountStreet(), "户口地址不能为空");
        if (aPatientMiVo.getAccountStreet().length() > 16) {
            aPatientMiVo.setAccountStreet(aPatientMiVo.getAccountStreet().substring(0, 16));
        }
        if (StrUtil.isNotBlank(aPatientMiVo.getHomeStreet()) && aPatientMiVo.getHomeStreet().length() > 16) {
            aPatientMiVo.setHomeStreet(aPatientMiVo.getHomeStreet().substring(0, 16));
        }
        if (StrUtil.isNotBlank(aPatientMiVo.getEmployerStreet()) && aPatientMiVo.getEmployerStreet().length() > 16) {
            aPatientMiVo.setEmployerStreet(aPatientMiVo.getEmployerStreet().substring(0, 16));
        }
        if (!PhoneUtil.isMobile(aPatientMiVo.getHomeTel())) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "手机号码不符合规范");
        }
        //身份证类型效验下号码格式
        //if(NumberEnum.ONE.getCode().equals(aPatientMiVo.getPsnCertType()) && !IdcardUtil.isValidCard(aPatientMiVo.getSocialNo())){
        //    throw new BizException(ExceptionEnum.LOGICAL_ERROR, "身份证号码不符合规范");
        //}
        //1 自动生成住院号
        String InpatientNoAuto = dictDataDao.getDictValueByDictName("4.0", "inpatientNo_auto");
        if (NumberEnum.ONE.getCode().equals(InpatientNoAuto)) {
            if (StrUtil.isBlank(aPatientMiVo.getInpatientNo())) {
                //住院号为空，需要自动生成住院号
                 if (YesOrNo.YES.getCode().equals(aPatientMiVo.getInpatientNoType())) {
                    //家床住院号
                    String jcNo = zyConfigService.getJcNo();
                    aPatientMiVo.setInpatientNo(jcNo);
                }else {
                    //自动的住院号
                    int inpatientNo = zyConfigService.getInpatientNo();
                    aPatientMiVo.setInpatientNo(String.valueOf(inpatientNo));
                }
            }
        } else {
            AssertUtil.isnotBlank(aPatientMiVo.getInpatientNo(), "住院号不能为空");
            if (CommonUtil.containsChinese(aPatientMiVo.getInpatientNo())) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "住院号不能包含中文");
            }
        }
        APatientMi aPatientMi = new APatientMi();
        BeanUtil.copyProperties(aPatientMiVo, aPatientMi);
        aPatientMi.setMzNo(aPatientMiVo.getPatientId());
        aPatientMi.setOutpatientNo(aPatientMi.getInpatientNo());
        APatientMi tempAPatientMi = aPatientMiService.queryPatientMiByInPatientNo(aPatientMiVo.getInpatientNo());
        if (tempAPatientMi != null) {
            aPatientMiService.modifyMzPatientMiByInpatientNo(aPatientMi);
        } else {
            aPatientMiService.saveMzPatientMi(aPatientMi);
        }
        return aPatientMiVo;
    }

    public ResultVo<Windows> queryLastWindowsIpAddress(String ipAddress) {
        String realUrl = thmzApiUrl + "/api/v1/queryWindowsByIp?ip=" + ipAddress;
        ResultVo<Windows> response = new ResultVo();
        try {
             response = template.getForObject(realUrl, ResultVo.class);
            if (response == null || response.getCode() == -1) {
                throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, "获取窗口信息失败");
            }
            if (response.getCode() == -1) {
                response.setCode(ExceptionEnum.INTERNAL_SERVER_ERROR.getCode());
            } else {
                response.setCode(ExceptionEnum.SUCCESS.getCode());
            }
        }catch (Exception e){
            response.setCode(ExceptionEnum.INTERNAL_SERVER_ERROR.getCode());
            response.setMessage("获取窗口信息失败");
            log.error("[queryLastWindowsIpAddress]报错:",e);
        }

        return response;
    }

    /**
     * @description:
     * @author: lihong
     * @date: 2025/5/9 10:04
     * @param: type 1 户口本
     * @param: patientId  查看户口本 传住院号 看身份证 传门诊号
     * @return: java.lang.String
     **/
    public byte[] querySfzOrHkb(Integer type, String patientId) {
        if (YesOrNo.YES.getCode().equals(type)) {
            ZyXnhRecord zyXnhRecord = queryZyXnhRecord(patientId);
            if (zyXnhRecord != null) {
                return zyXnhRecord.getFileXnh();
            }
        } else {
            List<PatientMiSfz> patientMiSfzs = dao.selectPatientMiSfzsByPatientId(patientId);
            if (CollUtil.isNotEmpty(patientMiSfzs)) {
                byte[] sfzImage = patientMiSfzs.get(patientMiSfzs.size() - 1).getSfzImage();
                return sfzImage;
            } else {
                List<String> inList = aPatientMiService.queryInPatientNoByMzNo(patientId);
                if (CollUtil.isNotEmpty(inList)) {
                    String patNO = inList.get(0);
                    PatientMiSfz patientMiSfz = queryByPatNo(patNO, patientId);
                    if (patientMiSfz != null) {
                        byte[] sfzImage = patientMiSfz.getSfzImage();
                        return sfzImage;
                    }
                }
            }
        }
        return null;
    }

    public ZyXnhRecord queryZyXnhRecord(String patNo) {
        List<ZyXnhRecord> zyXnhRecords = dao.selectZyXnhRecordByPatNo(patNo);
        if (CollUtil.isNotEmpty(zyXnhRecords)) {
            if (zyXnhRecords.size() == 1) {
                return zyXnhRecords.get(0);
            } else {
                return zyXnhRecords.stream().max(Comparator.comparing(item -> item.getAdmissTimes() + item.getItemNo())).get();
            }
        }
        return null;
    }

    public PatientMiSfz queryByPatNo(String patNO, String patientId) {
        PatientMiSfz patientMiSfz = dao.selectByPatNo(patNO);
        if (patientMiSfz != null) {
            //  更新门诊号
            dao.updatePatientId(patNO, patientId);
        }
        return patientMiSfz;
    }

    public int saveUpdatePatientId(String inpatientNo, String mzNo) {
        AssertUtil.isnotBlank(inpatientNo, "住院号不能为空");
        AssertUtil.isnotBlank(mzNo, "门诊号不能为空");
        return dao.updateMzNoByInpatientNo(inpatientNo, mzNo);
    }

    public int saveZyXnhRecord(ZyXnhRecord zyXnhRecord) {
        ZyActpatient zyActpatient = zyActpatientService.queryByInpatientNo(ZyActpatient.ZY_ACTPATIENT, zyXnhRecord.getInpatientNo(), null);
        if (zyActpatient != null) {
            zyXnhRecord.setAdmissTimes(zyActpatient.getAdmissTimes());
        } else {
            APatientMi aPatientMi = aPatientMiService.queryPatientMiByInPatientNo(zyXnhRecord.getInpatientNo());
            if (aPatientMi != null && aPatientMi.getLastadmissTimes() != null) {
                zyXnhRecord.setAdmissTimes(aPatientMi.getLastadmissTimes() + 1);
            }
        }
        String maxItemNo = dao.selectZyXnhRecord(zyXnhRecord);
        if (StrUtil.isNotBlank(maxItemNo) && NumberUtil.isInteger(maxItemNo)) {
            zyXnhRecord.setItemNo(Convert.toStr(Integer.valueOf(maxItemNo) + 1));
        }
        Integer num = dao.insertZyXnhRecord(zyXnhRecord);
        return num;
    }

    public int saveSfzPatient(PatientMiSfz patientMiSfz) {
        AssertUtil.isnotBlank(patientMiSfz.getSocialNo(),"身份证号码不能为空");
        AssertUtil.isnotBlank(patientMiSfz.getPatientId(),"门诊号不能为空");
        AssertUtil.isnotBlank(patientMiSfz.getInpatientNo(),"住院号不能为空");
        AssertUtil.isnotBlank(patientMiSfz.getBirthDay(),"出生日期不能为空");
        String base64SfzZm = dictDataDao.getDictValueByDictName("4.1", "sfzzm");
        patientMiSfz.setTxImage(Base64.decode(patientMiSfz.getTxImageBase64()));
        byte[] sfzZmc = CommonUtil.createSfzZmc(patientMiSfz, patientMiSfz.getTxImage(), Base64.decode(base64SfzZm));
        if(sfzZmc == null){
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "上传身份证失败");
        }
        patientMiSfz.setSfzImage(sfzZmc);
        patientMiSfz.setSex("男".equals(patientMiSfz.getSex()) ? "1" : "2");
        patientMiSfz.setBirthDay(DateUtil.format(DateUtil.parseDate(patientMiSfz.getBirthDay()),"yyyy年MM月dd日"));
        dao.deletePatientMiSfzByPatientId(patientMiSfz.getPatientId());
        return dao.insertPatientMiSfz(patientMiSfz);
    }

    public ResultVo<String> saveWindowPrint(Windows windows) {
        String realUrl = thmzApiUrl + "/saveWindowPrint";
        ResultVo response = null;
        try {
            windows.setUserIdCode(TokenUtil.getInstance().getTokenUserId());
            response = template.postForObject(realUrl,windows, ResultVo.class);
            if (response == null) {
                throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, "保存打印机配置失败");
            }
            if (response.getCode() == -1) {
                throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, response.getMessage());
            }
        }catch (Exception e){
            log.error("[saveWindowPrint]报错:",e);
            throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, "保存打印机配置失败:"+e.getMessage());
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo getMzZdDeptNos() {
        List<Map<String, Object>> list = dao.selectMzZdDeptNos();
        return ResultVoUtil.success(list);
    }
}
