package com.yeejoin.amos.kgd.config;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.component.robot.AmosRequestContext;
import com.yeejoin.amos.kgd.message.Constant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.typroject.tyboot.core.foundation.context.SpringContextHelper;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: xl
 * @Description:
 * @Date: 2023/10/10 16:21
 */
@SuppressWarnings("UnnecessarySemicolon")
public class ClientHandler<path> implements Runnable {
    private static final Logger log = LoggerFactory.getLogger(ClientHandler.class);

    private final Socket socket;

    private final String hostAndPort;

    public ClientHandler(Socket socket, String hostAndPort) {
        this.socket = socket;
        this.hostAndPort = hostAndPort;  //127.0.0.1:30009
    }

    @Override
    public void run() {
        try {


            // 获取输入流和输出流
            InputStream ips = socket.getInputStream();
            // ips中，不是单纯的文件流，还有一些其他字段，所以要将单纯文件的部分过滤出来
            String filePath = filenameFilter(ips);
            String filenameWithSuffix = FileSystems.getDefault().getPath(filePath).getFileName().toString();
            String filename = filenameWithSuffix.substring(0, filenameWithSuffix.lastIndexOf("."));

            ips = fileInputStreamFilter(ips);
            // 处理客户端请求
            log.info("收到客户端数据: ");
            String path = this.upload2Maas(ips, hostAndPort, filename);
            log.info("调用maas服务返回结果: {}", path);
            // 关闭连接
            byte[] bytes = path.getBytes();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String upload2Maas(InputStream inputStream, String hostAndPort, String filename) throws IOException {


        Properties properties = new Properties();
        FileInputStream input = new FileInputStream("amos-boot-system-kgd\\src\\main\\resources\\application-dev.properties");
        properties.load(input);
        String keyValue = properties.getProperty("keyValue");
        System.out.println(keyValue);

        AmosRequestContext robotAuthentication = SpringContextHelper.getBean(AmosRequestContext.class);
        if (Objects.nonNull(robotAuthentication)) {
            String token = robotAuthentication.getToken();
            String product = robotAuthentication.getProduct();
            String appKey = robotAuthentication.getAppKey();

/*            String token = "ae8d0003-128c-424f-9730-dc9923c395b1";  // 如果token、失效，就去浏览器复制最新的token、
            String product = "AMOS_STUDIO_WEB";
            String appKey = "AMOS_STUDIO";*/


            //1, 上传到maas
            String uploadUrl = "http://" + hostAndPort + "/maas/maas/desktop/excel/upload";
            MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
            Resource resource = new InputStreamResource(inputStream) {
                @Override
                public long contentLength() throws IOException {
                    long size = inputStream.available();
                    return size;
                }

                @Override
                public String getFilename() {
                    return "xlsx";
                }
            };
            params.add("file", resource);
            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, getHeader(token, product, appKey, hostAndPort, true));
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> responseEntity = restTemplate.exchange(uploadUrl, HttpMethod.POST, requestEntity, String.class);
            String body = responseEntity.getBody();
            JSONObject jsonObject = JSONObject.parseObject(body);
//            String result = jsonObject.getString("result");
            String result = jsonObject.getJSONObject("result").getString("key");
            String path = jsonObject.getString("path");
            if (jsonObject.getString("status").equals("200")) {
                log.info("路径：" + path + "/" + result);
            } else {
                throw new RuntimeException("返回状态码错误");
            }

            // 2， 调用conn接口
            String connsUrl = "http://" + hostAndPort + "/maas/maas/desktop/conns";
            Map<String, String> params2 = new HashMap<>();
            params2.put("connType", "excel");
            params2.put("detail", "{\"location\":{\"type\":\"excel\",\"path\":\"" + result + "\"}}");
            params2.put("subjectid", keyValue);
            HttpEntity<Map<String, String>> requestEntity2 = new HttpEntity<>(params2, getHeader(token, product, appKey, hostAndPort, false));
            ResponseEntity<String> response2 = restTemplate.exchange(connsUrl, HttpMethod.POST, requestEntity2, String.class);
            String body2 = response2.getBody();
            JSONObject jsonObject2 = JSONObject.parseObject(body2);
            String connId = jsonObject2.getString("result");
            String pathConns = jsonObject2.getString("path");

//            String queryUrl = "http://" + hostAndPort + "/maas/maas/desktop/data/query?page=0&size=50";
//            Map<String, String> params3 = new HashMap<>();
//            params3.put("connId", connId);
//            params3.put("query", "{\"columnNameLineNumber\":1,\"skipEmptyLines\":true,\"skipEmptyColumns\":false,\"columnFormatter\":{},\"sheet\":\"Sheet1\",\"configed\":true}");

            //3， sheets
            String sheetsUrl = "http://" + hostAndPort + "/maas/dsm/excel/sheets";
            Map<String, String> sheetsParams = new HashMap<>();
            sheetsParams.put("fileName", result);
            HttpEntity<Map<String, String>> sheetsRequestEntity = new HttpEntity<>(sheetsParams, getHeader(token,product,appKey,hostAndPort,false));
            ResponseEntity<String> sheetsResponseEntity = restTemplate.exchange(sheetsUrl, HttpMethod.POST, sheetsRequestEntity, String.class);
            String sheetsResponseEntityBody = sheetsResponseEntity.getBody();
            JSONObject sheetJsonObject = JSONObject.parseObject(sheetsResponseEntityBody);
            JSONArray sheetArray = sheetJsonObject.getJSONArray("result");
            //result可能有多个sheet
            String[] sheets = new String[sheetArray.size()];
            for (int i = 0; i < sheetArray.size(); i++) {
                sheets[i] = (String) sheetArray.getJSONObject(i).get("sheet");
            }
            log.info("sheets的结果是:" + sheetsResponseEntityBody);


            // 4，
            String tablesUrl = "http://" + hostAndPort + "/maas/maas/desktop/tables";
            Map<String, String> params3 = new HashMap<>();
            params3.put("name", filename);
            params3.put("pid", keyValue);
            params3.put("connId", connId);
//            params3.add("config", sheetArray.get(0).toString());
            params3.put("config", "{\"columnNameLineNumber\":1,\"skipEmptyLines\":true,\"skipEmptyColumns\":false,\"columnFormatter\":{\"zztest\":{\"name\":\"zztest\",\"alias\":\"zztest\",\"type\":\"VARCHAR\"},\"zz\":{\"name\":\"zz\",\"alias\":\"zz\",\"type\":\"VARCHAR\"}},\"sheet\":\"Sheet1\"}");
            HttpEntity<Map<String, String>> requestEntity3 = new HttpEntity<>(params3, getHeader(token, product, appKey, hostAndPort, false));
            ResponseEntity<String> response3 = restTemplate.exchange(tablesUrl, HttpMethod.POST, requestEntity3, String.class);
            String body3 = response3.getBody();
            JSONObject jsonObject3 = JSONObject.parseObject(body3);
            String result2 = jsonObject3.getString("result");
            String path2 = jsonObject3.getString("path");

            //datasource(name:excel+时间戳)
            // 获取当前时间的时间戳
            long timestamp = System.currentTimeMillis();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String timestampStr = sdf.format(new Date(timestamp));
            String datasourceUrl = "http://" + hostAndPort + "/maas/dsm/datasources";
            JSONObject all = new JSONObject();
            JSONObject oneJson = new JSONObject();
            all.put("filepath",result);
            for (int i = 0; i < sheetArray.size(); i++) {
                oneJson.put(sheets[i],sheetArray.get(i));
            }
            all.put("config",oneJson);

            Map<String, String> datasourceParams = new HashMap<>();
            datasourceParams.put("detail", all.toString());
            datasourceParams.put("groupid", "72684d79-5d28-4086-9f21-5b091b6675db");
            datasourceParams.put("subtype", "excel");
            datasourceParams.put("name", "excel"+timestampStr);
            datasourceParams.put("type", "File");
            HttpEntity<Map<String, String>> datasourceRequestEntity = new HttpEntity<>(datasourceParams, getHeader(token,product,appKey,hostAndPort,false));
            ResponseEntity<String> datasourceResponseEntity = restTemplate.exchange(datasourceUrl, HttpMethod.POST, datasourceRequestEntity, String.class);
            String datasourceResponseEntityBody = datasourceResponseEntity.getBody();
            log.info("datasourceResponseEntityBody:" + datasourceResponseEntityBody);
            return path + "/" + result;
        }
        return null;
    }


    //根据机器人生成的校验参数将其放入请求头
    private HttpHeaders getHeader(String token, String product, String appKey, String hostAndPort, Boolean isUpload) {
        HttpHeaders header = new HttpHeaders();
        header.add(Constant.TOKEN, token);
        header.add(Constant.PRODUCT, product);
        header.add(Constant.APPKEY, appKey);
        if (isUpload) {
            header.setContentType(MediaType.MULTIPART_FORM_DATA);
        } else {
            header.setContentType(MediaType.APPLICATION_JSON);
        }
        return header;
    }

    public static void main(String[] args) throws Exception {
        requestInfoToSocketServer();
    }

    public static void findDelimiter(InputStream is, String delimiter) throws IOException {
        StringBuilder sb = new StringBuilder();
        int nextByte;
        while ((nextByte = is.read()) != -1) {
            char c = (char) nextByte;
            sb.append(c);

            if (sb.toString().contains(delimiter)) {
                return;
            }
        }
        throw new IOException("没有开始分隔符");
    }
    public static byte[] checkDelimiter(byte[] buf, int byteRead, byte[] delimiter) {
        if (delimiter.length > buf.length) return buf;

        for (int i = 0; i <= buf.length - delimiter.length; i ++ ) {
            boolean isMatch = true;
            for (int j = 0; j < delimiter.length; j ++ ) {
                if (buf[i + j] != delimiter[j]) {
                    isMatch = false;
                    break;
                }
            }
            if (isMatch) {
                return Arrays.copyOf(buf, i);
            }
        }

        return buf;
    }

    public static String filenameFilter(InputStream is) throws IOException {
        StringBuilder sb = new StringBuilder();
        BufferedInputStream bis = new BufferedInputStream(is);

        findDelimiter(bis, "##STATITLE##");

        byte[] endDelimiter = "##ENDTITLE##".getBytes();

        int byteRead;
        byte[] buf = new byte[4096];
        if ((byteRead = bis.read(buf)) != -1) {
            byte[] newByte = checkDelimiter(buf, byteRead, endDelimiter);
            return new String(newByte, "GBK");
        }
        throw new IOException("没有输入流内容或者文件名太长");
    }

    public static InputStream fileInputStreamFilter(InputStream is) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(is);
        String fileTmpPath = "D:\\tmp.xlsx";
        FileOutputStream fos = new FileOutputStream(fileTmpPath);

        byte[] endDelimiter   = "##ENDFILE##".getBytes();

        findDelimiter(bis, "##STAFILE##");

        int byteRead;
        byte[] buf = new byte[4000];
        while ((byteRead = bis.read(buf)) != -1) {
            byte[] newByte = checkDelimiter(buf, byteRead, endDelimiter);
            fos.write(newByte, 0, Math.min(byteRead, newByte.length));
        }
        return new FileInputStream(fileTmpPath);
    }


