package com.sf.service.gateway.controller;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import com.sf.service.gateway.domain.*;
import com.sf.service.gateway.domain.dto.QueryGatewayServerDTO;
import com.sf.service.gateway.domain.dto.QueryGatewayStrategyDTO;
import com.sf.service.gateway.domain.dto.UpdateDataStatusDTO;
import com.sf.service.gateway.domain.vo.GatewayInterfaceInfoListVO;
import com.sf.service.gateway.domain.vo.GatewayServerDetailedVO;
import com.sf.service.gateway.domain.vo.GatewayServerListVO;
import com.sf.service.gateway.domain.vo.GatewayStrategyListVO;
import com.sf.service.gateway.enums.GatewayDataStatus;
import com.sf.service.gateway.enums.GatewayServiceModel;
import com.sf.service.gateway.service.IGatewayInterfaceInfoService;
import com.sf.service.gateway.service.IGatewayRouteService;
import com.sf.service.gateway.service.IGatewayServerService;
import com.sf.service.gateway.service.IGatewayStrategyService;
import com.sf.service.index.util.AppUtils;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sf.common.annotation.Log;
import com.sf.common.core.controller.BaseController;
import com.sf.common.core.domain.AjaxResult;
import com.sf.common.enums.BusinessType;
import com.sf.common.utils.poi.ExcelUtil;
import com.sf.common.core.page.TableDataInfo;

/**
 * 服务管理Controller
 *
 * @author zoukun
 * @date 2024-04-22
 */
@RestController
@RequestMapping("/gateway/server")
public class GatewayServerController extends BaseController {
    @Autowired
    private IGatewayServerService gatewayServerService;

    @Autowired
    private IGatewayRouteService gatewayRouteService;

    @Autowired
    private IGatewayInterfaceInfoService gatewayInterfaceInfoService;

    @Autowired
    private IGatewayStrategyService gatewayStrategyService;

    /**
     * 查询服务管理列表
     */
    @PreAuthorize("@ss.hasPermi('gateway:server:list')")
    @GetMapping("/list")
    public TableDataInfo list(GatewayServer gatewayServer) {
        gatewayServer.setAppCode(AppUtils.getAppCodeFromRequestHeader());
        startPage();
        List<GatewayServer> list = gatewayServerService.selectGatewayServerList(gatewayServer);
        // 如果是路由模式的服务，查询对应的路由服务信息
        Collection<Long> routeIds = list.stream().filter(item -> GatewayServiceModel.ROUTE.getCode().equals(item.getServiceModel()))
                .map(GatewayServer::getRouteId)
                .collect(Collectors.toSet());
        List<GatewayRoute> routeList = gatewayRouteService.selectGatewayRouteByIds(routeIds);
        Map<Long, String> routeIdAndNameMap = routeList.stream().collect(Collectors.toMap(GatewayRoute::getId, GatewayRoute::getRouteName));
        List<GatewayServerListVO> voList = list.stream().map(item -> {
            GatewayServerListVO vo = new GatewayServerListVO();
            vo.setId(item.getId());
            vo.setServerName(item.getServerName());
            vo.setServerAddress(GatewayServiceModel.ROUTE.getCode().equals(item.getServiceModel()) ?
                    routeIdAndNameMap.get(item.getRouteId()) : item.getServerAddress());
            vo.setRemark(item.getRemark());
            vo.setStatus(item.getStatus());
            vo.setCreated(item.getCreated());
            vo.setModified(item.getModified());
            vo.setServiceModel(item.getServiceModel());
            vo.setRouteId(item.getRouteId());
            vo.setCreateTime(item.getCreateTime());
            vo.setUpdateTime(item.getUpdateTime());
            return vo;
        }).collect(Collectors.toList());
        return getDataTable(voList);
    }

