/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.eventmesh.dashboard.service.meta;

import static org.apache.eventmesh.dashboard.enums.Status.NACOS_EMPTY_RESP_ERR;
import static org.apache.eventmesh.dashboard.enums.Status.NACOS_GET_CONFIGS_ERR;
import static org.apache.eventmesh.dashboard.enums.Status.NACOS_LOGIN_EMPTY_RESP_ERR;
import static org.apache.eventmesh.dashboard.enums.Status.NACOS_LOGIN_ERR;
import static org.apache.eventmesh.dashboard.enums.Status.NACOS_SDK_CONFIG_ERR;

import org.apache.eventmesh.dashboard.config.AdminProperties;
import org.apache.eventmesh.dashboard.constant.ConfigConst;
import org.apache.eventmesh.dashboard.constant.NacosConst;
import org.apache.eventmesh.dashboard.dto.Result;
import org.apache.eventmesh.dashboard.exception.EventMeshAdminException;
import org.apache.eventmesh.dashboard.exception.MetaException;
import org.apache.eventmesh.dashboard.model.SubscriptionInfo;
import org.apache.eventmesh.dashboard.service.SubscriptionService;

import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class NacosSubscriptionService implements SubscriptionService {

    AdminProperties adminProperties;

    Properties nacosProps = new Properties();

    RestTemplate restTemplate = new RestTemplate();

    private static String HTTP_PREFIX = ConfigConst.HTTP_PREFIX;

    public NacosSubscriptionService(AdminProperties adminProperties) {
        this.adminProperties = adminProperties;

        nacosProps.setProperty(PropertyKeyConst.SERVER_ADDR, adminProperties.getMeta().getNacos().getAddr());
        nacosProps.setProperty(PropertyKeyConst.NAMESPACE, adminProperties.getMeta().getNacos().getNamespace());
        if (adminProperties.getMeta().getNacos().isAuthEnabled()) {
            if (!adminProperties.getMeta().getNacos().getUsername().isEmpty()) {
                nacosProps.setProperty(PropertyKeyConst.USERNAME, adminProperties.getMeta().getNacos().getUsername());
            }
            if (!adminProperties.getMeta().getNacos().getPassword().isEmpty()) {
                nacosProps.setProperty(PropertyKeyConst.PASSWORD, adminProperties.getMeta().getNacos().getPassword());
            }
            if (!adminProperties.getMeta().getNacos().getAccessKey().isEmpty()) {
                nacosProps.setProperty(PropertyKeyConst.ACCESS_KEY, adminProperties.getMeta().getNacos().getAccessKey());
            }
            if (!adminProperties.getMeta().getNacos().getSecretKey().isEmpty()) {
                nacosProps.setProperty(PropertyKeyConst.SECRET_KEY, adminProperties.getMeta().getNacos().getSecretKey());
            }
        }
        if (adminProperties.getMeta().getNacos().getProtocol().equalsIgnoreCase("https")) {
            HTTP_PREFIX = ConfigConst.HTTPS_PREFIX;
        }
    }

    /**
     * Retrieve a specified config with Nacos SDK.
     */
    @Override
    public String retrieveConfig(String dataId, String group) {
        ConfigService configService;
        try {
            configService = NacosFactory.createConfigService(nacosProps);
        } catch (Exception e) {
            log.error(NACOS_SDK_CONFIG_ERR.getDesc(), e);
            throw new EventMeshAdminException(NACOS_SDK_CONFIG_ERR, e);
        }
        try {
            return configService.getConfig(dataId, group, adminProperties.getMeta().getTimeoutMs());
        } catch (Exception e) {
            log.error(NACOS_GET_CONFIGS_ERR.getDesc(), e);
            throw new MetaException(NACOS_GET_CONFIGS_ERR, e);
        }
    }

    /**
     * Retrieve a list of configs with Nacos OpenAPI, because Nacos SDK doesn't support listing and fuzzy matching.
     *
     * TODO Granularity should be based on subscriptions rather than Runtime;
     * retrieve all subscriptions for each Runtime, rather than retrieving subscriptions for each individual Runtime.
     */
    @Override
    public Result<List<SubscriptionInfo>> retrieveConfigs(Integer page, Integer size, String dataId, String group) {
        UriComponentsBuilder urlBuilder = UriComponentsBuilder
            .fromHttpUrl(HTTP_PREFIX + nacosProps.getProperty(PropertyKeyConst.SERVER_ADDR) + NacosConst.CONFIGS_API)
            .queryParam(NacosConst.CONFIGS_REQ_PAGE, page)
            .queryParam(NacosConst.CONFIGS_REQ_PAGE_SIZE, size)
            .queryParam(NacosConst.CONFIGS_REQ_DATAID, dataId)
            .queryParam(NacosConst.CONFIGS_REQ_GROUP, group)
            .queryParam(NacosConst.CONFIGS_REQ_SEARCH, "blur");

        if (adminProperties.getMeta().getNacos().isAuthEnabled()) {
            urlBuilder.queryParam(NacosConst.CONFIGS_REQ_TOKEN, loginGetAccessToken());
        }

        ResponseEntity<String> response;
        try {
            response = restTemplate.getForEntity(urlBuilder.toUriString(), String.class);
        } catch (Exception e) {
            log.error(NACOS_GET_CONFIGS_ERR.getDesc(), e);
            throw new MetaException(NACOS_GET_CONFIGS_ERR, e);
        }
        if (response.getBody() == null || response.getBody().isEmpty()) {
            log.error(NACOS_EMPTY_RESP_ERR.getDesc());
            throw new MetaException(NACOS_EMPTY_RESP_ERR);
        }

        JSONObject obj = JSON.parseObject(response.getBody());
        return new Result<>(toSubscriptionInfos(obj), obj.getInteger(NacosConst.CONFIGS_RESP_PAGES));
    }

    private List<SubscriptionInfo> toSubscriptionInfos(JSONObject obj) {
        List<SubscriptionInfo> subscriptionInfos = new ArrayList<>();
        for (Object pageItem : obj.getJSONArray(NacosConst.CONFIGS_RESP_CONTENT_LIST)) {
            JSONObject pageItemObj = (JSONObject) pageItem;
            subscriptionInfos.add(toSubscriptionInfo(pageItemObj));
        }
        return subscriptionInfos;
    }

    private SubscriptionInfo toSubscriptionInfo(JSONObject obj) {
        String content = obj.getString(NacosConst.CONFIGS_RESP_CONTENT);
        return SubscriptionInfo.builder()
            .clientName(obj.getString(NacosConst.CONFIGS_RESP_DATAID))
            .group(obj.getString(NacosConst.CONFIGS_RESP_GROUP))
            // The subscription content of Nacos config should be base64 encoded to protect special characters.
            .subscription(Base64.getEncoder().encodeToString(content.getBytes()))
            .build();
    }

    /**
     * Login if auth enabled and return accessToken.
     */
    private String loginGetAccessToken() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, String> bodyParams = new LinkedMultiValueMap<>();
        bodyParams.put(NacosConst.LOGIN_REQ_USERNAME, Collections.singletonList(nacosProps.getProperty(PropertyKeyConst.USERNAME)));
        bodyParams.put(NacosConst.LOGIN_REQ_PASSWORD, Collections.singletonList(nacosProps.getProperty(PropertyKeyConst.PASSWORD)));

        String loginUrl = HTTP_PREFIX + nacosProps.getProperty(PropertyKeyConst.SERVER_ADDR) + NacosConst.LOGIN_API;
        HttpEntity<MultiValueMap<String, String>> loginRequest = new HttpEntity<>(bodyParams, headers);
        ResponseEntity<String> loginResponse;
        try {
            loginResponse = restTemplate.postForEntity(loginUrl, loginRequest, String.class);
        } catch (Exception e) {
            log.error(NACOS_LOGIN_ERR.getDesc(), e);
            throw new MetaException(NACOS_LOGIN_ERR, e);
        }
        if (loginResponse.getBody() == null || loginResponse.getBody().isEmpty()) {
            log.error(NACOS_LOGIN_EMPTY_RESP_ERR + " Status code: {}", loginResponse.getStatusCode());
            throw new MetaException(NACOS_LOGIN_EMPTY_RESP_ERR + " Status code: " + loginResponse.getStatusCode());
        }
        return JSON.parseObject(loginResponse.getBody()).getString(NacosConst.LOGIN_RESP_TOKEN);
    }
}
