package com.zjty.inspect.controller;

import com.alibaba.fastjson.JSON;
import com.zjty.inspect.dao.BudegReportDao;
import com.zjty.inspect.dao.MasterConfigParamDao;
import com.zjty.inspect.entity.*;
import com.zjty.inspect.enums.LanguageEnum;
import com.zjty.inspect.service.*;
import com.zjty.inspect.thread.task.AsyncTask;
import com.zjty.inspect.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.io.File;
import java.util.*;

/**
 * 评估接口
 *
 * @author mcj
 */
@Slf4j
@RestController
@RequestMapping("/inspect")
@Api(value = "评估接口管理接口", description = "评估管理接口,提供页面的增、删、改、查")
public class InspectController {

    @Autowired
    private InspectService inspectService;
    @Autowired
    private EvaluationService evaluationService;
    @Autowired
    private EvaReportService evaReportService;
    @Autowired
    private BudegReportDao budegReportDao;

    @Autowired
    private TechnologyService technologyService;

    @Autowired
    private ReportService reportService;

    @Autowired
    private MasterConfigParamDao masterConfigParamDao;

    @Autowired
    private AsyncTask asyncTask;
    //应用类型转换:小型0
    Integer[] small = {3, 4};
    //应用类型转换:中型2
    private Integer[] middle = {1, 2, 6, 7, 8, 10};
    //应用类型转换:大型4
    private Integer[] big = {5, 9};

    @Value("${upload.location}")
    private String uploadPath;
    /**
     * 上传代码进行评估
     *
     * @param years      系统开发时间
     * @param systemFund 系统开发费用
     * @param modules    模块数
     * @param valid      预算数据是否可用
     * @param framework  架构
     * @param safety     安全能力
     * @param disaster   容灾能力
     * @param data       数据量
     * @param admin      是否管理员
     * @param multfile   文件
     * @return
     * @throws IOException
     */
    @PostMapping("/path")
    @ApiOperation("上传代码进行评估")
    public ServerResponse<ReportVo> inspect(Integer years, Integer systemFund, Integer modules
            , String valid, Integer framework, Integer safety, Integer disaster, Integer data
            , Integer admin, String projectName, Integer tables, String databaseType, Integer content, Integer method, String username, MultipartFile multfile) throws IOException {

        InspectParameter inspectParameter = new InspectParameter();
        ReportVo reportVo = new ReportVo();
        if (multfile != null) {
            File file = FileUtil.saveToLocal(multfile);
            log.info("inspect:代码解压完成,地址为{}", file.getCanonicalPath());
            inspectParameter.setSourceAddress(file.getCanonicalPath());
            reportVo.setFileName(file.getName());
            reportVo.setSourceAddress(file.getCanonicalPath());
        }
        inspectParameter.setUsername(username);
        inspectParameter.setSystemFund(systemFund);
        inspectParameter.setModules(modules);
        inspectParameter.setSafety(safety);
        inspectParameter.setTables(tables);
        inspectParameter.setValid(valid);
        inspectParameter.setYears(years);
        inspectParameter.setDisaster(disaster);
        inspectParameter.setData(data);
        inspectParameter.setFramework(framework);
        inspectParameter.setContent(content);
        inspectParameter.setId(UUIDUtil.getUUID());
        inspectParameter.setAdmin(admin);
        inspectParameter.setSystemFund(systemFund);
        inspectParameter.setRecastMethod(method);
        reportVo.setId(RandomUtil.getRandom());
        reportVo.setUploadType("文件上传");
        reportVo.setProjectName(projectName);
        reportVo.setDatabaseType(databaseType);
        ReportVo inspect = inspectService.inspect(reportVo, inspectParameter);

        int count = technologyService.findAllTechnologyCount();
        reportVo.setTechnologiesNum(count);
        int support = technologyService.findAllTechnologyNotSupport();
        reportVo.setTechnologiesRepair(support);
        log.info("inspect:代码评估完成");
        reportVo.setHtmlAddress(null);

        MasterReport report = new MasterReport();
        report.setId(RandomUtil.getRandom());
        report.setHtmlAddress(reportVo.getHtmlAddress());
        reportService.saveReport(report);
        return ServerResponse.ok(inspect);
    }

