package org.dromara.zhishu.util;


import com.baomidou.mybatisplus.core.toolkit.Assert;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.zhishu.domain.TDepot;
import org.dromara.zhishu.domain.TFreight;
import org.dromara.zhishu.domain.TShelves;
import org.dromara.zhishu.domain.vo.FreightGoodsCountVo;
import org.dromara.zhishu.mapper.TDepotMapper;
import org.dromara.zhishu.mapper.TShelvesMapper;
import org.dromara.zhishu.mapper.ZhishuShopGoodsMapper;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.apache.commons.lang3.ObjectUtils.isEmpty;

/**
 * CnumberUtils 类用于生成货号
 */
@Component
@Log4j2
@RequiredArgsConstructor
public class CnumberUtils {
    @Resource
    TDepotMapper tDepotMapper;
    @Resource
    TShelvesMapper tShelvesMapper;
    @Resource
    ZhishuShopGoodsMapper baseMapper;
    //品相对应的数值
    private static final double[] CONDITION_CODES={1,2,3,4,5,6,6.5,7,7.5,8,8.5,9,9.5,10};
    // 品相对应的字母标识
    private static final String[] CONDITION_CODE={"A","B","C","D","E","F","G","H","I","J","K","L","M","N"};

    // 品相对应的中文标识
    private static final String[] CHINESE_CODE={"一品","二品","三品","四品","五品","六品","六五品","七品","七五品","八品","八五品","九品","九五品","全新"};

    //字母转数值
    private static final Map<String, String> QUALITY_MAP = new HashMap<>();
    static {
        QUALITY_MAP.put("A", "10");
        QUALITY_MAP.put("B", "20");
        QUALITY_MAP.put("C", "30");
        QUALITY_MAP.put("D", "40");
        QUALITY_MAP.put("E", "50");
        QUALITY_MAP.put("F", "60");
        QUALITY_MAP.put("G", "65");
        QUALITY_MAP.put("H", "70");
        QUALITY_MAP.put("I", "75");
        QUALITY_MAP.put("J", "80");
        QUALITY_MAP.put("K", "85");
        QUALITY_MAP.put("L", "90");
        QUALITY_MAP.put("M", "95");
        QUALITY_MAP.put("N", "100");

        QUALITY_MAP.put("10","A");
        QUALITY_MAP.put("20","B");
        QUALITY_MAP.put("30","C");
        QUALITY_MAP.put("40","D");
        QUALITY_MAP.put("50","E");
        QUALITY_MAP.put("60","F");
        QUALITY_MAP.put("65","G");
        QUALITY_MAP.put("70","H");
        QUALITY_MAP.put("75","I");
        QUALITY_MAP.put("80","J");
        QUALITY_MAP.put("85","K");
        QUALITY_MAP.put("90","L");
        QUALITY_MAP.put("95","M");
        QUALITY_MAP.put("100","N");

        QUALITY_MAP.put("一品","10");
        QUALITY_MAP.put("二品","20");
        QUALITY_MAP.put("三品","30");
        QUALITY_MAP.put("四品","40");
        QUALITY_MAP.put("五品","50");
        QUALITY_MAP.put("六品","60");
        QUALITY_MAP.put("六五品","65");
        QUALITY_MAP.put("七品","70");
        QUALITY_MAP.put("七五品","75");
        QUALITY_MAP.put("八品","80");
        QUALITY_MAP.put("八五品","85");
        QUALITY_MAP.put("九品","90");
        QUALITY_MAP.put("九五品","95");
        QUALITY_MAP.put("全新","100");
    }
    //数字转中文
    public static final Map<String, String> NUM_CHINESE_MAP = new HashMap<>();
    static {
        NUM_CHINESE_MAP.put("10","一品");
        NUM_CHINESE_MAP.put("20","二品");
        NUM_CHINESE_MAP.put("30","三品");
        NUM_CHINESE_MAP.put("40","四品");
        NUM_CHINESE_MAP.put("50","五品");
        NUM_CHINESE_MAP.put("60","六品");
        NUM_CHINESE_MAP.put("65","六五品");
        NUM_CHINESE_MAP.put("70","七品");
        NUM_CHINESE_MAP.put("75","七五品");
        NUM_CHINESE_MAP.put("80","八品");
        NUM_CHINESE_MAP.put("85","八五品");
        NUM_CHINESE_MAP.put("90","九品");
        NUM_CHINESE_MAP.put("95","九五品");
        NUM_CHINESE_MAP.put("100","全新");
    }
    private static final String BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

