package cn.reghao.bnt.web.devops.app.controller;

import cn.reghao.bnt.web.devops.app.model.vo.*;
import cn.reghao.jutil.jdk.web.db.PageList;
import cn.reghao.jutil.jdk.web.result.NotAvailable;
import cn.reghao.bnt.web.devops.app.service.AppBuildService;
import cn.reghao.bnt.web.devops.app.service.bd.DeployApp;
import cn.reghao.bnt.web.devops.app.service.bd.GetApp;
import cn.reghao.bnt.web.devops.app.service.webhook.WebhookService;
import cn.reghao.bnt.web.devops.app.db.query.AppBuildQuery;
import cn.reghao.bnt.web.devops.app.db.query.AppDeployQuery;
import cn.reghao.bnt.web.devops.app.model.po.log.BuildConfigSnapshot;
import cn.reghao.bnt.web.devops.app.model.po.log.BuildConsumed;
import cn.reghao.bnt.web.devops.app.model.po.log.BuildLog;
import cn.reghao.bnt.web.devops.app.service.bd.BuildApp;
import cn.reghao.bnt.web.util.StringUtil;
import cn.reghao.jutil.jdk.web.result.Result;
import cn.reghao.jutil.web.WebResult;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author reghao
 * @date 2019-08-30 18:49:15
 */
@Slf4j
@Tag(name = "构建部署页面")
@RestController
@RequestMapping("/api/devops/app/bd")
public class BuildDeployController {
    private final AppBuildQuery appBuildQuery;
    private final AppDeployQuery appDeployQuery;
    private final BuildApp buildApp;
    private final DeployApp deployApp;
    private final GetApp getApp;
    private final AppBuildService appBuildService;
    private final WebhookService webhookService;
    private int pageSize = 10;

    public BuildDeployController(AppBuildQuery appBuildQuery, AppDeployQuery appDeployQuery, BuildApp buildApp,
                                 DeployApp deployApp, GetApp getApp, AppBuildService appBuildService,
                                 WebhookService webhookService) {
        this.appBuildQuery = appBuildQuery;
        this.appDeployQuery = appDeployQuery;
        this.buildApp = buildApp;
        this.deployApp = deployApp;
        this.getApp = getApp;
        this.appBuildService = appBuildService;
        this.webhookService = webhookService;
    }

    @Operation(summary = "应用构建页面", description = "N")
    @GetMapping(value = "/build")
    public String index(@RequestParam(value = "pn") int pageNumber,
                        @RequestParam(value = "env") String env,
                        @RequestParam(value = "appType") String appType) {
        Sort sort = Sort.by(Sort.Direction.DESC, "buildTime");
        PageRequest pageRequest = PageRequest.of(pageNumber-1, pageSize, sort);
        Page<AppBuildingVO> page = appBuildQuery.getByPage(env, appType, pageRequest);
        PageList<AppBuildingVO> pageList = getPageList(page);
        return WebResult.success(pageList);
    }

    private PageList<AppBuildingVO> getPageList(Page<AppBuildingVO> page) {
        int pageNumber = page.getNumber() + 1;
        int pageSize = page.getSize();
        long total = page.getTotalElements();
        List<AppBuildingVO> list = page.getContent();
        return PageList.pageList(pageNumber, pageSize, (int) total, list);
    }

    @Operation(summary = "构建任务页面", description = "N")
    @GetMapping(value = "/task")
    public String buildTaskPage() {
        List<BuildTask> list = buildApp.getBuildTasks();
        return WebResult.success(list);
    }

    @Operation(summary = "重置应用构建状态", description = "N")
    @PostMapping(value = "/reset", produces = MediaType.APPLICATION_JSON_VALUE)
    public String resetState() {
        appBuildService.resetBuildStat();
        return WebResult.success("构建状态已重置");
    }

    @Operation(summary = "取消构建任务", description = "N")
    @PostMapping(value = "/cancel_task", produces = MediaType.APPLICATION_JSON_VALUE)
    public String cancelTask(String appId) {
        //buildApp.cancelTask(appId);
        return WebResult.failWithMsg("接口未实现");
    }

    @Operation(summary = "应用部署页面", description = "N")
    @GetMapping("/deploy")
    public String deployPage(@RequestParam("appId") String appId) {
        List<AppDeployingNodeVO> list = appDeployQuery.get(appId);
        return WebResult.success(list);
    }

