package thyyxxk.webserver.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import thyyxxk.webserver.entity.zygl.PatientMiSfz;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @Description:
 * @Author:lihong
 * @Date: 2023/1/12
 */
@Slf4j
public class CommonUtil {
    /**
     * @description:计算医保支付方式
     * @author: lihong
     * @date: 2023/1/12 9:44
     * @param: insuplcAdmdvs 参保地
     * @param: medType 医疗类别
     * @param: insurtype 险种类型
     * @param: setlTime 结算时间
     * @return: java.lang.Integer
     **/
    public static Integer calcHiPaymtd (String insuplcAdmdvs, String medType, String insurtype, Date setlTime){
        //// 长沙 4301 株洲4302   湘潭 4303   衡阳4304  郴州4310(郴州先不算) 省本级 439900
        //长沙市、县、浏阳、宁乡、望城、内五区的职工、居民的普通住院、外伤住院结算清单是按DRG传， 4
        //普通住院 2101 外伤住院 22
        List<String> medTypes = Arrays.asList("2101", "22");
        //职工 310  居民 390
        List<String> insurtypes = Arrays.asList("310", "390");
        try {
            if(setlTime.getTime() < DateUtil.parse("2023-01-01","yyyy-MM-dd").getTime()){
                return 3;
            }
            //单病种
            if (medType.equals("2102")) {
                return  2;
            }
            if(matchInsuplcAdmdvs(insuplcAdmdvs) && insurtypes.contains(insurtype) && medTypes.contains(medType)){
                return 4;
            }
        }catch (Exception e){
            return 1;
        }
        // 其他都是按项目 1
        return 1;
    }

    private static boolean matchInsuplcAdmdvs(String insuplcAdmdvs){
        //省本级
        if("439900".equals(insuplcAdmdvs)){
            return true;
        }
        //长沙 4301 株洲4302   湘潭 4303   衡阳4304
        String[] drgCityCode =  {"4301","4302","4303","4304"};
        for(String code:drgCityCode){
            if(insuplcAdmdvs.startsWith(code)){
                return true;
            }
        }
        return false;
    }


    public static String toInStringSql(List<String> list) {
        StringBuilder str = new StringBuilder();
        list.forEach(item ->{
            str.append("'");
            str.append(item);
            str.append("'");
            str.append(",");
        });
        String s = str.toString();
        return s.substring(0,s.length()-1);
    }


    /**
     * @description:对bean去前后空格
     * @author: lihong
     * @date: 2023/4/27 17:12
     * @param: list
     **/
    public static<T> void BeanTrim(List<T> list){
        if(CollUtil.isNotEmpty(list)){
            list.stream().forEach(item ->{
                BeanUtil.trimStrFields(item);
            });
        }
    }

    /**
     * @description:将对象字段类型为字符串,为空''的值 设置为 null
     * @author: lihong
     * @date: 2023/9/26 14:33
     * @param: object
     * @param: clazz
     **/
    public static void objectEmpty2Null(Object object,Class clazz){
        Field[] fields = ReflectUtil.getFields(clazz);
        for(Field field : fields){
            Object fieldValue = ReflectUtil.getFieldValue(object, field);
            if(fieldValue instanceof String){
                String value = (String) fieldValue;
                if(StrUtil.isBlank(value)){
                    ReflectUtil.setFieldValue(object,field,null);
                }
            }
        }
    }
    /**
     * @description:生成药单号
     * @author: lihong
     * @date: 2023/9/27 16:12
     * @param: pageNo
     **/
    public static Integer getSerPagNo(Integer pageNo) {
        String date = cn.hutool.core.date.DateUtil.formatDate(new Date());
       return Integer.valueOf(date.substring(2,4)+date.substring(5, 7)+date.substring(8)+pageNo);
    }

    public static boolean containsChinese(String str){
        return Pattern.compile("[\u4e00-\u9fa5]").matcher(str).find();
    }

    private static int inc = 0;
    /**
     * 获取流水号
     * @return
     */
    public static String getReceiptNo(){
        long id = Long.parseLong(String.valueOf(System.currentTimeMillis())
                .substring(1,10)
                .concat(String.valueOf(inc)));
        inc = (inc+1)%10;
        SimpleDateFormat smf = new SimpleDateFormat("yyMMdd");
        return smf.format(new Date())+id;
    }