    //截取文件流
    public static InputStream intercept(InputStream is) throws IOException {


        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "/n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        String string1 = sb.toString();

//        int fileStart = string1.indexOf(".xlsx") + 5;
////        int fileStart = string1.indexOf(".txt") + 4;
//        String file = string1.substring(fileStart);
//
//        InputStream fileInputStream = new ByteArrayInputStream(file.getBytes());
//        return fileInputStream;

//
        int startFilePath = string1.indexOf("##STATITLE##");
        int endFilePath = string1.indexOf("##ENDTITLE##");
        int startFile = string1.indexOf("##STAFILE##");
        int endFile = string1.indexOf("##ENDFILE##");

        if (startFilePath < 0) {
            log.info("不存在文件名开始标志");
            return null;
        }
        if (endFilePath < 0) {
            log.info("不存在文件名结束标志");
            return null;
        }
        if (startFile < 0) {
            log.info("不存在文件开始标志");
            return null;
        }
        if (endFile < 0) {
            log.info("不存在文件结束标志");
            return null;
        }

        String filePath = string1.substring(startFilePath, endFilePath).substring("##STATITLE##".length());
        log.info("文件名：" + filePath);
        String file = string1.substring(startFile, endFile).substring("##STAFILE##".length());
        log.info("文件：" + file);
        System.out.println("file size " + file.length() );

//        FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\kgdcz\\data\\maas\\test.xlsx"));
//        fileOutputStream.write(file.getBytes());
//        fileOutputStream.close();

        InputStream fileInputStream = new ByteArrayInputStream(file.getBytes());
        return fileInputStream;

    }


    private static void requestInfoToSocketServer() {
        try {
            Socket socket = new Socket("127.0.0.1", 7777);
//            Socket socket = new Socket("localhost", 7777);
            OutputStream ops = socket.getOutputStream();
            FileInputStream fis = new FileInputStream("D:\\SamData\\RecordXLS\\測試\\1.xlsx");
            int len = 0;
            byte[] bs = new byte[20480];
            while ((len = fis.read(bs)) != -1) {
                ops.write(bs, 0, len);
            }
            socket.shutdownOutput();
            ops.flush();
            //开始接收服务端的消息
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            log.info("接收到服务端的回复:" + in.readLine());
        } catch (Exception e) {
            log.info("Socket传输数据异常!" + e.getMessage());
        }
    }
}