    @PostMapping("/rapidAssessment")
    public ServerResponse rapidAssessment(@RequestBody Reform reform) throws IOException {
        String in = JSON.toJSONString(reform);
        MasterEvaluation evaluation = new MasterEvaluation();
        evaluation.setInEva(in);
        //判断评估类型
        if (reform.getAssessmentType() != null && reform.getAssessmentType() == 1) {
            //快速评估
            reform.setSystemStructure(new SystemStructure());
            reform.setBrowser(new Browser());
            reform.setMiddleware(new Middleware());
            reform.setDatabase(new Database());
            reform.setApply(new Apply());
            reform.setStrategy(-1);
        }
        //获取admin
        MasterConfig adminConfig = masterConfigParamDao.findByName("admin");
        int admin;
        if (adminConfig != null) {
            admin = Integer.parseInt(adminConfig.getValue());
        } else {
            admin = 2;
        }
        System.out.println("admin:" + admin);
        System.out.println(JSON.toJSONString(reform));
        //架构类型
        Integer framework = reform.getFramework();
        if (framework != null && framework == 1) {
            framework = 2;
        }
        //应用类型
        int content = 0;
        List<Integer> applicationType = reform.getApplicationType();
        if (applicationType == null || applicationType.size() == 0) {
            content = -1;
        } else {
            for (Integer type : applicationType) {
                if (Arrays.asList(middle).contains(type)) {
                    if (content < 2) {
                        content = 2;
                    }
                } else if (Arrays.asList(big).contains(type)) {
                    content = 4;
                    break;
                }
            }
        }

        InspectParameter inspectParameter = new InspectParameter();
        inspectParameter.setContent(content);
        inspectParameter.setUsername(reform.getUsername());
        inspectParameter.setValid("1");
        inspectParameter.setSourceAddress(reform.getCodeUrl());
        inspectParameter.setSystemFund(reform.getCost());
        inspectParameter.setAdmin(admin);
        inspectParameter.setModules(reform.getModuleNum());
        inspectParameter.setSafety(reform.getSafe());
        inspectParameter.setTables(reform.getTableNum());
        inspectParameter.setDisaster(reform.getDisasterTolerance());
        inspectParameter.setData(reform.getDatabaseNum());
        inspectParameter.setFramework(framework);
        inspectParameter.setGitAddress(reform.getGitUrl());
        inspectParameter.setRecastMethod(reform.getMode());
        inspectParameter.setYears(reform.getTime());
        inspectParameter.setId(UUIDUtil.getUUID());
        ReportVo reportVo = new ReportVo();
        int count = technologyService.findAllTechnologyCount();
        reportVo.setTechnologiesNum(count);
        int support = technologyService.findAllTechnologyNotSupport();
        reportVo.setTechnologiesRepair(support);
        reportVo.setId(RandomUtil.getRandom());
        if (reform.getGitUrl() == null) {
            reportVo.setUploadType("文件上传");
        } else {
            reportVo.setUploadType("git下载");
        }
        reportVo.setFileName(reform.getCodeName());
        reportVo.setProjectName(reform.getProjectName());
        reportVo.setSourceAddress(reform.getCodeUrl());
        reportVo.setDatabaseType(null);
        ReportVo inspect = inspectService.inspect(reportVo, inspectParameter);
        log.info("inspect:代码评估完成");
        /*
        马晨俊运算结束预算
         */
        System.out.println(JSON.toJSONString(inspect));

        /*
        将马晨俊的数据放入输出的表单
         */
        AssessmentReport assessmentReport = new AssessmentReport();
        if (reform.getMode() == 1 && inspect.getLanguage() != 1) {
            assessmentReport.setCode(500);
        } else {
            assessmentReport.setCode(200);
        }
        //架构
        assessmentReport.setFramework(inspect.getFramework());
        //语言
        if (StringUtils.isEmpty(reform.getDevelopLanguageSystem().getName())) {
            assessmentReport.setLanguage(inspect.getLanguage());
        } else {
            LanguageEnum byName = LanguageEnum.getByName(reform.getDevelopLanguageSystem().getName());
            assessmentReport.setLanguage(byName.getCode());
        }
        //适配还是改造
        assessmentReport.setType(reform.getMode());
        SysScale sysScale = new SysScale();
        Scale scale = new Scale();
        //文件数量
        scale.setNum(inspect.getFileNum());
        sysScale.setFile(scale);
        //代码行数
        Scale scale1 = new Scale();
        scale1.setNum(inspect.getFileLine());
        sysScale.setCode(scale1);
        //模块数
        Scale scale2 = new Scale();
        scale2.setNum(reform.getModuleNum());
        sysScale.setMode(scale2);
        assessmentReport.setSysScale(sysScale);
        //系统名称
        assessmentReport.setSysName(inspect.getProjectName());
        //软件名称
        assessmentReport.setOrgName(inspect.getFileName());
        //评估时间
        assessmentReport.setTime(inspect.getCreateDate());
        //设置项目中有的所有语言
        assessmentReport.setLanguages(reportVo.getLanguages());

        assessmentReport.setRecastMethod(reportVo.getRecastMethod());
        //样式调整
        int css = 0;
        //API数量
        int api = 0;
        //插件替换数量
        int plugIn = 0;
        //jni数量
        int jni = 0;
        //中间件依赖数量
        int number = 0;
        HashMap<String, List<Warn>> warnDetails = inspect.getWarnDetails();
        List<TechnologyReport> technologyReports = new ArrayList<>();
        if(warnDetails!=null) {
            Set<String> keySet = warnDetails.keySet();
            for (String key : keySet) {
                List<Warn> warns = warnDetails.get(key);
                if (warns.size() > 0) {
                    TechnologyReport technologyReport = new TechnologyReport();
                    technologyReport.setTechnology(key);
                    //少一个策略
                    List<TechnologyContent> technologyContents = new ArrayList<>();
                    for (Warn warn : warns) {
                        TechnologyContent technologyContent = new TechnologyContent();
                        //technologyContent.setLocal(warn.get);
                        technologyContent.setFile(warn.getFilePath());
                        technologyContent.setKeyWord(warn.getRule());
                        technologyContent.setPosition(warn.getLineNum().toString());
                        String categoryId = warn.getCategoryId();
                        if (!Objects.equals(categoryId, "0") && categoryId != null && Objects.equals(categoryId, "1")
                                && (key.contains("不支持") || key.contains("未知"))) {
                            number += 1;
                        }
                        technologyContents.add(technologyContent);
                    }
                    if (Objects.equals(key, "前端CSS(不支持)")) {
                        css = technologyContents.size();
                    } else if (Objects.equals(key, "前端API(不支持)")) {
                        api = technologyContents.size();
                    } else if (Objects.equals(key, "前端JS(不支持)")) {
                        plugIn = technologyContents.size();
                    } else if (Objects.equals(key, "JNI(不支持)")) {
                        jni = technologyContents.size();
                    }
                    technologyReport.setTechnologyContents(technologyContents);
                    technologyReports.add(technologyReport);
                }
            }

        }
        TechnologyList technologyList = new TechnologyList();
        technologyList.setDes(null);
        technologyList.setTechnologyReports(technologyReports);
        assessmentReport.setTechnologyList(technologyList);
        //额外申请
        assessmentReport.setApply(reform.getApply());

        //难度数据填写
        DifficultyAssessment difficultyAssessment = new DifficultyAssessment();
        //系统部署架构难度,reform中获取
        FrameDifficulty frameDifficulty = new FrameDifficulty();
        frameDifficulty.setDetails(inspect.getFramework());
        SystemStructure systemStructure = reform.getSystemStructure();
        frameDifficulty.setDisaster(systemStructure.getDisaster());
        frameDifficulty.setDistributed(systemStructure.getDistributed());
        frameDifficulty.setLoadBalance(systemStructure.getLoadBalance());
        frameDifficulty.setOtherDemand(systemStructure.getOtherDemand());
        difficultyAssessment.setFrameDifficulty(frameDifficulty);
        //浏览器难度
        BrowserDifficulty browserDifficulty = new BrowserDifficulty();
        browserDifficulty.setApi(api);
        browserDifficulty.setStyle(css);
        browserDifficulty.setPlugInUnit(plugIn);
        Browser browser = reform.getBrowser();
        browserDifficulty.setOtherDemand(browser.getOtherDemand());
        browserDifficulty.setGeography(browser.getGeography());
        browserDifficulty.setPeripheral(browser.getPeripheral());
        browserDifficulty.setAnimation(browser.getAnimation());
        browserDifficulty.setThreeD(browser.getThreeD());
        browserDifficulty.setDocument(browser.getDocument());
        browserDifficulty.setMedia(browser.getMedia());
        browserDifficulty.setFlash(browser.getFlash());
        System.out.println("BrowserDifficulty:" + JSON.toJSONString(browserDifficulty));
        difficultyAssessment.setBrowserDifficulty(browserDifficulty);
        //中间件难度
        MiddlewareDifficulty middlewareDifficulty = new MiddlewareDifficulty();
        middlewareDifficulty.setNumber(number);
        middlewareDifficulty.setDependOnNum(inspect.getSupportSize());
        Middleware middleware = reform.getMiddleware();
        middlewareDifficulty.setWeb(middleware.getWeb());
        middlewareDifficulty.setJms(middleware.getJms());
        middlewareDifficulty.setJndi(middleware.getJndi());
        middlewareDifficulty.setRoute(middleware.getRoute());
        System.out.println("middlewareDifficulty" + JSON.toJSONString(middlewareDifficulty));
        difficultyAssessment.setMiddlewareDifficulty(middlewareDifficulty);
        //数据库难度
        DatabaseDifficulty databaseDifficulty = new DatabaseDifficulty();
        Database database = reform.getDatabase();
        databaseDifficulty.setDisasterTolerance(database.getDisasterTolerance());
        databaseDifficulty.setSafe(database.getSafe());
        databaseDifficulty.setSeparate(database.getSeparate());
        databaseDifficulty.setPerformance(database.getPerformance());
        databaseDifficulty.setOtherContent(database.getOtherContent());
        difficultyAssessment.setDatabaseDifficulty(databaseDifficulty);
        //本地程序难度
        ProgramDifficulty programDifficulty = new ProgramDifficulty();
        List<DependOnNum> dependOns = new ArrayList<>();
        DependOnNum dependOnNum2 = new DependOnNum("jni", jni);
        dependOns.add(dependOnNum2);
        programDifficulty.setDependOnNum(dependOns);
        difficultyAssessment.setProgramDifficulty(programDifficulty);
        System.out.println("programDifficulty+:" + JSON.toJSONString(programDifficulty));
        assessmentReport.setDifficultyAssessment(difficultyAssessment);
        WorkLoadUtil workLoadUtil = new WorkLoadUtil();
        //造价估算
        //r:人工费
        //计算f
        Budget budget = inspect.getBudgets().getBudget().get(0);
        double f = budget.getProportion() * budget.getSysFund() * budget.getMoneyRate() * budget.getCoefficient();
        System.out.println("F:" + f);
        workLoadUtil.result(reform, assessmentReport, f, 1.5);

        //输出参数
        assessmentReport.setLocalContact(reform.getLocalContact());

        String out = JSON.toJSONString(assessmentReport);
        evaluation.setOutEva(out);
        evaluation.setUsername(reform.getUsername());
        evaluation.setProjectName(reform.getProjectName());
        evaluation.setAuthority(reform.getAuthority());
        evaluation.setDel(0);
        MasterEvaluation save = evaluationService.save(evaluation);
        if(save==null){
            return ServerResponse.badRequest();
        }
        MasterEvaReport evaReport=new MasterEvaReport();
        BeanUtils.copyProperties(save,evaReport);
        evaReport.setEva_id(save.getId());
        BudegReport budegReport=new BudegReport();
        budegReport.setEvaId(save.getId());
        budegReport.setBudReport(JSON.toJSONString(inspect));
        budegReportDao.save(budegReport);
        evaReportService.save(evaReport);

        return ServerResponse.ok(save.getId());
    }