    private static final String CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final int BASE = 62;


    /**
     * 单品上书获取货号
     *
     * @param conCode 品相
     * @param userId  用户ID
     * @param isbn    ISBN号
     * @param depotId 仓库ID
     * @param sheId   货架ID
     * @param freId   自由区ID
     * @return 生成的货号
     */
    public String getArtNo(Double conCode, Long userId, String isbn, Long depotId, Long sheId, Long freId,String Series) {

        if (conCode == null) {
            throw new IllegalArgumentException("品相和用户ID不能为空");
        }
       // 获取条件码
        String conditionCode = getConditionCode(conCode);
        String goodNumber = "";
        String depotCode = "";
        String sheCode = "";
        String freCode = "";
        String newisbn="";
        // ISBN 处理逻辑
        if (StringUtils.isEmpty(isbn)) {
            String newisbn1 = generateRandomIsbn();
            newisbn = convertISBN(newisbn1);
            saveIsbn(newisbn1,newisbn);
//            String oldisbn = revertRandomISBN(newisbn);
        } else {
            if(isbn.length() < 13)  {
                   String newIsbnCon = convert8To13(isbn);
                   newisbn=convertISBN(newIsbnCon);
                   saveIsbn(newIsbnCon,newisbn);
//                   String oldisbn = revertISBN(newisbn);
                // 判断数据库中是否有oldisbn和newisbn的数据
//                Integer number = tDepotMapper.selectByNewIsbn(Long.parseLong(isbn), Long.parseLong(newisbn));
////                // 如果数据库中没有oldisbn和newisbn的数据，则插入数据
//                if (number == 0) {
//                    tDepotMapper.insertIsbn(Long.parseLong(isbn), Long.parseLong(newisbn));
//                }
            }else if(isbn.length()==13){
                newisbn= convertISBN(isbn);
                saveIsbn(isbn,newisbn);
                // String oldisbn = revertISBN(newisbn);
//                newisbn=isbn;
            }
        }
        //  仓库id不能为空
        if(depotId==null){
            throw new RuntimeException("仓库ID不能为空");
        }
        //二级货区必须存在
        List<TShelves> sheCount= baseMapper.selectSheCount(depotId);
        if(sheCount.size()==0){
            throw new RuntimeException("二级货区为空");
        }
        //三级货区必须存在
        List<TFreight> freCount=baseMapper.selectFreCount1(sheCount);
        if(freCount.size()==0){
            throw new RuntimeException("三级货区为空");
        }
        Map<Long,Long> map=new HashMap<>();
        //查询出货架编码sheCode与之匹配货架编码freCode
        sheCount.forEach(she  -> {
            // 跳过无效code长度（非1位或2位）
            if (she.getCode().length()  != 1 && she.getCode().length()  != 2) {
                return; // 在forEach中相当于continue
            }
            // 查询货架编码
            List<TFreight> tFreight = baseMapper.selectBySId(she.getId());
            if (tFreight == null) {
                return; // 跳过空数据
            }
            for (int i = 0; i < tFreight.size(); i++) {
                if(tFreight.get(i).getCode()  == null){
                    return; // 跳过空数据
                }
                // 核心匹配逻辑，将符合的数据添加到map中
                if ((she.getCode().length()  == 2 && tFreight.get(i).getCode().length()  == 1) ||
                        (she.getCode().length()  == 1 && tFreight.get(i).getCode().length()  == 2)) {
                    map.put(tFreight.get(i).getId(),  she.getId());
                }
            }
        });
        // 判断map是否为空
        if(map.isEmpty()){
            throw new RuntimeException("货区不存在");
        }

        // 根据不同 ID 情况生成对应的代码
        if (isEmpty(depotId)) {
            depotCode = tDepotMapper.selectByCode(userId, depotId);
            sheCode = tShelvesMapper.selectFreCode(depotCode, userId);
            freCode = String.valueOf(generateRandomNumber(1, 5));
        } else if (isEmpty(sheId)) {
            // 1. 转换为可随机访问的Entry集合
            List<Map.Entry<Long, Long>> entries = new ArrayList<>(map.entrySet());
            // 2. 线程安全随机选择（Java 8+）
            if (!entries.isEmpty())  {
                Map.Entry<Long, Long> randomEntry = entries.get(
                        ThreadLocalRandom.current().nextInt(entries.size())
                );
                freId = randomEntry.getKey();
                sheId = randomEntry.getValue();
            }
            depotCode = tDepotMapper.selectByCode(userId, depotId);
            sheCode = tShelvesMapper.selectSCode(sheId);
            freCode = tShelvesMapper.selectByFreCode(freId);
//            freCode = String.valueOf(generateRandomNumber(1, 5));
        } else if (isEmpty(freId)) {
            // 1. 转换为可随机访问的Entry集合
            List<Map.Entry<Long, Long>> entries = new ArrayList<>(map.entrySet());
            // 2. 线程安全随机选择（Java 8+）
            if (!entries.isEmpty())  {
                Map.Entry<Long, Long> randomEntry = entries.get(
                        ThreadLocalRandom.current().nextInt(entries.size())
                );
                freId = randomEntry.getKey();
                sheId = randomEntry.getValue();
            }
            depotCode = tDepotMapper.selectByCode(userId, depotId);
            sheCode = tShelvesMapper.selectSCode(sheId);
            freCode = tShelvesMapper.selectByFreCode(freId);
//            freCode = String.valueOf(generateRandomNumber(1, 5));
        } else {
            depotCode = tDepotMapper.selectByCode(userId, depotId);
            sheCode = tShelvesMapper.selectSCode(sheId);
            freCode = tShelvesMapper.selectByFreCode(freId);
        }
        // 构建最终的货号
        goodNumber = buildArtNo(depotCode, sheCode, freCode, conditionCode, newisbn, Series);
        return goodNumber;
    }



