package com.lion.lionwebsite.Service;

import cn.hutool.core.util.RandomUtil;
import com.lion.lionwebsite.Dao.normal.SubMapper;
import com.lion.lionwebsite.Domain.SubBind;
import com.lion.lionwebsite.Domain.SubUpdateRecord;
import com.lion.lionwebsite.Util.CustomUtil;
import com.lion.lionwebsite.Util.FileDownload;
import com.lion.lionwebsite.Util.Response;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;

@Service
public class SubService {
    SubMapper subMapper;

    byte[] vIndex;

    String dbPath = "ip2region.xdb";
    public SubService(SubMapper subMapper) {
        this.subMapper = subMapper;
        try {
            vIndex = Searcher.loadVectorIndexFromFile(dbPath);
        }catch (Exception e){
            System.out.printf("failed to load vector index from `%s`: %s\n", dbPath, e);
        }
    }

    public String insertSubBind(String user){
        Response response = Response.generateResponse();
        String key = RandomUtil.randomString(8);
        while (subMapper.selectSubBindExist(key))
            key = RandomUtil.randomString(8);

        SubBind subBind = new SubBind(key, user);
        subMapper.insertSubBind(subBind);

        return response.success("添加成功").toJSONString();
    }

    public String resetKey(String user){
        Response response = Response.generateResponse();

        subMapper.deleteSubBind(user);
        subMapper.deleteSubUpdateRecord(user);
        String key = RandomUtil.randomString(8);
        while (subMapper.selectSubBindExist(key))
            key = RandomUtil.randomString(8);
        SubBind subBind = new SubBind(key, user);
        subMapper.insertSubBind(subBind);

        return response.success().toJSONString();
    }

    public String selectAllSubBind(){
        Response response = Response.generateResponse();
        ArrayList<SubBind> subBinds = subMapper.selectAllSubBind();
        return response.success(CustomUtil.objectMapper.valueToTree(subBinds)).toJSONString();
    }

    public String SelectAllSubUpdateRecord(){
        Response response = Response.generateResponse();
        ArrayList<SubUpdateRecord> subUpdateRecords = subMapper.selectAllSubUpdateRecord();
        return response.success(CustomUtil.objectMapper.valueToTree(subUpdateRecords)).toJSONString();
    }

    public void updateSub(HttpServletResponse response, HttpServletRequest request, String client, String key){
        if(key == null || client == null)
            return;

        SubBind subBind = subMapper.selectSubBind(key);
        if(subBind == null)
            return;

        String ip;
        if(request.getRemoteAddr().equals("127.0.0.1")){
            ip = request.getHeader("X-Forwarded-For");
            if(ip.contains(","))
                ip = ip.split(",")[0].trim();
            if(ip.contains(":"))
                ip = ip.split(":")[0].trim();
        } else
            ip = request.getRemoteAddr();

        String UA = request.getHeader("User-Agent");
        if(UA == null)
            return;

        StringBuilder location = new StringBuilder();
        Searcher searcher;
        try {
            searcher = Searcher.newWithVectorIndex(dbPath, vIndex);
            String region = searcher.search(ip);
            String[] temp = region.split("\\|");
            for (int i = 2; i < temp.length; i++)
                if(!temp[i].equals("0"))
                    location.append(temp[i]).append(" ");
        } catch (Exception e) {
            System.out.printf("failed to create vectorIndex cached searcher with `%s`: %s\n", dbPath, e);
            return;
        }

        SubUpdateRecord subUpdateRecord = new SubUpdateRecord(0, subBind.getUser(), ip, UA, new Date(), location.toString().trim());
        subMapper.insertSubUpdateRecord(subUpdateRecord);
        if(subMapper.selectUpdateRecordCount(subBind.getUser()) > 10)
            subMapper.deleteSubUpdateRecordById(subMapper.selectMinUpdateRecordId(subBind.getUser()));

        switch (client){
            case "v2" -> FileDownload.export(request, response, "sub/DouNaiV2ray.txt");
            case "cat" -> FileDownload.export(request, response, "sub/DouNaiClash.txt");
            default -> {
                try{
                    response.getOutputStream().write("client error".getBytes(StandardCharsets.UTF_8));
                } catch (IOException ignored){}
            }
        }
    }

    public String deleteSubBind(String user){
        Response response = Response.generateResponse();
        subMapper.deleteSubBind(user);
        subMapper.deleteSubUpdateRecord(user);
        return response.success("删除成功").toJSONString();
    }
}
