package org.jeecg.modules.adweb.dmp.service.google;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.io.Resources;

import jakarta.annotation.PostConstruct;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.jeecg.common.util.FastJsonUtil;
import org.jeecg.modules.adweb.common.util.RestTemplateUtil;
import org.jeecg.modules.adweb.dmp.dto.OpenAPIRequest;
import org.jeecg.modules.adweb.dmp.dto.OpenAPIResponse;
import org.jeecg.modules.adweb.dmp.dto.google.analytics.CreatePropertyRequestDTO;
import org.jeecg.modules.adweb.dmp.dto.google.analytics.GAAccountDTO;
import org.jeecg.modules.adweb.dmp.dto.google.analytics.GAPropertyDTO;
import org.jeecg.modules.adweb.dmp.dto.google.gtm.CreateContainerRequestDTO;
import org.jeecg.modules.adweb.dmp.dto.google.gtm.GTMAccountDTO;
import org.jeecg.modules.adweb.dmp.dto.google.gtm.GTMContainerDTO;
import org.jeecg.modules.adweb.dmp.entity.GoogleGTM;
import org.jeecg.modules.adweb.dmp.service.IGoogleGTMService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * Google Tag Manager + Google Analytics帐号及标签管理
 *
 * <p>http://data-bridge.v3.adwebcloud.com:9002/swagger-ui/index.html
 *
 * @author wfansh
 */
@Slf4j
@Service
public class GTMAdminService {

    private static final String GA_CREATE_PROPERTY_API_PATH = "/api/google/ga/properties/create";
    private static final String GA_DELETE_PROPERTY_API_PATH = "/api/google/ga/properties/delete";
    private static final String GTM_CREATE_CONTAINER_API_PATH = "/api/google/gtm/containers/create";
    private static final String GTM_DELETE_CONTAINER_API_PATH = "/api/google/gtm/containers/delete";

    @Value("${data-bridge.api.host}")
    private String dataBridgeApiHost;

    @Value("${data-bridge.api.token}")
    private String dataBridgeApiToken;

    @Value("${data-bridge.gtm.account-id}")
    private String gtmAccountId;

    @Value("${data-bridge.ga.account-id}")
    private String gaAccountId;

    @Autowired private IGoogleGTMService googleGTMService;

    private RestTemplate restTemplate;

    private String headSnippetTemplate;

    private String bodySnippetTemplate;

    @PostConstruct
    private void init() throws IOException {
        this.restTemplate = RestTemplateUtil.getRestTemplate(60, 60, dataBridgeApiToken);

        headSnippetTemplate =
                Resources.toString(
                        this.getClass()
                                .getClassLoader()
                                .getResource("google/gtm/head-snippet.tmpl"),
                        StandardCharsets.UTF_8);
        bodySnippetTemplate =
                Resources.toString(
                        this.getClass()
                                .getClassLoader()
                                .getResource("google/gtm/body-snippet.tmpl"),
                        StandardCharsets.UTF_8);
    }