    public static byte[] image2byte(InputStream in){
        byte[] data = null;
        try {
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            int numBytesRead = 0;
            while ((numBytesRead = in.read(buf)) != -1) {
                output.write(buf, 0, numBytesRead);
            }
            data = output.toByteArray();
            output.close();
            in.close();
        }
        catch (FileNotFoundException ex1) {
            ex1.printStackTrace();
        }
        catch (IOException ex1) {
            ex1.printStackTrace();
        }
        return data;
    }
    /**
     * @description: 将身份证地址 拆分为 省  市 区 地址
     * @author: lihong
     * @date: 2025/5/10 16:29
     * @param: address
     * @return: province  city  district detail
     **/
    public static Map<String, String> addressResolution(String address) {
        Map<String, String> res = new HashMap<>();
        if(StrUtil.isBlank(address)) return res;
        if (address.indexOf("北京市") != -1) {
            putProvinceAll(address, "北京市", res);
        } else if (address.indexOf("天津市") != -1) {
            putProvinceAll(address, "天津市", res);
        } else if (address.indexOf("上海市") != -1) {
            putProvinceAll(address, "上海市", res);
        } else if (address.indexOf("重庆市") != -1) {
            putProvinceAll(address, "重庆市", res);
        } else if (address.indexOf("自治区") != -1) {
            int proIndex = address.indexOf("自治区");
            String province = address.substring(0, proIndex + 3);
            res.put("province", province);
            String cityAddress = address.substring(proIndex + 3);
            putCityAll(res, cityAddress);
        } else if (address.indexOf("省") != -1) {
            int proIndex = address.indexOf("省");
            String province = address.substring(0, proIndex + 1);
            res.put("province", province);
            String cityAddress = address.substring(proIndex + 1);
            putCityAll(res, cityAddress);
        } else {
            putCityAll(res, address);
        }
        return res;
    }

    public static void putProvinceAll(String address, String cityAddress, Map<String, String> res) {
        res.put("province", cityAddress);
        String city = cityAddress + "城区";
        res.put("province", city);
        String dicStr = address.substring(address.indexOf(city) + 5);
        putDistrictAndDetail(dicStr, res);
    }

    public static void putCityAll(Map<String, String> res, String cityAddress) {
        int cityIndex = cityAddress.indexOf("市");
        if (cityIndex > -1) {
            String city = cityAddress.substring(0, cityIndex + 1);
            res.put("city", city);
            String districtStr = cityAddress.substring(cityIndex + 1);
            putDistrictAndDetail(districtStr, res);
        } else {
            putDistrictAndDetail(cityAddress, res);
        }
    }

    public static void putDistrictAndDetail(String cityAddress, Map<String, String> map) {
        String district = "";
        String detail = "";
        int districtIndex = cityAddress.indexOf("县") > -1 ? cityAddress.indexOf("县") : cityAddress.indexOf("区");
        if (districtIndex > -1) {
            district = cityAddress.substring(0, districtIndex + 1);
            detail = cityAddress.substring(districtIndex + 1);
        } else {
            detail = cityAddress;
        }
        map.put("district", district);
        map.put("detail", detail);
    }


    public static byte[] createSfzZmc(PatientMiSfz patientMiSfz, byte[] txImage, byte[] sfzZmc) {
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        Color color1 = new Color(30, 30, 30);
        map.put("text", patientMiSfz.getName()); // 姓名
        map.put("color", color1);
        map.put("x", 90);
        map.put("y", 48);
        map.put("fontType", "幼圆");
        map.put("fontSize", 18);
        list.add(map);

        map = new HashMap<>();
        map.put("text", patientMiSfz.getSex()); // 性别
        map.put("color", color1);
        map.put("x", 90);
        map.put("y", 94);
        map.put("fontType", "幼圆");
        map.put("fontSize", 18);
        list.add(map);

        map = new HashMap<>();
        map.put("text", patientMiSfz.getNation()); // 民族
        map.put("color", color1);
        map.put("x", 210);
        map.put("y", 94);
        map.put("fontType", "幼圆");
        map.put("fontSize", 18);
        list.add(map);

        map = new HashMap<>();
        map.put("text", patientMiSfz.getBirthDay().split("-")[0]); // 年
        map.put("color", color1);
        map.put("x", 90);
        map.put("y", 136);
        map.put("fontType", "幼圆");
        map.put("fontSize", 18);
        list.add(map);

        map = new HashMap<>();
        map.put("text", patientMiSfz.getBirthDay().split("-")[1]);// 月
        map.put("color", color1);
        map.put("x", 180);
        map.put("y", 136);
        map.put("fontType", "幼圆");
        map.put("fontSize", 18);
        list.add(map);

        map = new HashMap<>();
        map.put("text", patientMiSfz.getBirthDay().split("-")[2]);// 日
        map.put("color", color1);
        map.put("x", 230);
        map.put("y", 136);
        map.put("fontType", "幼圆");
        map.put("fontSize", 18);
        list.add(map);

        String[] adds = new String[2];
        if (patientMiSfz.getAddress().length() > 11) {
            adds[0] = patientMiSfz.getAddress().substring(0, 11);
            adds[1] = patientMiSfz.getAddress().substring(11);
        } else {
            adds[0] = patientMiSfz.getAddress();
            adds[1] = "";
        }
        map = new HashMap<>();
        map.put("text", adds[0]); // 证件地址1
        map.put("color", color1);
        map.put("x", 90);
        map.put("y", 184);
        map.put("fontType", "幼圆");
        map.put("fontSize", 18);
        list.add(map);
        if (patientMiSfz.getAddress().length() > 11) {
            map = new HashMap<>();
            map.put("text", adds[1]);// 证件地址2
            map.put("color", color1);
            map.put("x", 90);
            map.put("y", 210);
            map.put("fontType", "幼圆");
            map.put("fontSize", 18);
            list.add(map);
        }

        map = new HashMap<>();
        map.put("text", patientMiSfz.getSocialNo()); // 证件号码
        map.put("color", color1);
        map.put("x", 167);
        map.put("y", 296);
        map.put("fontType", "微软雅黑");
        map.put("fontSize", 24);
        list.add(map);
        InputStream sfzIn = new ByteArrayInputStream(sfzZmc);
        InputStream txIn = new ByteArrayInputStream(txImage);
        try {
            Image theImg = ImageIO.read(sfzIn);
            int width = theImg.getWidth(null);
            int height = theImg.getHeight(null);
            BufferedImage bimage = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bimage.createGraphics();
            g.drawImage(theImg, 0, 0, null);
            for (int i = 0; i < list.size(); i++) {
                add(g, list.get(i));
            }
            BufferedImage content = convertTx(txIn);
            g.drawImage(content.getScaledInstance(150, 180, Image.SCALE_DEFAULT), 320, 50, null);
            g.dispose();
            return toByteArray(bimage, "jpg");
        }catch (Exception e){
            log.error("生成身份证正面照报错:",e);
        }finally {
            IoUtil.close(sfzIn);
            IoUtil.close(txIn);
        }
        return null;
    }

