package com.example.sjkbf.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.sjkbf.common.FileManage;
import com.example.sjkbf.entity.ProjectPer;
import com.example.sjkbf.entity.projectconfig.Project;
import com.example.sjkbf.entity.projectconfig.ProjectConfig;
import com.example.sjkbf.mapper.ProjectPerMapper;
import com.example.sjkbf.service.ProjectPerService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.sjkbf.util.RSATooL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author bozhiqiang
 * @since 2025-04-15
 */
@Service
public class ProjectPerServiceImpl extends ServiceImpl<ProjectPerMapper, ProjectPer> implements ProjectPerService {


    @Autowired
    FileManage fileManage;

//    public  ProjectConfig projectConfig;


    //key为文件夹名字  y为json
    Map<String, ProjectConfig> projectScriptMap;

    public String configMd5="";

    @Override
    public Project getByName(String projectName) {

        if (projectName != null){
            return projectScriptMap.get("max").getProjectScript().get(projectName);
        }
        return null;
    }



    @Override
    public Map<String, Map<String, Object>> getProjectInfoList() {

        Map<String, Project> projectScript = projectScriptMap.get("max").getProjectScript();
        Set<String> strings = projectScript.keySet();

        Map<String, Map<String, Object>> info = new HashMap<>();
        for (String string : strings) {
            //如果是私有的就不放进去
            if(projectScript.get(string).getPrivate())continue;

            Map<String, Object> info1 = projectScript.get(string).getInfo();
            info1.put("ProjectPrice", projectScript.get(string).getPrice());
            info.put(string, info1);

        }
        return info;
    }

    @Override
    public Map<String, Map<String, Object>> getProjectInfoListAll() {

        Map<String, Project> projectScript = projectScriptMap.get("max").getProjectScript();
        Set<String> strings = projectScript.keySet();

        Map<String, Map<String, Object>> info = new HashMap<>();
        for (String string : strings) {
            Map<String, Object> info1 = projectScript.get(string).getInfo();
            info1.put("ProjectPrice", projectScript.get(string).getPrice());
            info.put(string, info1);
        }
        return info;
    }

    /**
     * 获得所有的base脚本
     * 需要一个版本号
     * @return
     */
    @Override
    public List<String>  getBaseScriptStr(String ve) {
        return projectScriptMap.get(ve).getBaseScriptStr();
    }

    public List<String>  getCSBaseScriptStr(String ve) {
        return projectScriptMap.get(ve).getCSBaseScriptStr();
    }

    /**
     * 根据key对base脚本进行加密
     * @param key
     * @return
     */
    @Override
    public List<String>  getBaseScriptStrEncrypt(int[] key,String ve) {
        List<String> baseScriptStr = getBaseScriptStr(ve);
        List<String> StrEncrypt = new ArrayList<>();

        for (String s : baseScriptStr) {
            byte[] makecode = RSATooL.Makecode(s.getBytes(), key);

            String string = Arrays.toString(makecode);
            StrEncrypt.add(string.substring(1, string.length()-1));

        }
        return  StrEncrypt;
    }

    @Override
    public List<String> getCSBaseScriptStrEncrypt(int[] key,String ve) {
        List<String> baseScriptStr = getCSBaseScriptStr(ve);
        List<String> StrEncrypt = new ArrayList<>();

        for (String s : baseScriptStr) {
            byte[] makecode = RSATooL.Makecode(s.getBytes(), key);

            String string = Arrays.toString(makecode);
            StrEncrypt.add(string.substring(1, string.length()-1));

        }
        return  StrEncrypt;
    }

    /**
     * 根据key对base脚本进行加密
     *
     * @param key
     * @return
     */
    public List<byte[]> getBaseScriptStrEncrypt2(int[] key,String  ve) {
        List<String> baseScriptStr = getBaseScriptStr(ve);
        List<byte[]> StrEncrypt = new ArrayList<>();

        for (String s : baseScriptStr) {

            byte[] makecode = RSATooL.Makecode(s.getBytes(), key);

            String string = Arrays.toString(makecode);
            StrEncrypt.add(makecode);
        }
        return  StrEncrypt;
    }