    @Operation(summary = "构建结果页面", description = "N")
    @GetMapping("/result")
    public String buildLogResultPage(@RequestParam("buildLogId") String buildLogId) {
        String content;
        if (NotAvailable.na.getDesc().equals(buildLogId)) {
            content = "构建结果暂不可用";
        } else {
            content = appBuildQuery.getBuildResult(buildLogId);
        }

        String html = StringUtil.txtToHtml(content);
        return WebResult.success(html);
    }

    @Operation(summary = "历史构建页面", description = "N")
    @GetMapping("/history")
    public String buildLogPage(@RequestParam("pn") int pageNumber, @RequestParam("appId") String appId) {
        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = PageRequest.of(pageNumber-1, pageSize, sort);
        Page<BuildLogVO> buildLogs = appBuildQuery.buildLogVOs(appId, pageRequest);
        PageList<BuildLogVO> pageList = getPageList1(buildLogs);
        return WebResult.success(pageList);
    }

    private PageList<BuildLogVO> getPageList1(Page<BuildLogVO> page) {
        int pageNumber = page.getNumber() + 1;
        int pageSize = page.getSize();
        long total = page.getTotalElements();
        List<BuildLogVO> list = page.getContent();
        return PageList.pageList(pageNumber, pageSize, (int) total, list);
    }

    @Operation(summary = "构建配置页面", description = "N")
    @GetMapping("/config")
    public String buildConfigPage(@RequestParam("buildLogId") String buildLogId) {
        BuildLog buildLog = appBuildQuery.getBuildLog(buildLogId);
        BuildConfigSnapshot buildConfigSnapshot = buildLog.getBuildConfigSnapshot();
        return WebResult.success(buildConfigSnapshot);
    }

    @Operation(summary = "构建耗时页面", description = "N")
    @GetMapping("/consumed")
    public String buildTimePage(@RequestParam("buildLogId") String buildLogId) {
        BuildLog buildLog = appBuildQuery.getBuildLog(buildLogId);
        BuildConsumed buildConsumed = buildLog.getBuildConsumed();
        return WebResult.success(buildConsumed);
    }

    @Operation(summary = "构建部署应用", description = "N")
    @PostMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE)
    public String buildAndDeploy(String appId) throws Exception {
        Result result = buildApp.buildAndDeploy(appId, true);
        return WebResult.result(result);
    }

    @Operation(summary = "构建应用", description = "N")
    @PostMapping(value = "/build", produces = MediaType.APPLICATION_JSON_VALUE)
    public String build(String appId) throws Exception {
        Result result = buildApp.buildAndDeploy(appId, false);
        return WebResult.result(result);
    }

    @Operation(summary = "部署应用", description = "N")
    @PostMapping(value = "/deploy", produces = MediaType.APPLICATION_JSON_VALUE)
    public String deploy(String buildLogId, String machineId)
            throws Exception {
        if (buildLogId == null || buildLogId.equals("null")) {
            return WebResult.failWithMsg("应用尚未构建");
        }

        deployApp.deploy(buildLogId, machineId);
        return WebResult.successWithMsg("部署请求已提交");
    }

    @Operation(summary = "构建包下载接口", description = "N")
    @GetMapping(value = "/package_url", produces = MediaType.APPLICATION_JSON_VALUE)
    public String packageUrl(@RequestParam("buildLogId") String buildLogId) throws Exception {
        /*try {
            String filename = buildLogId;
            getApp.dlPackage(filename);
        } catch (Exception e) {
            log.error(e.getMessage());
        }*/
        String packageUrl = getApp.packageUrl(buildLogId);
        return WebResult.successWithMsg(packageUrl);
    }

    @Operation(summary = "删除构建", description = "N")
    @PostMapping(value = "/delete", produces = MediaType.APPLICATION_JSON_VALUE)
    public String deleteBuild(String buildLogId) throws Exception {
        appBuildService.deleteBuildLog(buildLogId);
        return WebResult.success();
    }

    @Operation(summary = "webhook 自动构建部署", description = "N")
    @PostMapping("/hook")
    public String hook(@RequestBody String body) throws Exception {
        webhookService.handle(body);
        return WebResult.success();
    }
}