    /**
     * Excel表上传生成货号
     * @param conCode
     * @param userId
     * @param isbn
     * @param depotId
     * @param sheId
     * @param freId
     * @param Series
     * @param tDepotList
     * @param tShelvesList
     * @param tFreightList
     * @return
     */
    public String getArtNo(Double conCode, Long userId, String isbn, Long depotId, Long sheId, Long freId,String Series,List<TDepot> tDepotList ,List<TShelves> tShelvesList,List<TFreight> tFreightList){
        // 检查必要参数
        if (conCode == null) {
            throw new IllegalArgumentException("品相和用户ID不能为空");
        }
        // 获取条件码
        String conditionCode = getConditionCode(conCode);
        String goodNumber = "";
        String depotCode = "";
        String sheCode = "";
        String freCode = "";
        String newisbn="";
        // ISBN 处理逻辑
        if (StringUtils.isEmpty(isbn)) {
           String  newisbnCon = generateRandomIsbn();
            newisbn = convertISBN(newisbnCon);
//            saveIsbn(newisbnCon,newisbn);
//           解压isbn
            // String oldisbn = revertRandomISBN(newisbn);
        } else {
            if(isbn.length() < 13)  {
                String newisbnCon = convert8To13(isbn);
                newisbn = convertISBN(newisbnCon);
//                saveIsbn(isbn,newisbnCon);
              //  String oldisbn = revertISBN(newisbn);
            }else if(isbn.length()==13){
                newisbn= convertISBN(isbn);
//                String oldisbn = revertISBN(newisbn);
//                saveIsbn(isbn,newisbn);
            }
        }
        int randomIndex = ThreadLocalRandom.current().nextInt(tDepotList.size());
        if (isEmpty(depotId)) {
            depotCode= tDepotList.get(randomIndex).getCode();
            sheCode = getShe(tDepotList.get(randomIndex).getId(),sheId,tShelvesList);
            freCode = String.valueOf(generateRandomNumber(1, 5));
        }else if (isEmpty(sheId)) {
            for ( TDepot tDepot : tDepotList){
                if (tDepot.getId().equals(depotId)) {
                    depotCode = tDepot.getCode();
                    sheCode = getShe(tDepot.getId(),sheId,tShelvesList);
                }
            }
            freCode = String.valueOf(generateRandomNumber(1, 5));
        }else if (isEmpty(freId)) {
            for ( TDepot tDepot : tDepotList){
                if (tDepot.getId().equals(depotId)) {
                    depotCode = tDepot.getCode();
                }
            }
            sheCode = getShe(depotId,sheId,tShelvesList);
            freCode = String.valueOf(generateRandomNumber(1, 5));
        }else {
            for ( TDepot tDepot : tDepotList){
                if (tDepot.getId().equals(depotId)) {
                    depotCode = tDepot.getCode();
                }
            }
            sheCode = getShe(depotId,sheId,tShelvesList);
            freCode = getFre(sheId,freId,tFreightList);
        }
        // 构建最终的货号
        goodNumber = buildArtNo(depotCode, sheCode, freCode, conditionCode, newisbn, Series);
        return goodNumber;
    }

//    保存原始和压缩后的isbn数据
//@Transactional
private void saveIsbn(String newisbnCon,String oldisbn){
        //                 判断数据库中是否有oldisbn和newisbn的数据
        Integer number = tDepotMapper.selectByNewIsbn(Long.parseLong(newisbnCon), oldisbn);
        // 如果数据库中没有oldisbn和newisbn的数据，则插入数据
        if (number == 0) {
            tDepotMapper.insertIsbn(Long.parseLong(newisbnCon),oldisbn);
        }
    }