    /**
     * 导出服务管理列表
     */
    @PreAuthorize("@ss.hasPermi('gateway:server:export')")
    @Log(title = "服务管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, GatewayServer gatewayServer) {
        List<GatewayServer> list = gatewayServerService.selectGatewayServerList(gatewayServer);
        ExcelUtil<GatewayServer> util = new ExcelUtil<GatewayServer>(GatewayServer.class);
        util.exportExcel(response, list, "服务管理数据");
    }

    /**
     * 获取服务管理详细信息
     */
    @PreAuthorize("@ss.hasPermi('gateway:server:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        GatewayServerDetailedVO vo = new GatewayServerDetailedVO();
        GatewayServer gatewayServer = gatewayServerService.selectGatewayServerById(id);
        List<GatewayInterfaceInfo> interfaceInfoList = gatewayInterfaceInfoService.selectGatewayInterfaceInfoByServerIds(Collections.singleton(id));
        List<GatewayInterfaceLinkStrategy> linkList = gatewayInterfaceInfoService.selectGatewayInterfaceLinkStrategyByInterfaceIds(interfaceInfoList.stream().map(GatewayInterfaceInfo::getId).collect(Collectors.toSet()));
        Map<Long, List<GatewayInterfaceLinkStrategy>> groupByInterfaceLinkMap = linkList.stream().collect(Collectors.groupingBy(GatewayInterfaceLinkStrategy::getInterfaceId));
        List<GatewayStrategy> strategyList = gatewayStrategyService.selectGatewayStrategyByIds(linkList.stream().map(GatewayInterfaceLinkStrategy::getStrategyId).collect(Collectors.toSet()));
        Map<Long, GatewayStrategy> strategyMap = strategyList.stream().collect(Collectors.toMap(GatewayStrategy::getId, Function.identity()));
        if (GatewayServiceModel.ROUTE.getCode().equals(gatewayServer.getServiceModel())){
            GatewayRoute route = gatewayRouteService.selectGatewayRouteById(gatewayServer.getRouteId());
            vo.setServerAddress(route.getRouteName());
        }else {
            vo.setServerAddress(gatewayServer.getServerAddress());
        }
        vo.setId(gatewayServer.getId());
        vo.setServerName(gatewayServer.getServerName());
        vo.setRemark(gatewayServer.getRemark());
        vo.setStatus(gatewayServer.getStatus());
        vo.setCreated(gatewayServer.getCreated());
        vo.setModified(gatewayServer.getModified());
        vo.setServiceModel(gatewayServer.getServiceModel());
        vo.setRouteId(gatewayServer.getRouteId());
        vo.setCreateTime(gatewayServer.getCreateTime());
        vo.setUpdateTime(gatewayServer.getUpdateTime());
        List<GatewayInterfaceInfoListVO> interfaceInfoListVOList = interfaceInfoList.stream().map(info -> {
            GatewayInterfaceInfoListVO interfaceInfoListVO = new GatewayInterfaceInfoListVO();
            interfaceInfoListVO.setId(info.getId());
            interfaceInfoListVO.setInterfaceName(info.getInterfaceName());
            interfaceInfoListVO.setInterfacePath(info.getInterfacePath());
            interfaceInfoListVO.setRequestMethod(info.getRequestMethod());
            interfaceInfoListVO.setDescription(info.getDescription());
            interfaceInfoListVO.setVersion(info.getVersion());
            interfaceInfoListVO.setStatus(info.getStatus());
            interfaceInfoListVO.setDocument(info.getDocument());
            // 策略信息
            List<GatewayInterfaceLinkStrategy> currentLinks = groupByInterfaceLinkMap.getOrDefault(info.getId(), Collections.emptyList());
            List<GatewayStrategyListVO> strategyListVOList = currentLinks.stream().map(link -> {
                        GatewayStrategy strategy = strategyMap.get(link.getStrategyId());
                        GatewayStrategyListVO strategyListVO = new GatewayStrategyListVO();
                        strategyListVO.setId(strategy.getId());
                        strategyListVO.setStrategyName(strategy.getStrategyName());
                        strategyListVO.setStrategyType(strategy.getStrategyType());
                        strategyListVO.setDescription(strategy.getDescription());
                        strategyListVO.setStatus(strategy.getStatus());
                        return strategyListVO;
                    })
                    .collect(Collectors.toList());
            interfaceInfoListVO.setStrategyList(strategyListVOList);
            return interfaceInfoListVO;
        }).collect(Collectors.toList());
        vo.setInterfaceInfoList(interfaceInfoListVOList);

        return success(vo);
    }

