package com.zjty.autotest.mq;

import com.alibaba.fastjson.JSON;
import com.zjty.autotest.dao.AutoResultSetDao;
import com.zjty.autotest.pojo.report.ElementDetail;
import com.zjty.autotest.pojo.report.Measure;
import com.zjty.autotest.pojo.report.Report;
import com.zjty.autotest.pojo.sjq.*;
import com.zjty.autotest.pojo.test.Input;
import com.zjty.autotest.pojo.test.Project;
import com.zjty.autotest.service.AutoResultSetService;
import com.zjty.autotest.service.TestReportService;
import com.zjty.autotest.service.impl.SeleniumExecutor;
import com.zjty.autotest.util.FileHtmlUtil;
import com.zjty.autotest.util.IdWorker;
import com.zjty.autotest.util.UnZipRarUtil;
import com.zjty.autotest.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Component
@Slf4j
public class TestTask {
    @Autowired
    private AutoResultSetService autoResultSetService;
    @Autowired
    private TestReportService testReportService;
    @Autowired
    private SeleniumExecutor seleniumExecutor;
    private static Object o = new Object();

    @Scheduled(cron = "0/5 * * * * ?")
    @Async("asyncServiceExecutor")
    public void getMessage() {
        synchronized (o) {
            String take = QueueManager.take();
            log.info("获取到消息:{}", take);
            if (!StringUtils.isEmpty(take)) {
                doBusiness(take);
            }
        }
    }