    /**
     *
     * <li>1. 创建GTM container + GA property
     * <li>2. 更新{@link GoogleGTM}表
     */
    public GoogleGTM createContainer(String siteCode, String siteUrl, String siteName) {
        List<GoogleGTM> googleGTMs =
                googleGTMService.list(
                        new LambdaQueryWrapper<GoogleGTM>().eq(GoogleGTM::getSiteCode, siteCode));
        if (CollectionUtils.isNotEmpty(googleGTMs)) {
            log.info("站点 {} 对应的GoogleGTM已存在，ID = {}", siteCode, googleGTMs.get(0).getId());
            return googleGTMs.get(0);
        }

        // 1. 创建GA property - 通过data-bridge API
        OpenAPIRequest<CreatePropertyRequestDTO> createGAPropertyRequest = new OpenAPIRequest<>();
        createGAPropertyRequest.setRequestServer(this.getClass().getSimpleName());
        createGAPropertyRequest.setRequestTime(System.currentTimeMillis());
        createGAPropertyRequest.setData(
                CreatePropertyRequestDTO.builder()
                        .accountResourceName(GAAccountDTO.toResourceName(gaAccountId))
                        .displayName(siteName)
                        .url(siteUrl)
                        .build());
        GAPropertyDTO gaProperty =
                RestTemplateUtil.postForObject(
                                restTemplate,
                                dataBridgeApiHost + GA_CREATE_PROPERTY_API_PATH,
                                createGAPropertyRequest,
                                new ParameterizedTypeReference<OpenAPIResponse<GAPropertyDTO>>() {})
                        .getData();
        log.info("为站点 {} 创建GA property: {}", siteCode, FastJsonUtil.toJSONString(gaProperty));

        // 2. 创建GTM container - 通过data-bridge API
        OpenAPIRequest<CreateContainerRequestDTO> createGTMContainerRequest =
                new OpenAPIRequest<>();
        createGTMContainerRequest.setRequestServer(this.getClass().getSimpleName());
        createGTMContainerRequest.setRequestTime(System.currentTimeMillis());
        createGTMContainerRequest.setData(
                CreateContainerRequestDTO.builder()
                        .accountResourceName(GTMAccountDTO.toResourceName(gtmAccountId))
                        .displayName(siteName)
                        .googleTagId(gaProperty.getDataStreams().get(0).getStreamMeasurementId())
                        .build());
        GTMContainerDTO gtmContainer =
                RestTemplateUtil.postForObject(
                                restTemplate,
                                dataBridgeApiHost + GTM_CREATE_CONTAINER_API_PATH,
                                createGTMContainerRequest,
                                new ParameterizedTypeReference<
                                        OpenAPIResponse<GTMContainerDTO>>() {})
                        .getData();
        log.info("为站点 {} 创建GTM container: {}", siteCode, FastJsonUtil.toJSONString(gtmContainer));

        // 3. 更新数据库
        GoogleGTM googleGTM = new GoogleGTM();
        googleGTM.setSiteCode(siteCode);
        googleGTM.setUid(null); // TODO
        googleGTM.setGtmAccountId(gtmAccountId);
        googleGTM.setGtmContainerId(gtmContainer.getId());
        googleGTM.setGtmTagId(gtmContainer.getPublicId());
        googleGTM.setGaAccountId(gaAccountId);
        googleGTM.setGaPropertyId(gaProperty.getId());
        googleGTM.setGaVersion("V4"); // GA4 https://support.google.com/analytics/answer/10089681
        googleGTM.setGaSiteUrl(siteUrl);
        googleGTM.setGaTagId(gaProperty.getDataStreams().get(0).getStreamMeasurementId());
        googleGTMService.save(googleGTM);

        return googleGTM;
    }

    /**
     * 返回GTM container的head + body snippet代码
     *
     * @param gtmTagId
     * @return
     */
    public Pair<String, String> getSnippets(String gtmTagId) {
        return Pair.of(
                String.format(headSnippetTemplate, gtmTagId),
                String.format(bodySnippetTemplate, gtmTagId));
    }

    /**
     * 测试专用 - 删除相关资源
     * <li>1. 删除GTM container + GA property
     * <li>2. 删除{@link GoogleGTM}表
     */
    @VisibleForTesting
    boolean deleteContainer(String siteCode) {
        List<GoogleGTM> googleGTMs =
                googleGTMService.list(
                        new LambdaQueryWrapper<GoogleGTM>().eq(GoogleGTM::getSiteCode, siteCode));
        if (CollectionUtils.isEmpty(googleGTMs)) {
            log.info("站点 {} 对应的GoogleGTM不存在", siteCode);
            return false;
        }

        GoogleGTM googleGTM = googleGTMs.get(0);

        // 1. 删除GA property - 通过data-bridge API
        OpenAPIRequest<String> deleteGAPropertyRequest = new OpenAPIRequest<>();
        deleteGAPropertyRequest.setRequestServer(this.getClass().getSimpleName());
        deleteGAPropertyRequest.setRequestTime(System.currentTimeMillis());
        deleteGAPropertyRequest.setData(GAPropertyDTO.toResourceName(googleGTM.getGaPropertyId()));
        String gaPropertyResourceName =
                RestTemplateUtil.postForObject(
                                restTemplate,
                                dataBridgeApiHost + GA_DELETE_PROPERTY_API_PATH,
                                deleteGAPropertyRequest,
                                new ParameterizedTypeReference<OpenAPIResponse<String>>() {})
                        .getData();
        log.info("为站点 {} 删除GA property: {}", siteCode, gaPropertyResourceName);

        // 2. 删除GTM container - 通过data-bridge API
        OpenAPIRequest<String> deleteGTMContainerRequest = new OpenAPIRequest<>();
        deleteGTMContainerRequest.setRequestServer(this.getClass().getSimpleName());
        deleteGTMContainerRequest.setRequestTime(System.currentTimeMillis());
        deleteGTMContainerRequest.setData(
                GTMContainerDTO.toResourceName(
                        googleGTM.getGtmAccountId(), googleGTM.getGtmContainerId()));
        String gtmContainerResourceName =
                RestTemplateUtil.postForObject(
                                restTemplate,
                                dataBridgeApiHost + GTM_DELETE_CONTAINER_API_PATH,
                                deleteGTMContainerRequest,
                                new ParameterizedTypeReference<OpenAPIResponse<String>>() {})
                        .getData();
        log.info("为站点 {} 删除GTM container: {}", siteCode, gtmContainerResourceName);

        // 3. 更新数据库
        googleGTMService.removeById(googleGTM.getId());

        return true;
    }
}