    /**
     * 新增服务管理
     */
    @PreAuthorize("@ss.hasPermi('gateway:server:add')")
    @Log(title = "服务管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody GatewayServer gatewayServer) {
        gatewayServer.setAppCode(AppUtils.getAppCodeFromRequestHeader());
        String username = getUsername();
        gatewayServer.setCreated(username);
        gatewayServer.setModified(username);
        return toAjax(gatewayServerService.insertGatewayServer(gatewayServer));
    }

    /**
     * 修改服务管理
     */
    @PreAuthorize("@ss.hasPermi('gateway:server:edit')")
    @Log(title = "服务管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody GatewayServer gatewayServer) {
        return toAjax(gatewayServerService.updateGatewayServer(gatewayServer));
    }

    /**
     * 删除服务管理
     */
    @PreAuthorize("@ss.hasPermi('gateway:server:remove')")
    @Log(title = "服务管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(gatewayServerService.deleteGatewayServerByIds(ids));
    }

    @ApiOperation("启用/停用网关服务")
    @Log(title = "启用/停用网关服务", businessType = BusinessType.UPDATE)
    @PutMapping("/status")
    public AjaxResult updateStatus(@Validated @RequestBody UpdateDataStatusDTO dto) {
        return toAjax(gatewayServerService.updateGatewayServerStatusByIds(dto.getIds(), GatewayDataStatus.getByCode(dto.getStatus())));
    }

    /**
     * 查询可绑定的策略列表（状态为启用的,不分页）
     */
    @GetMapping("/bindableList")
    public List<GatewayServerListVO> bindableList(QueryGatewayServerDTO dto)
    {
        GatewayServer gatewayServer = new GatewayServer();
        gatewayServer.setStatus(GatewayDataStatus.ENABLE.getCode());
        gatewayServer.setServiceModel(dto.getServiceModel());
        gatewayServer.setAppCode(AppUtils.getAppCodeFromRequestHeader());
        Map<String, Object> params = new HashMap<>(8);
        params.put("ids",dto.getIds());
        params.put("excludedIds",dto.getExcludedIds());
        gatewayServer.setParams(params);
        List<GatewayServer> list = gatewayServerService.selectGatewayServerList(gatewayServer);
        // 如果是路由模式的服务，查询对应的路由服务信息
        Collection<Long> routeIds = list.stream().filter(item -> GatewayServiceModel.ROUTE.getCode().equals(item.getServiceModel()))
                .map(GatewayServer::getRouteId)
                .collect(Collectors.toSet());
        List<GatewayRoute> routeList = gatewayRouteService.selectGatewayRouteByIds(routeIds);
        Map<Long, String> routeIdAndNameMap = routeList.stream().collect(Collectors.toMap(GatewayRoute::getId, GatewayRoute::getRouteName));
        return list.stream().map(item -> {
            GatewayServerListVO vo = new GatewayServerListVO();
            vo.setId(item.getId());
            vo.setServerName(item.getServerName());
            vo.setServerAddress(GatewayServiceModel.ROUTE.getCode().equals(item.getServiceModel()) ?
                    routeIdAndNameMap.get(item.getRouteId()) : item.getServerAddress());
            vo.setStatus(item.getStatus());
            vo.setServiceModel(item.getServiceModel());
            vo.setRouteId(item.getRouteId());
            return vo;
        }).collect(Collectors.toList());
    }
}