    @ApiOperation("大文件分片上传")
//    @PostMapping("/chunkUpload")
    @PostMapping("/uploads")
    public ServerResponse fileChunkUpload(MultipartFileParam param, HttpServletRequest request, HttpServletResponse response){
//        OSSInformation ossInformation = ossInformationService.queryOne();
//        String root = ossInformation.getRoot();
        String root = uploadPath;
        //验证文件夹规则,不能包含特殊字符
        java.io.File file = new java.io.File(root);
//        createDirectoryQuietly(file);
        System.out.println("88888888888888");

        String path=file.getAbsolutePath();
        response.setContentType("text/html;charset=UTF-8");
        // response.setStatus对接前端插件
        //        200, 201, 202: 当前块上传成功，不需要重传。
        //        404, 415. 500, 501: 当前块上传失败，会取消整个文件上传。
        //        其他状态码: 出错了，但是会自动重试上传。

        try {
            /**
             * 判断前端Form表单格式是否支持文件上传
             */
            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
            if(!isMultipart){
                //这里是我向前端发送数据的代码，可理解为 return 数据; 具体的就不贴了
                System.out.println("不支持的表单格式");
                return ServerResponse.badRequest();
            }else {
                param.setTaskId(param.getIdentifier());
                File myfile = inspectService.chunkUploadByMappedByteBuffer(param,path);//service层
                if (myfile!=null){
                    String name = myfile.getName();
                    String myPath = myfile.getCanonicalPath();
                    return ServerResponse.ok(new com.zjty.inspect.entity.File(name, myPath));
                }else {
                    return ServerResponse.ok("继续断点传续！");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("上传文件失败");
//            response.setStatus(415);
            return ServerResponse.error(415, "上传文件失败");
        }
    }

    @PostMapping("/gitdownload")
    private ServerResponse gitDownloads(String gitAddress, String username, String password) {
        try {
            String gitPath = GitLabUtil.downLoadProject(gitAddress, username, password);
            return ServerResponse.ok(gitPath);
        } catch (Exception e) {
            return ServerResponse.badRequest();
        }
    }

    @PostMapping("/importExcelToRapidAssessment")
    private ServerResponse<Reform> uploadFileToInspect(MultipartFile file, String username) throws IOException {
        Reform reform = ExcelUtil.parseExcel(file.getInputStream(),file.getOriginalFilename());
        Integer cost = reform.getCost();
        int x=cost;
        if(cost<100){
            int sub = BigDecimalUtil.sub(100, cost);
            int divi = BigDecimalUtil.divi(sub, 10);
            x = BigDecimalUtil.sub(100, divi);


        }else if(cost>500){
            int sub = BigDecimalUtil.sub( cost,500);
            int divi = BigDecimalUtil.divi(sub, 10);
            x = BigDecimalUtil.add(500, divi);
        }
        reform.setCost(x);
        reform.setUsername(username);
        return ServerResponse.ok(reform);
    }
}
