package cn.reghao.autodop.dmaster.machine.controller;

import cn.reghao.autodop.dmaster.app.model.constant.EnvList;
import cn.reghao.autodop.dmaster.app.model.vo.KeyValue;
import cn.reghao.autodop.dmaster.machine.db.crud.MachineInfoCrud;
import cn.reghao.autodop.dmaster.machine.db.query.MachineHostQuery;
import cn.reghao.autodop.dmaster.machine.db.query.MachineInfoQuery;
import cn.reghao.autodop.dmaster.machine.db.query.MachineStatQuery;
import cn.reghao.autodop.dmaster.machine.model.SshConnData;
import cn.reghao.autodop.dmaster.machine.model.po.MachineHost;
import cn.reghao.autodop.dmaster.machine.model.po.MachineStat;
import cn.reghao.autodop.dmaster.machine.model.po.SshAuth;
import cn.reghao.autodop.dmaster.machine.model.po.MachineInfo;
import cn.reghao.autodop.dmaster.machine.service.ssh.Keys;
import cn.reghao.autodop.dmaster.notification.model.po.NotifyGroup;
import cn.reghao.autodop.dmaster.notification.db.repository.NotifyGroupRepository;
import cn.reghao.autodop.dmaster.util.db.PageList;
import cn.reghao.autodop.dmaster.util.db.PageSort;
import cn.reghao.jdkutil.converter.DateTimeConverter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2019-08-30 18:49:15
 */
@Slf4j
@Api(tags = "机器模块页面")
@Controller
@RequestMapping("/machine")
public class MachinePageController {
    private MachineInfoCrud infoCrud;
    private MachineInfoQuery infoQuery;
    private MachineHostQuery hostQuery;
    private MachineStatQuery statQuery;
    private NotifyGroupRepository receiverRepository;

    public MachinePageController(MachineInfoCrud infoCrud, MachineInfoQuery infoQuery,
                                 MachineHostQuery hostQuery, MachineStatQuery statQuery,
                                 NotifyGroupRepository receiverRepository) {
        this.infoCrud = infoCrud;
        this.infoQuery = infoQuery;
        this.hostQuery = hostQuery;
        this.statQuery = statQuery;
        this.receiverRepository = receiverRepository;
    }

    @ApiOperation(value = "机器节点页面")
    @GetMapping("/host")
    public String hostPage(@RequestParam(value = "env", required = false) String env,
                           @RequestParam(value = "machineIpv4", required = false) String machineIpv4,
                           Model model) {
        if (env == null) {
            env = EnvList.test.name();
        }

        if (machineIpv4 != null) {
            searchByMachineIpv4(env, machineIpv4, model);
            return "/machine/host";
        }

        PageRequest pageRequest = PageSort.pageRequest();
        Page<MachineHost> page = hostQuery.findByEnv(env, pageRequest);
        PageList<MachineHost> pageList = PageList.pageList(page);

        model.addAttribute("env", env);
        model.addAttribute("page", page);
        model.addAttribute("list", pageList.getList());
        return "/machine/host";
    }

    private void searchByMachineIpv4(String env, String machineIpv4, Model model) {
        MachineHost machineHost = hostQuery.findByMachineIpv4(machineIpv4);
        List<MachineHost> list = new ArrayList<>();
        list.add(machineHost);
        Page<MachineHost> page = new PageImpl<>(list);
        PageList<MachineHost> pageList = PageList.pageList(page);

        model.addAttribute("env", env);
        model.addAttribute("page", page);
        model.addAttribute("list", pageList.getList());
    }

    @ApiOperation(value = "机器通知设置页面")
    @GetMapping("/notify/{machineId}")
    public String machineNotifyPage(@PathVariable("machineId") String machineId, Model model) {
        MachineHost machineHost = hostQuery.findByMachineId(machineId);
        Set<NotifyGroup> currentSet = new HashSet<>(machineHost.getNotifyGroups());
        List<NotifyGroup> list = receiverRepository.findAll();

        model.addAttribute("machineId", machineId);
        model.addAttribute("currentSet", currentSet);
        model.addAttribute("list", list);
        return "/machine/machinenotify";
    }

    @ApiOperation(value = "SSH 认证设置页面")
    @GetMapping("/sshauth/{machineId}")
    public String sshAuthPage(@PathVariable("machineId") String machineId, Model model) {
        MachineHost machineHost = hostQuery.findByMachineId(machineId);
        SshAuth sshAuth = machineHost.getSshAuth();

        model.addAttribute("machineId", machineId);
        model.addAttribute("sshAuth", sshAuth);
        return "/machine/sshauth";
    }

    @ApiOperation(value = "SSH 控制台页面")
    @GetMapping("/webssh/{machineId}")
    public String webSshPage(@PathVariable("machineId") String machineId, Model model) {
        MachineHost machineHost = hostQuery.findByMachineId(machineId);
        String machineIpv4 = machineHost.getMachineIpv4();
        SshAuth sshAuth = machineHost.getSshAuth();
        if (sshAuth == null) {
            return "先设置 SSH 认证";
        }

        SshConnData sshConnData = new SshConnData();
        sshConnData.setOps(Keys.OPS_CONNECT);
        sshConnData.setHost(machineIpv4);
        sshConnData.setPort(sshAuth.getPort());
        sshConnData.setUsername(sshAuth.getUsername());
        sshConnData.setPassword(sshAuth.getPassword());

        model.addAttribute("sshConnData", sshConnData);
        return "/machine/webssh";
    }