    /**
     * 获取货架编码sheCode
     * @param depotId
     * @param sheId
     * @param tShelvesList
     * @return
     */
    private String getShe(Long depotId,Long sheId,List<TShelves> tShelvesList) {
        String  sheCode="";
        if(sheId!=null){
            for ( TShelves tShelves : tShelvesList){
                if (tShelves.getId().equals(sheId)) {
                    sheCode = tShelves.getCode();
                }
            }
        }else{
            List<TShelves>  list= tShelvesList.stream().filter(tShelves -> tShelves.getDepotId().equals(depotId)).collect(Collectors.toList());
            int randomIndex = ThreadLocalRandom.current().nextInt(list.size());
            sheCode=list.get(randomIndex).getCode();
        }
        return sheCode;
    }


    /**
     * 获取货位编码freCode
     * @param shelvesId
     * @param freightId
     * @param tFreightList
     * @return
     */
    private String getFre(Long shelvesId,Long freightId,List<TFreight> tFreightList) {
        String  freCode="";
        if(freightId!=null){
            for ( TFreight tFreight : tFreightList){
                if (tFreight.getId().equals(freightId)) {
                    freCode = tFreight.getCode();
                }
            }
        }else{
            List<TFreight>  list= tFreightList.stream().filter(tFreight -> tFreight.getShelvesId().equals(shelvesId)).collect(Collectors.toList());
            int randomIndex = ThreadLocalRandom.current().nextInt(list.size()-1);
            freCode=list.get(randomIndex).getCode();
        }
        return freCode;
    }



    // 生成A-Z或0-9的随机字符
//    public static char generateRandomChar() {
//        int randomChoice = ThreadLocalRandom.current().nextInt(36);  // 0-35
//        if (randomChoice < 26) {
//            // 生成A-Z（ASCII码65-90）
//            return (char) (randomChoice + 65);
//        } else {
//            // 生成0-9（ASCII码48-57），或直接数字转字符
//            return (char) (randomChoice - 26 + 48);
//        }
//    }




    // 辅助方法：生成随机13位 ISBN
    public static String generateRandomIsbn() {
        StringBuilder sb = new StringBuilder(13);
        ThreadLocalRandom random = ThreadLocalRandom.current();
        //国定第一个字符为6
        sb.append(678);
        for (int i = 0; i < 10; i++) {
            sb.append(random.nextInt(10)); // 生成0-9随机数
        }
        return sb.toString();
    }



    /**
     * 生成指定范围内的随机数
     *
     * @param min 最小值
     * @param max 最大值
     * @return 随机数
     */
    private int generateRandomNumber(int min, int max) {
        Random random=new Random();
        return random.nextInt(max - min + 1) + min;
    }