    @Override
    public List<String> getzdy(String ip, int[] key,String  ve) {

        Map<String, List<String>> projectScriptStr = projectScriptMap.get(ve).getProjectZDYScriptStr();
        if (projectScriptStr==null)return new ArrayList<>();
        List<String> strings = projectScriptStr.get(ip);
        if (strings==null)return new ArrayList<>();

        List<String> StrEncrypt = new ArrayList<>();
        for (String s : strings) {
            byte[] makecode = RSATooL.Makecode(s.getBytes(), key);
            String string = Arrays.toString(makecode);
            StrEncrypt.add(string.substring(1, string.length()-1));
        }
        return  StrEncrypt;
    }


    byte[] AESkey = new byte[]{120, -2, 20, -80, -24, 60, 62, -48, -18, 101, -117, -8, 52, 48, -59, 94};
    SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, AESkey);

    @Override
    public List<String> getzdy2(String ip,String  ve) {
        ve = "max";
        Map<String, List<String>> projectScriptStr = projectScriptMap.get(ve).getProjectZDYScriptStr();
        if (projectScriptStr==null)return new ArrayList<>();
        List<String> strings = projectScriptStr.get(ip);
        if (strings==null)return new ArrayList<>();

        List<String> StrEncrypt = new ArrayList<>();
        for (String s : strings) {

            //加密为16进制表示
            String encryptHex = aes.encryptHex(s);
            StrEncrypt.add(encryptHex);
        }
        return  StrEncrypt;
    }



    @Override
    public List<String>  getProjectScriptStr(String projectName,String ve) {
        List<String> strings = projectScriptMap.get(ve).getProjectScriptStr().get(projectName);
        return strings;
    }



    @Override
    public List<String>  getProjectScriptStrEncrypt(String projectName,int[] key,String ve) {
        Map<String, List<String>> projectScriptStr = projectScriptMap.get(ve).getProjectScriptStr();
        if (projectScriptStr==null)return new ArrayList<>();
        List<String> strings = projectScriptStr.get(projectName);
        List<String> StrEncrypt = new ArrayList<>();
        for (String s : strings) {
            byte[] makecode = RSATooL.Makecode(s.getBytes(), key);
            String string = Arrays.toString(makecode);
            StrEncrypt.add(string.substring(1, string.length()-1));
        }
        return  StrEncrypt;
    }

    @Override
    public List<byte[]>  getProjectScriptStrEncrypt2(String projectName,int[] key,String ve) {
        Map<String, List<String>> projectScriptStr = projectScriptMap.get(ve).getProjectScriptStr();
        if (projectScriptStr==null)return new ArrayList<>();
        List<String> strings = projectScriptStr.get(projectName);
        List<byte[]> StrEncrypt = new ArrayList<>();
        for (String s : strings) {
            byte[] makecode = RSATooL.Makecode(s.getBytes(), key);
            String string = Arrays.toString(makecode);
            StrEncrypt.add(makecode);
        }
        return  StrEncrypt;
    }


    @Override
    public int getProjectPrice(String projectName) {
        if (projectScriptMap.get("max").getProjectScript().get(projectName)!=null){
            return projectScriptMap.get("max").getProjectScript().get(projectName).getPrice();
        }
        return 0;
    }


    public synchronized  void   initInfo(){
        projectScriptMap = new HashMap<>();
        System.out.println("初始化项目信息");

        String scriptfile = fileManage.getScriptfile();
        //获得这个文件夹下的所有子文件夹
        File[] files = FileUtil.ls(scriptfile);

        File[] subDirs = Arrays.stream(files)
                .filter(File::isDirectory) // 仅保留子文件夹
                .toArray(File[]::new);

        // 2. 使用自定义自然排序比较器排序
        Arrays.sort(subDirs, new NaturalNameComparator());

        for (File file : subDirs) {
            //取Script 之后的文件名
            String name = file.getName().substring(7);
            System.out.println( name);
            ProjectConfig projectConfig = initInfo(file.getPath());
            projectScriptMap.put(name, projectConfig);
            projectScriptMap.put("max", projectConfig);
        }

    }

    public static void main(String[] args) {
        String content = "test中文";





    }

    //读取文件
    public synchronized  ProjectConfig  initInfo( String  path) {
        FileReader fileReader = new FileReader(path+"/"+"FileConfig.json");
        String result = fileReader.readString();
        ProjectConfig projectConfig = JSONUtil.toBean(result, new TypeReference<ProjectConfig>() {}, true);

        List<String> baseScript = projectConfig.getBaseScript();


        for (String s : baseScript) {
            FileReader fileReader1 = new FileReader(path+"/"+s);
            projectConfig.getBaseScriptStr().add(fileReader1.readString());
        }

/*
        List<String> csBaseScript = projectConfig.getCSBaseScript();
        for (String s : csBaseScript) {
            FileReader fileReader1 = new FileReader(path+"/"+s);
            projectConfig.getCSBaseScriptStr().add(fileReader1.readString());
        }*/



        Set<String> strings = projectConfig.getProjectScript().keySet();

        for (String string : strings) {

            List<String> script = projectConfig.getProjectScript().get(string).getScript();
            projectConfig.getProjectScriptStr().put(string,new ArrayList<>());
            for (String s : script) {
                FileReader fileReader1 = new FileReader(path+"\\"+s);
                projectConfig.getProjectScriptStr().get(string).add(fileReader1.readString());
            }
        }

        File[] ls = FileUtil.ls("/root/rindro/ClentUserScript");

        for (File l : ls) {
            Path path1 = Paths.get(l.getPath());
            List<String> ZDYScript = new ArrayList<>();
            if (Files.exists(path1)) {
                List<String> strings444 = FileUtil.readUtf8Lines(l + "/config");
                for (String s : strings444) {
                    File file2 = FileUtil.file(l + "/" + s);
                    FileReader fileReader1 = new FileReader(file2);
                    ZDYScript.add(fileReader1.readString());
                }
            }
            projectConfig.getProjectZDYScriptStr().put(l.getName(),ZDYScript);
        }


        return projectConfig;
    }



    private static final Pattern NUMBER_PATTERN = Pattern.compile("(\\d+\\.?\\d*)|([^\\d]+)");


    // 自定义自然排序比较器（核心）
    static class NaturalNameComparator implements Comparator<File> {
        @Override
        public int compare(File f1, File f2) {
            String name1 = f1.getName();
            String name2 = f2.getName();

            // 拆分两个名称的数字/非数字片段，逐个比较
            Matcher m1 = NUMBER_PATTERN.matcher(name1);
            Matcher m2 = NUMBER_PATTERN.matcher(name2);

            while (m1.find() && m2.find()) {
                String segment1 = m1.group();
                String segment2 = m2.group();

                int compareResult;
                // 判断当前片段是否是数字
                if (segment1.matches("\\d+\\.?\\d*") && segment2.matches("\\d+\\.?\\d*")) {
                    // 数字片段：按数值大小比较（支持小数）
                    double num1 = Double.parseDouble(segment1);
                    double num2 = Double.parseDouble(segment2);
                    compareResult = Double.compare(num1, num2);
                } else {
                    // 非数字片段：按字符串字典序比较（忽略大小写，可选）
                    compareResult = segment1.compareToIgnoreCase(segment2);
                }

                // 只要有一个片段比较出结果，就返回
                if (compareResult != 0) {
                    return compareResult;
                }
            }

            // 前面的片段都相同，短名称排前面
            return Integer.compare(name1.length(), name2.length());
        }
    }
}