    @ApiOperation(value = "机器额外信息编辑页面")
    @GetMapping("/host/edit/{machineId}")
    public String hostEditPage(@PathVariable("machineId") String machineId, Model model) {
        List<KeyValue> envs = new ArrayList<>();
        for (EnvList envList : EnvList.values()) {
            envs.add(new KeyValue(envList.name(), envList.name()));
        }

        MachineHost machineHost = hostQuery.findByMachineId(machineId);
        model.addAttribute("machineId", machineId);
        model.addAttribute("environments", envs);
        model.addAttribute("env", machineHost.getEnv());
        return "/machine/edit";
    }

    @ApiOperation(value = "机器信息详情页面")
    @GetMapping("/host/detail/{machineId}")
    public String hostDetailPage(@PathVariable("machineId") String machineId, Model model) {
        MachineInfo machineInfo = infoQuery.findByMachineId(machineId);
        model.addAttribute("machine", machineInfo);
        return "/machine/detail";
    }

    @ApiOperation(value = "机器状态列表页面")
    @GetMapping("/status")
    public String statusPage(@RequestParam(value = "env", required = false) String env,
                             @RequestParam(value = "machineIpv4", required = false) String machineIpv4,
                             Model model) {
        if (env == null) {
            env = EnvList.test.name();
        }

        if (machineIpv4 != null) {
            searchByMachineIpv4(env, machineIpv4, model);
            return "/machine/status";
        }

        PageRequest pageRequest = PageSort.pageRequest();
        Page<MachineHost> page = hostQuery.findByEnv(env, pageRequest);
        PageList<MachineHost> pageList = PageList.pageList(page);

        model.addAttribute("env", env);
        model.addAttribute("page", page);
        model.addAttribute("list", pageList.getList());
        return "/machine/status";
    }

    @ApiOperation(value = "系统负载页面")
    @GetMapping("/status/sys/{machineId}")
    public String hostStatusPage(@PathVariable("machineId") String machineId, Model model) {
        /*MachineStat machineStat = statQuery.queryByMachineId(machineId, 1).get(0);
        LocalDateTime statTime = DateTimeConverter.localDateTime(machineStat.getTimestamp());

        model.addAttribute("statTime", DateTimeConverter.format(statTime));
        model.addAttribute("sysload", machineStat.getOsStat());*/
        return "/machine/stat/sysload";
    }

    @ApiOperation(value = "网络状态页面")
    @GetMapping("/status/network/{machineId}")
    public String networkStatusPage(@PathVariable("machineId") String machineId, Model model) {
        /*MachineStat machineStat = statQuery.queryByMachineId(machineId, 1).get(0);
        LocalDateTime statTime = DateTimeConverter.localDateTime(machineStat.getTimestamp());

        model.addAttribute("statTime", DateTimeConverter.format(statTime));
        model.addAttribute("tcpConnNum", machineStat.getTcpConnNum());
        model.addAttribute("networkStat", machineStat.getNetworkStat());*/
        return "/machine/stat/network";
    }

    @ApiOperation(value = "CPU 使用率页面")
    @GetMapping("/status/cpu/{machineId}")
    public String cpuUsagePage(@PathVariable("machineId") String machineId, Model model) {
        /*MachineStat machineStat = statQuery.queryByMachineId(machineId, 1).get(0);
        LocalDateTime statTime = DateTimeConverter.localDateTime(machineStat.getTimestamp());

        model.addAttribute("statTime", DateTimeConverter.format(statTime));
        model.addAttribute("cpuUsage", machineStat.getCpuStat());*/
        return "/machine/stat/cpu";
    }

    @ApiOperation(value = "内存详情页面")
    @GetMapping("/status/mem/{machineId}")
    public String memUsagePage(@PathVariable("machineId") String machineId, Model model) {
        /*MachineStat machineStat = statQuery.queryByMachineId(machineId, 1).get(0);
        LocalDateTime statTime = DateTimeConverter.localDateTime(machineStat.getTimestamp());

        model.addAttribute("statTime", DateTimeConverter.format(statTime));
        model.addAttribute("memoryUsage", machineStat.getMemoryUsage());*/
        return "/machine/stat/mem";
    }

    @ApiOperation(value = "磁盘详情页面")
    @GetMapping("/status/disk/{machineId}")
    public String diskUsagePage(@PathVariable("machineId") String machineId, Model model) {
        /*MachineStat machineStat = statQuery.queryByMachineId(machineId, 1).get(0);
        LocalDateTime statTime = DateTimeConverter.localDateTime(machineStat.getTimestamp());

        model.addAttribute("statTime", DateTimeConverter.format(statTime));
        model.addAttribute("diskUsages", machineStat.getDiskUsages());*/
        return "/machine/stat/disk";
    }
}