    /**
     * 构建货号
     *
     * @param depotCode   仓库代码
     * @param sheCode     货架代码
     * @param freCode     自由区代码
     * @param conditionCode 品相
     * @param isbn        ISBN号
     * @return 拼接后的货号
     */
    private String buildArtNo(String depotCode, String sheCode, String freCode, String conditionCode, String isbn,String Series) {

        //Series为空时，默认为A
        if(isEmpty(Series)){
            Series="A";
        }
//        毫秒级时间戳
        long timestamp = System.currentTimeMillis();
        String time = encodeBase62(timestamp);
        StringBuilder builder = new StringBuilder();
        builder.append(depotCode).append(sheCode).append(freCode).append(conditionCode).append(isbn).append(Series).append(time);
        return builder.toString();
    }


    // 品相映射表
    public static final Map<Double, String> CODE_MAP = IntStream.range(0,  CONDITION_CODES.length).boxed().collect(Collectors.toMap(
                            i -> CONDITION_CODES[i], //键：数字标识（如"1"）
                            i -> CONDITION_CODE[i],  //值：字母标识（如"A"）
                            (oldVal, newVal) -> oldVal, () -> new TreeMap<>(Comparator.comparingDouble(Double::doubleValue))));



    public static final Map<String, String> CHINESE_TO_CODE_MAP = IntStream.range(0, CHINESE_CODE.length).boxed().collect(Collectors.toMap(
                            i -> CHINESE_CODE[i],    // 键：中文标识（如"一品"）
                            i -> CONDITION_CODE[i],  // 值：字母标识（如"A"）
                            (oldVal, newVal) -> oldVal,
                            LinkedHashMap::new));  // 保持插入顺序


    public String convertChineseToCode(String chineseName) {
        String code = CHINESE_TO_CODE_MAP.get(chineseName);
        if (code == null) {
            throw new IllegalArgumentException("无效的中文品名: " + chineseName);
        }
        return code;
    }


    /**
     * 品相 字母对应 数字
     */
    public static String getQualityNum(String qualityStr){
        return QUALITY_MAP.getOrDefault(qualityStr, "UNDEFINED");
    }

    /**
     * 根据输入的数值获取对应的条件代码
     *
     * @param input 输入的数值，用于查找对应的条件代码
     * @return 对应的条件代码，如果找不到则返回"UNDEFINED"
     */
    public static String getConditionCode(double input) {
        return CODE_MAP.getOrDefault(input,  "UNDEFINED");
    }

    /**
     * 将ISBN-8转换为ISBN-13
     *
     * @param isbn8 ISBN-8格式的字符串
     * @return ISBN-13格式的字符串
     * @throws IllegalArgumentException 如果输入的ISBN-8格式不正确，则抛出异常
     */
    public static String convert8To13(String isbn8) {
        // 移除所有非数字字符
        String cleaned = isbn8.replaceAll("[^0-9]", "");

        // 验证输入长度
        if (cleaned.length() != 8) {
            throw new IllegalArgumentException("ISBN-8必须包含8位数字");
        }

        // 在前面添加978前缀
        String prefix = "978" + cleaned.substring(0, 7)+"00";
        // 计算新的校验位
        int checkDigit = calculateCheckDigit13(prefix);
        // 返回完整的ISBN-13
        return prefix + checkDigit;
    }

    /**
     * 计算ISBN-13的校验位
     *
     * @param digits ISBN-13的前12位数字
     * @return 计算得到的校验位
     */
    private static int calculateCheckDigit13(String digits) {
        int sum = 0;

        for (int i = 0; i < digits.length(); i++) {
            int digit = Character.getNumericValue(digits.charAt(i));
            // 奇数位(从0开始计数)乘以1，偶数位乘以3
            sum += (i % 2 == 0) ? digit * 1 : digit * 3;
        }
        int remainder = sum % 10;
        return (remainder == 0) ? 0 : 10 - remainder;
    }