    private static BufferedImage convertTx(InputStream txIn) throws Exception{
        BufferedImage image = ImageIO.read(txIn);
        ImageIcon imageIcon = new ImageIcon(image);
        int w = imageIcon.getIconWidth();
        int h = imageIcon.getIconHeight();
        BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();
        g2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver());
        int alpha = 0;
        for (int i = bufferedImage.getMinX(); i < w; i++) {
            for (int j = bufferedImage.getMinY(); j < h; j++) {
                int rgb = bufferedImage.getRGB(i, j);
                //以白色为例
                int RGB = Color.WHITE.getRGB();
                int r = (rgb & 0xff0000) >> 16;
                int g = (rgb & 0xff00) >> 8;
                int b = (rgb & 0xff);
                int R = (RGB & 0xff0000) >> 16;
                int G = (RGB & 0xff00) >> 8;
                int B = (RGB & 0xff);
                if (Math.abs(R - r) < 15 && Math.abs(G - g) < 15 && Math.abs(B - b) < 15) {
                    alpha = 0;
                } else
                    alpha = 255;
                rgb = (alpha << 24) | (rgb & 0x00ffffff);
                bufferedImage.setRGB(i, j, rgb);
            }
        }
        g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver());
        return bufferedImage;
    }

    public static byte[] toByteArray(BufferedImage image, String format) throws IOException {
        // 使用ByteArrayOutputStream来存储字节数据
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 将BufferedImage写入到输出流中，指定格式
        ImageIO.write(image, format, baos);
        // 将输出流转换为字节数组
        return baos.toByteArray();
    }

    public static void add(Graphics2D g, Map<String, Object> map) {
        String markContent = (String) map.get("text");
        g.setColor((Color) map.get("color"));
        g.setBackground(Color.white);

        AttributedString ats = new AttributedString(markContent);
        Font f = new Font((String) map.get("fontType"), Font.BOLD,
                (Integer) map.get("fontSize"));
        ats.addAttribute(TextAttribute.FONT, f, 0, markContent.length());
        AttributedCharacterIterator iter = ats.getIterator();

        g.drawString(iter, (Integer) map.get("x"), (Integer) map.get("y")); // 添加水印的文字和设置水印文字出现的内容
    }

    /**
     * @description: 检查门诊诊断
     * @author: lihong  门（急）诊诊断编码范围应为:A~U开头和Z开头的编码;不包括字母V、W、X、Y开头的编码。
     * @date: 2025/7/3 15:21
     * @return: boolean
     **/
    public static boolean validateClinicDiagnose(String diagCode){
        if(StrUtil.isBlank(diagCode)) return false;
        String first = diagCode.substring(0, 1).toUpperCase();
        List<String> list = CollUtil.newArrayList(new String[]{"V", "W", "X", "Y"});
        if(!NumberUtil.isNumber(first) && !list.contains(first)){
            return true;
        }
        return false;
    }

}
