package org.springblade.thirdparty.ocr.util;

import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.thirdparty.ocr.constant.OCRImageType;
import org.springblade.thirdparty.ocr.convert.IDCardConvert;
import org.springblade.thirdparty.ocr.convert.TransportCertificateConvert;
import org.springblade.thirdparty.ocr.pojo.vo.IDCardVO;
import org.springblade.thirdparty.ocr.pojo.vo.TransportCertificateVO;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 *  转换工具类
 * @author bfhuange
 * @date 2024/11/7
 */
@Slf4j
public class ConvertUtil {
    private ConvertUtil() {}

    /**
     *  有效期分隔符
     */
    private static final String DATE_VALID_SPLIT = "至";
    /**
     *  有效期至 长期
     */
    private static final String DATE_VALID_END_LONG_TERM = "长期";
    /**
     *  日期格式
     */
    private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4})[-./年](\\d{1,2})[-./月](\\d{1,2})日?");

    /**
     *  非磅单类型set
     */
    private static final Set<String> NONE_POUND_TYPE_SET = initNonePoundTypeSet();
    /**
     *  车辆凭证setter map
     */
    private static final Map<String, BiConsumer<TransportCertificateVO, String>> TRANSPORT_CERTIFICATE_SETTER_MAP = initTransportCertificateSetterMap();
    /**
     *  身份证setter map
     */
    private static final Map<String, Map<String, BiConsumer<IDCardVO, String>>> ID_CARD_SETTER_MAP = initIDCardSetterMap();

    /**
     *  获取车辆凭证setter
     * @param typeId
     * @param key
     * @return
     */
    public static BiConsumer<TransportCertificateVO, String> getTransportCertificateSetter(String typeId, String key) {
        String mapKey = ConvertUtil.generateKey(typeId, key);
        return TRANSPORT_CERTIFICATE_SETTER_MAP.get(mapKey);
    }

    /**
     *  获取身份证setter
     * @param typeId
     * @param key
     * @return
     */
    public static BiConsumer<IDCardVO, String> getIDCardSetter(String typeId, String key) {
        Map<String, BiConsumer<IDCardVO, String>> setterMap = ID_CARD_SETTER_MAP.get(typeId);
        if (setterMap == null) {
            return null;
        }
        BiConsumer<IDCardVO, String> setter = setterMap.get(key);
        if (setter == null) {
            return null;
        }
        return setter;
    }

    /**
     *  转换日期
     * @param dateString
     * @return
     */
    public static Consumer<Consumer<Date>> convertDate(String dateString) {
        Date date = ConvertUtil.convert2date(dateString);
        return consumer -> consumer.accept(date);
    }

    /**
     *  转换有效期
     * @param dateString
     * @return
     */
    public static Consumer<Consumer<Date>> convertDateValid(String dateString) {
        Date date = ConvertUtil.convert2dateValid(dateString);
        return consumer -> consumer.accept(date);
    }

    /**
     *  转换有效期
     * @param dateString 日期字符串，2015-05-31至2025-05-31
     * @return
     */
    private static Date convert2dateValid(String dateString) {
        if (StringUtil.isBlank(dateString)) {
            return null;
        }
        if (dateString.contains(DATE_VALID_END_LONG_TERM)) {
            // 如果有效期至是长期，设置为10年后
            return DateUtil.plusYears(new Date(), 10);
        }
        Date rangeEndDate = ConvertUtil.parseDateRange(dateString, true);
        if (rangeEndDate != null) {
            return rangeEndDate;
        }
        // 按至分隔，解析最后一截日期
        String[] splitDate = dateString.split(DATE_VALID_SPLIT);
        return ConvertUtil.convert2date(splitDate[splitDate.length -1]);
    }

    /**
     *  截取有效期止
     * @param dateString
     * @return
     */
    public static Consumer<Consumer<Date>> extractEndDate(String dateString) {
        Date date = ConvertUtil.parseEndDate(dateString);
        return consumer -> consumer.accept(date);
    }

    /**
     *  截取有效期起
     * @param dateString
     * @return
     */
    public static Consumer<Consumer<Date>> extractStartDate(String dateString) {
        Date date = ConvertUtil.parseDateRange(dateString, false);
        return consumer -> consumer.accept(date);
    }

    /**
     *  解析有效期止
     * @param dateString 日期字符串，格式 2020.12.15-2030.12.15
     * @return
     */
    private static Date parseEndDate(String dateString) {
        Date date = ConvertUtil.parseDateRange(dateString, true);
        if (date != null) {
            return date;
        }
        if (dateString == null || dateString.isBlank()) {
            return null;
        }
        dateString = dateString.substring(dateString.lastIndexOf("-") + 1);
        return DateUtil.parse(dateString, "yyyy.MM.dd");
    }

    /**
     *  解析日期区间
     * @param dateString
     * @param end
     * @return
     */
    private static Date parseDateRange(String dateString, boolean end) {
        if (dateString == null || dateString.isBlank()) {
            return null;
        }
        Matcher matcher = DATE_PATTERN.matcher(dateString);
        String dateValue = null;
        while (matcher.find()) {
            dateValue = matcher.group();
            if (!end) {
                break;
            }
        }
        return dateValue == null ? null : ConvertUtil.convert2date(dateValue);
    }

    /**
     * 转换重量数值
     *
     * @param numString 重量字符串
     * @return
     */
    public static Consumer<Consumer<BigDecimal>> convertWeightBigDecimal(String numString) {
        BigDecimal bigDecimal = ConvertUtil.convert2WeightBigDecimal(numString);
        return consumer -> consumer.accept(bigDecimal);
    }

    /**
     *  字符串转日期
     * @param dateString
     * @return
     */
    private static Date convert2date(String dateString) {
        if (dateString == null || dateString.isBlank()) {
            return null;
        }
        try {
            return DateUtil.parse(ConvertUtil.normalizeDateString(dateString), "yyyy-MM-dd");
        } catch (Exception e) {
            log.error("解析日期异常", e);
            return null;
        }
    }

    /**
     *  归一化日期字符串
     * @param dateString
     * @return
     */
    private static String normalizeDateString(String dateString) {
        String value = dateString.trim()
                .replace("年", "-")
                .replace("月", "-")
                .replace("日", "")
                .replace("/", "-")
                .replace(".", "-");
        String[] parts = value.split("-");
        if (parts.length != 3) {
            return value;
        }
        return parts[0] + "-" + ConvertUtil.normalizeDatePart(parts[1]) + "-"
                + ConvertUtil.normalizeDatePart(parts[2]);
    }

    /**
     *  归一化月日
     * @param value
     * @return
     */
    private static String normalizeDatePart(String value) {
        String part = value.strip();
        return part.length() == 1 ? "0" + part : part;
    }

    /**
     * 字符串转数值
     *
     * @param numString
     * @return
     */
    public static BigDecimal convert2WeightBigDecimal(String numString) {
        if (numString == null || numString.isBlank()) {
            return null;
        }
        try {
            return new BigDecimal(numString);
        } catch (Exception e) {
            log.error("解析数值异常", e);
            return null;
        }
    }

    /**
     *  初始化 非磅单类型set
     * @return
     */
    private static Set<String> initNonePoundTypeSet() {
        return Stream.of(OCRImageType.values())
                .map(OCRImageType::getId)
                .collect(Collectors.toSet());
    }

    /**
     *  初始化setter map
     * @return
     */
    private static Map<String, BiConsumer<TransportCertificateVO, String>> initTransportCertificateSetterMap() {
        Map<String, BiConsumer<TransportCertificateVO, String>> setterMap = new HashMap<>();
        for (TransportCertificateConvert convert : TransportCertificateConvert.values()) {
            if (convert.getImageTypes().isEmpty()) {
                // 图像类型列表为空，设置类型id为空，只用key
                String key = ConvertUtil.generateKey(null, convert.getKeyInfo().getKey());
                setterMap.put(key, convert.getSetter());
            } else {
                for (OCRImageType imageType : convert.getImageTypes()) {
                    // 图像类型列表不为空，每个类型id和key重新生成key
                    String key = ConvertUtil.generateKey(imageType.getId(), convert.getKeyInfo().getKey());
                    setterMap.put(key, convert.getSetter());
                }
            }
        }
        return setterMap;
    }

    /**
     *  初始化 身份证 setter map
     * @return
     */
    private static Map<String, Map<String, BiConsumer<IDCardVO, String>>> initIDCardSetterMap() {
        return Stream.of(IDCardConvert.values())
                // 先按类型id分组
                .collect(Collectors.groupingBy(convert -> convert.getImageType().getId(),
                        // 再按key分组
                        Collectors.toMap(convert -> convert.getKeyInfo().getKey(), IDCardConvert::getSetter, (a, b) -> a)
                ));
    }

    /**
     *  生成key，typeId + - + key
     * @param typeId
     * @param key
     * @return
     */
    private static String generateKey(String typeId, String key) {
        return typeId == null || !NONE_POUND_TYPE_SET.contains(typeId)? key : typeId + "-" + key;
    }

}