    /**
     * 书籍自动分配货区
     *
     * @param freightGoodsCountList 货区商品数量列表 调用ZhishuShopGoodsMapper的selectFreightGoodsNumber()方法获得
     * @return 自动分配货区结果
     */
    public static FreightGoodsCountVo autoAllocatingAreas(List<FreightGoodsCountVo> freightGoodsCountList) {
        Assert.isTrue(!freightGoodsCountList.isEmpty(), "该用户下或没有库房区域，请检查后重试");
        // 找到最低的商品数量
        int minGoodsCount = Integer.MAX_VALUE;
        for (FreightGoodsCountVo item : freightGoodsCountList) {
            if (item.getGoodsCount() < minGoodsCount) {
                minGoodsCount = item.getGoodsCount();
            }
        }
        // 收集所有具有最低商品数量的记录
        List<FreightGoodsCountVo> minGoodsCountItems = new ArrayList<>();
        for (FreightGoodsCountVo item : freightGoodsCountList) {
            if (item.getGoodsCount() == minGoodsCount) {
                minGoodsCountItems.add(item);
            }
        }
        // 如果有多个相同最低数量的记录，随机选择一个
        if (!minGoodsCountItems.isEmpty()) {
            Random random = new Random();
            return minGoodsCountItems.get(random.nextInt(minGoodsCountItems.size()));
        }
        // 在正常情况下不会到达这里
        return null;
    }




    /**
     * ISBN压缩
     *
     * @param originalISBN 原始的ISBN
     * @return 转换后的ISBN
     */
    public static String convertISBN(String originalISBN) {
         // 提取ISBN的前四位
        String firstFour = originalISBN.substring(0, 4);
        // 提取ISBN的后九位
        String lastNine = originalISBN.substring(4, 13);

        // 对前四位进行编码
        String encodedFirstFour = encodeFirstFour(firstFour);
        // 对后九位进行编码
        String encodedLastNine = encodeLastNine(lastNine);
        // 返回编码后的ISBN
        return encodedFirstFour + encodedLastNine;
    }

    //正常isbn全部解压
    public static String revertISBN(String convertedISBN) {
        String encodedFirstFour = convertedISBN.substring(0, 1);
        String encodedLastNine = convertedISBN.substring(1, 6);

        String decodedFirstFour = decodeFirstFour(encodedFirstFour);
        String decodedLastNine = decodeLastNine(encodedLastNine);

        return decodedFirstFour + decodedLastNine;
    }

    //自定义isbn全部解压
    public static String revertRandomISBN(String convertedISBN) {
        String encodedFirstFour = convertedISBN.substring(0, 1);
        String encodedLastNine = convertedISBN.substring(1, 6);

        String decodedFirstFour = decodeRandomFirstFour(encodedFirstFour);
        String decodedLastNine = decodeLastNine(encodedLastNine);

        return decodedFirstFour + decodedLastNine;
    }

    /**
     * 将字符串中的前四位数字转换为对应的字母
     * 此方法旨在处理特定格式的数据转换，将数字字符串的每一位数字映射到字母，
     * 以便用于可能的编码或加密需求每个数字对应字母的规则是基于ASCII码，
     * 数字0对应字母'A'，1对应'B'，以此类推
     *
     * @param firstFour 一个包含四位数字的字符串如果输入的字符串不全为数字或者长度不是四，
     *                  将抛出IllegalArgumentException异常
     * @return 转换后的由字母组成的字符串
     * @throws IllegalArgumentException 如果输入字符串中包含非数字字符，抛出此异常
     */
    private static String encodeFirstFour(String firstFour) {
        StringBuilder sb = new StringBuilder();
        if(firstFour.equals("9777")){
            sb.append('a');
        }
        // 常规编码逻辑（9780-9789 → A-Z）
        if (firstFour.startsWith("978")  && firstFour.length()  == 4) {
            int lastDigit = firstFour.charAt(3)  - '0';
            if (lastDigit >= 0 && lastDigit <= 9) {
                sb.append((char) ('A' + lastDigit));
//                return String.valueOf((char)('A'  + lastDigit));
            }
        }
        if (firstFour.startsWith("678")  && firstFour.length()  == 4) {
            int lastDigit = firstFour.charAt(3)  - '0';
            if (lastDigit >= 0 && lastDigit <= 9) {
                sb.append((char) ('A' + lastDigit));
            }
        }
        return sb.toString();
    }


//    解压正常isbn前1位
    private static String decodeFirstFour(String encoded) {
        StringBuilder sb = new StringBuilder();
        //将encoded转换为字符
        char encod = encoded.charAt(0);
        if(encod==97){
            sb.append("9777");
        }else{
            // 校验输入范围（A-J）
            if (encod < 'A' || encod > 'J') {
                throw new IllegalArgumentException("输入字母必须为A-J之间");
            }else{
                // 计算数字部分（A=0, B=1,... J=9）
                int digit = encod - 'A';
                String con= "978" + digit;
                sb.append(con);
            }
        }

        // 返回构建好的字符串
        return sb.toString();
    }