    private void doBusiness(String id) {


        TestChannel testChannel = (TestChannel) CacheManager.getCache(id);
        if (testChannel != null) {
            log.info("testChannel不为空:{}", testChannel);
            try {
                Project project = new Project();
                project.setBrowser(testChannel.getBrowser().toLowerCase());
                project.setName(testChannel.getName());
                project.setUrl(testChannel.getUrl());
                List<RuleSet> ruleSets = testChannel.getRuleSets();
                List<Input> inputs = new ArrayList<>();
                project.setInputs(null);
                if (ruleSets != null) {
                    for (RuleSet ruleSet : ruleSets) {
                        Input input = new Input();
                        input.setKey(ruleSet.getDes());
                        input.setAttrName(ruleSet.getCommand());
                        input.setAttrValue(ruleSet.getTarget());
                        input.setValue(ruleSet.getValue());
                        inputs.add(input);
                    }
                    project.setInputs(inputs);
                }


                //调用黄承天代码
                Report report = seleniumExecutor.execute(project);
                log.info("黄承天结束返回 report:{}",report);
                List<Measure> measures = report.getMeasures();
                if (measures != null && measures.size() > 0) {
                    long count = measures.stream().filter(m -> m.getSuccess() != true).count();
                    EvaReport evaReport = new EvaReport();
                    evaReport.setBrowser(report.getBrowser());
                    evaReport.setFailCount(testChannel.getName() + "系统通过测试，" + "未通过测试点共0个");
                    if (count > 0) {
                        evaReport.setFailCount(testChannel.getName() + "系统未通过测试，" + "未通过测试点共" + count + "个");
                    }

                    evaReport.setProjectName(report.getProjectName());
                    evaReport.setCreateTime(new Date());
                    evaReport.setSystem("中标麒麟v7龙芯版");
                    evaReport.setUrl(testChannel.getUrl());
                    List<FailMessage> failMessages = new ArrayList<>();
                    List<Measure> measureList = measures.stream().filter(m -> !m.getSuccess()).collect(Collectors.toList());
                    for (Measure measure : measureList) {
                        FailMessage failMessage = new FailMessage();
                        failMessage.setUrl(measure.getUrl());
                        failMessage.setMessage(measure.getMessage());
                        failMessage.setPicture(measure.getScreenshot());
                        failMessages.add(failMessage);
                    }
                    evaReport.setFailMessages(failMessages);
                    evaReport.setPageRoutes(null);

                    List<PageContentTest> pageContents = new ArrayList<>();
                    for (Measure measure : measures) {
                        PageContentTest pageContentTest = new PageContentTest();
                        pageContentTest.setUrl(measure.getUrl());
                        pageContentTest.setMessage(measure.getMessage());
                        pageContentTest.setResponseTime(measure.getResponseTime());
                        pageContentTest.setScreenshot(measure.getScreenshot());
                        pageContentTest.setSuccess(0);
                        if (measure.getSuccess()) {
                            pageContentTest.setSuccess(1);
                        }
                        List<ElementDetail> elementDetails = measure.getElementDetails();
                        if (elementDetails != null) {
                            List<PageContent> contents = new ArrayList<>();
                            for (ElementDetail elementDetail : elementDetails) {
                                PageContent pageContent = new PageContent();
                                pageContent.setParms(elementDetail.getType());
                                pageContent.setMessage(elementDetail.getMessage());
                                pageContent.setResponseTime(elementDetail.getResponseTime());
                                pageContent.setSuccess(0);
                                if (elementDetail.getSuccess()) {
                                    pageContent.setSuccess(1);
                                }
                                contents.add(pageContent);
                            }
                            pageContentTest.setContents(contents);
                        }
                        pageContents.add(pageContentTest);
                    }
                    evaReport.setPageContents(pageContents);
                    List<PageRoute> pageRoutes = new ArrayList<>();
                    for (Measure measure : measures) {
                        PageRoute pageRoute = new PageRoute();
                        pageRoute.setPageName(measure.getUrl());
                        pageRoute.setSuccess(0);
                        if (measure.getSuccess()) {
                            pageRoute.setSuccess(1);
                        }
                        pageRoute.setMessage("无/有");
                        pageRoute.setPicture(measure.getScreenshot());
                        pageRoute.setResponseTime(measure.getResponseTime());
                        pageRoutes.add(pageRoute);
                    }
                    List<String> sourceUrls = getSourceUrls(testChannel, pageContents);
                    List<PageRoute> allPageRoutes = getAllPageRoutes(pageRoutes, sourceUrls);
                    if(allPageRoutes!=null&&allPageRoutes.size()>0) {
                        List<PageRoute> collect = allPageRoutes.stream().distinct().collect(Collectors.toList());
                        if (collect != null && collect.size() > 0) {
                            evaReport.setPageRoutes(collect);
                        } else {
                            evaReport.setPageRoutes(null);
                        }
                    }else {
                        evaReport.setPageRoutes(null);
                    }

                    log.info("修改状态");
                    //改变报告状态
                    String out = JSON.toJSONString(evaReport);

                    log.info(id);
                    TestReport testReport = new TestReport();
                    testReport.setResultId(id);
                    testReport.setOutReport(out);

                    testReportService.update(testReport);
                    autoResultSetService.updateByid(id, 1);
                    WebSocketServer.sendInfo("1," + id, "sjq110");
                    return;
                }
                log.info("评测失败");
                autoResultSetService.updateByid(id, 2);
                WebSocketServer.sendInfo("2," + id, "sjq110");
            } catch (Exception e) {
                log.info("评测失败:{}",e.getMessage());
                e.printStackTrace();
                try {
                    autoResultSetService.updateByid(id, 2);
                    WebSocketServer.sendInfo("2," + id, "sjq110");
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }

        }
    }

    private List<String> getSourceUrls(TestChannel testChannel, List<PageContentTest> pageContents) {
        if (testChannel.getCodeUrl() != null) {
            //解压上传得代码
            FileHtmlUtil.getFiles(testChannel.getCodeUrl(), null);
            Map<String, List<FileType>> alls = FileHtmlUtil.getAlls();

            //获取项目类型
            FileHtmlUtil.getFileRoutes(testChannel.getCodeUrl());
            int jspcount = FileHtmlUtil.jspNum;
            int jscount = FileHtmlUtil.jsNum;
            int vuecount = FileHtmlUtil.vueNum;
            int angularcount = FileHtmlUtil.angularNum;
            int htmlcount = FileHtmlUtil.count;
            String fileRoutes = null;
            if (jspcount > 0) {
                fileRoutes = "jsp";
            } else if (vuecount > 0) {
                fileRoutes = "vue";
            } else if (jscount > 0) {
                fileRoutes = "react";
            } else if (angularcount > 0) {
                fileRoutes = "angular";
            }
            if (fileRoutes != null) {
                log.info("源码类型:" + fileRoutes);
                List<String> routerList = getRouterList(alls, fileRoutes);
                List<String> collect = routerList.stream().map(String::toLowerCase).distinct().collect(Collectors.toList());
                log.info("源代码中的路由地址:" + collect.toString());
                FileHtmlUtil.clearAll();
                return collect;
            }
            FileHtmlUtil.clearAll();
        }
        return null;
    }

    private List<String> getRouterList(Map<String, List<FileType>> alls, String fileRoutes) {
        String pattern = "(<*\\/:*[a-zA-Z]+)+";
        List<String> allRouters = new ArrayList<>();
        Set<String> all = alls.keySet();
        if (all != null) {
            //所有的路由
            if (fileRoutes.equals("vue")) {
                for (String s1 : all) {
                    if ("router".equals(s1)) {
                        List<FileType> fileBeans = alls.get(s1);
                        if (fileRoutes != null) {

                            for (FileType fileBean : fileBeans) {
                                if (fileBean.getFileName().equals("index.js")) {
                                    allRouters.addAll(FileHtmlUtil.readTxtFile(fileBean.getAddress(), pattern));
                                }
                            }
                        }
                    }
                }
            } else if (fileRoutes.equals("angular")) {
                for (String s1 : all) {
                    if("app".equals(s1)) {
                        List<FileType> fileBeans = alls.get(s1);
                        if (fileRoutes != null) {
                            for (FileType fileBean : fileBeans) {
                                if (fileBean.getFileName().equals("app.module.ts")) {
                                    allRouters.addAll(FileHtmlUtil.readTxtFile(fileBean.getAddress(), pattern));
                                }
                            }
                        }
                    }
                }
            }else if (fileRoutes.equals("react")) {
                for (String s1 : all) {
                        List<FileType> fileBeans = alls.get(s1);
                        if (fileRoutes != null) {
                            for (FileType fileBean : fileBeans) {
                                if (fileBean.getFileName().equals("index.js")) {
                                    allRouters.addAll(FileHtmlUtil.readTxtFile(fileBean.getAddress(), pattern));
                                }
                            }
                        }
                    }
                }
            } else {
                return null;
            }
        return allRouters;
    }

    public static void main(String[] args) {
        List<PageRoute> pageRoutes = new ArrayList<>();
        PageRoute p1 = new PageRoute();
        p1.setPageName("http://www.baidu.com/eva/update");
        PageRoute p2 = new PageRoute();
        p2.setPageName("/eva/save");
        PageRoute p3 = new PageRoute();
        p3.setPageName("http://www.baidu.com/eva/delete");
        PageRoute p4 = new PageRoute();
        p4.setPageName("http://www.baidu.com/eva/find");
        PageRoute p5 = new PageRoute();
        p5.setPageName("http://www.baidu.com/sff/1/s/10");
        pageRoutes.add(p1);
        pageRoutes.add(p2);
        pageRoutes.add(p3);
        pageRoutes.add(p4);
        pageRoutes.add(p5);

        List<String> urls = Arrays.asList("/save", "/find/search", "/update", "/sdf/hks", "/sff/:sdf/s/:size");
        List<PageRoute> pageRouteList = new ArrayList<>();
        List<String> s = new ArrayList<>();
        for (PageRoute pageRoute : pageRoutes) {
            for (String url : urls) {
                if (pageRoute.getPageName().contains(url)) {
                    pageRouteList.add(pageRoute);
                    s.add(url);
                }
            }
        }
        List<String> collect = urls.stream().filter(u -> !s.contains(u)).collect(Collectors.toList());
        List<PageRoute> ps = pageRoutes.stream().filter(u -> !pageRouteList.contains(u)).collect(Collectors.toList());
        List<PageRoute> allPageRoutes = new ArrayList<>();
        for (PageRoute pageRoute : pageRouteList) {
            pageRoute.setMessage("有/有");
            allPageRoutes.add(pageRoute);
        }
        for (String s1 : collect) {
            PageRoute pageRoute = new PageRoute();
            pageRoute.setPageName(s1);
            pageRoute.setMessage("有/无");
            pageRoute.setResponseTime(0);
            pageRoute.setSuccess(0);
            allPageRoutes.add(pageRoute);
        }
        for (PageRoute p : ps) {
            p.setMessage("无/有");
            allPageRoutes.add(p);
        }

        allPageRoutes.stream().forEach(System.out::println);
    }

    public List<PageRoute> getAllPageRoutes(List<PageRoute> pageRoutes, List<String> sourceUrls) {
        if (pageRoutes == null || pageRoutes.size() == 0) {
            return null;
        }
        if (sourceUrls == null || sourceUrls.size() == 0) {
            return pageRoutes;
        }
        List<PageRoute> pageRouteList = new ArrayList<>();
        List<String> s = new ArrayList<>();
        for (PageRoute pageRoute : pageRoutes) {
            for (String url : sourceUrls) {
                if (pageRoute.getPageName().contains(url)) {
                    pageRouteList.add(pageRoute);
                    s.add(url);
                }
            }
        }
        List<String> collect = sourceUrls.stream().filter(u -> !s.contains(u)).collect(Collectors.toList());
        List<PageRoute> ps = pageRoutes.stream().filter(u -> !pageRouteList.contains(u)).collect(Collectors.toList());
        List<PageRoute> allPageRoutes = new ArrayList<>();
        for (PageRoute pageRoute : pageRouteList) {
            pageRoute.setMessage("有/有");
            allPageRoutes.add(pageRoute);
        }
        for (String s1 : collect) {
            PageRoute pageRoute = new PageRoute();
            pageRoute.setPageName(s1);
            pageRoute.setMessage("有/无");
            pageRoute.setResponseTime(0);
            pageRoute.setSuccess(0);
            allPageRoutes.add(pageRoute);
        }
        for (PageRoute p : ps) {
            p.setMessage("无/有");
            allPageRoutes.add(p);
        }

        allPageRoutes.stream().forEach(System.out::println);
        return allPageRoutes;
    }


}