    //    解压自定义isbn前1位
    private static String decodeRandomFirstFour(String encoded) {
        StringBuilder sb = new StringBuilder();
        //将encoded转换为字符
        char encod = encoded.charAt(0);

            int digit = encod - 'A';
            String con= "678" + digit;
            sb.append(con);
        // 返回构建好的字符串
        return sb.toString();
    }



    /**
     * 将最后九位数字编码为Base64字符串
     * 此方法首先验证输入的最后九位数字是否有效，然后将其转换为Base64编码的字符串
     * 选择Base64编码是因为它可以在不增加存储空间的情况下，有效处理数字信息
     * 为何使用5作为toBase64的第二个参数：这里的5是根据具体的编码需求和目标字符集大小来选择的，
     * 由于Base64字符集有64个字符，使用5个字符可以表示的数字范围与9位数字相符
     *
     * @param lastNine 一个字符串，包含最后九位数字
     * @return 编码后的Base64字符串
     * @throws IllegalArgumentException 如果输入的数字不是9位
     */
    private static String encodeLastNine(String lastNine) {
        // 验证输入的最后九位数字是否为有效的9位数字
        validateNineDigits(lastNine);
        // 将验证过的字符串转换为长整型数字，以便进行后续的编码处理
        long number = Long.parseLong(lastNine);
        // 使用Base64编码方式将数字编码为字符串，这里指定编码长度为5
        return toBase64(number, 5);
    }

    private static String toBase64(long number, int length) {
        char[] chars = new char[length];
        for (int i = length - 1; i >= 0; i--) {
            chars[i] = BASE64_CHARS.charAt((int) (number % 64));
            number /= 64;
        }
        if (number != 0) {
            throw new IllegalArgumentException("Number too large");
        }
        return new String(chars);
    }

//  isbn前4位压缩
    private static String decodeLastNine(String encoded) {
        long number = fromBase64(encoded);
        return String.format("%09d", number);
    }


//    压缩毫秒级时间戳
    private static long fromBase64(String encoded) {
        // 前置校验
        if (encoded == null || encoded.length()  != 5) {
            throw new IllegalArgumentException("必须为5位编码字符串");
        }

        // 解码计算
        long result = 0;
        for (char c : encoded.toCharArray())  {
            int index = BASE64_CHARS.indexOf(c);
            if (index == -1) throw new IllegalArgumentException("非法字符: " + c);
            if (result > (Long.MAX_VALUE - 63) / 64) {
                throw new ArithmeticException("数值溢出");
            }
            result = result * 64 + index;
        }
        return result;
    }

    private static void validateNineDigits(String s) {
        // 使用正则表达式检查字符串是否为9位数字
        if (!s.matches("\\d{9}")) {
            // 如果不是9位数字，抛出异常并提示必须为9位数字
            throw new IllegalArgumentException("必须为9位数字");
        }
    }





    /**
     * 编码为 base62，结果填充至长度 7
     */
    public static String encodeBase62(long num) {
        // 特殊情况处理：当输入数字为0时，直接返回编码字符的第一个字符
        if (num == 0) {
            return CHARS.substring(0, 1);
        }

        StringBuilder sb = new StringBuilder();
        // 循环将输入数字除以基数，并将余数转换为对应的Base62字符添加到字符串构建器中
        while (num > 0) {
            long rem = num % BASE;
            sb.append(CHARS.charAt((int) rem));
            num /= BASE;
        }
        // 将字符串构建器中的字符反转，以获得正确的编码顺序
        String encoded = sb.reverse().toString();
        // 填充到7位
        // 确保编码后的字符串长度至少为7位，不足7位时在前面补0
        return String.format("%7s", encoded).replace(' ', '0');
    }

    /**
     * 解码 base62 字符串为 long 数值
     */
    public static long decodeBase62(String s) {
        long num = 0;
        for (char c : s.toCharArray()) {
            num = num * BASE + CHARS.indexOf(c);
        }
        return num;
    }


}

