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.lang3.tuple.Pair;
import org.jeecg.common.util.FastJsonUtil;
import org.jeecg.modules.adweb.common.databridge.OpenAPIRequest;
import org.jeecg.modules.adweb.common.databridge.OpenAPIResponse;
import org.jeecg.modules.adweb.common.util.RestTemplateUtil;
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.dto.matomo.CreateSiteRequestDTO;
import org.jeecg.modules.adweb.dmp.dto.matomo.MatomoSiteDTO;
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;
import java.util.Objects;

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

    private static final String GA_ACCOUNT_LIST_API_PATH = "/api/google/ga/accounts/list";
    private static final String GA_PROPERTY_CREATE_API_PATH = "/api/google/ga/properties/create";
    private static final String GA_PROPERTY_DELETE_API_PATH = "/api/google/ga/properties/delete";
    private static final String MATOMO_SITE_CREATE_API_PATH = "/api/matomo/sites/create";
    private static final String MATOMO_SITE_DELETE_API_PATH = "/api/matomo/sites/delete";
    private static final String GTM_CONTAINER_CREATE_API_PATH = "/api/google/gtm/containers/create";
    private static final String GTM_CONTAINER_DELETE_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-ids}")
    private List<String> gaAccountIds; // v3系统可用的GA帐号IDs

    @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, String gaAccountId) {
        GoogleGTM googleGTM =
                googleGTMService.getOne(
                        new LambdaQueryWrapper<GoogleGTM>().eq(GoogleGTM::getSiteCode, siteCode));
        // 如果GoogleGTM表中已存在，不再创建，返回现有记录
        if (Objects.nonNull(googleGTM)) {
            log.info("站点 {} 对应的GoogleGTM已存在，ID = {}", siteCode, googleGTM.getId());
            return googleGTM;
        }

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

        // 2. 创建Matomo site - 通过data-bridge API
        OpenAPIRequest<CreateSiteRequestDTO> createMatomoSiteRequest =
                this.buildOpenAPIRequest(
                        CreateSiteRequestDTO.builder().siteName(siteName).url(siteUrl).build());
        MatomoSiteDTO matomoSite =
                RestTemplateUtil.postForObject(
                                restTemplate,
                                dataBridgeApiHost + MATOMO_SITE_CREATE_API_PATH,
                                createMatomoSiteRequest,
                                new ParameterizedTypeReference<OpenAPIResponse<MatomoSiteDTO>>() {})
                        .getData();
        log.info("为站点 {} 创建Matomo site: {}", siteCode, FastJsonUtil.toJSONString(matomoSite));

        // 3. 创建GTM container - 通过data-bridge API
        OpenAPIRequest<CreateContainerRequestDTO> createGTMContainerRequest =
                this.buildOpenAPIRequest(
                        CreateContainerRequestDTO.builder()
                                .accountResourceName(GTMAccountDTO.toResourceName(gtmAccountId))
                                .displayName(siteName)
                                .gaMeasurementId(
                                        gaProperty.getDataStreams().get(0).getStreamMeasurementId())
                                .matomoSiteId(matomoSite.getSiteId())
                                .build());
        GTMContainerDTO gtmContainer =
                RestTemplateUtil.postForObject(
                                restTemplate,
                                dataBridgeApiHost + GTM_CONTAINER_CREATE_API_PATH,
                                createGTMContainerRequest,
                                new ParameterizedTypeReference<
                                        OpenAPIResponse<GTMContainerDTO>>() {})
                        .getData();
        log.info("为站点 {} 创建GTM container: {}", siteCode, FastJsonUtil.toJSONString(gtmContainer));

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

        return googleGTM;
    }

    /** 获取GA account列表，并根据v3系统配置为可用的{@link #gaAccountIds}过滤 */
    public List<GAAccountDTO> listGAAccounts() {
        // 获取GA account列表 - 通过data-bridge API
        OpenAPIRequest<?> listGAAccountsRequest = this.buildOpenAPIRequest(null);
        OpenAPIResponse<List<GAAccountDTO>> listGAAccountsResponse =
                RestTemplateUtil.postForObject(
                        restTemplate,
                        dataBridgeApiHost + GA_ACCOUNT_LIST_API_PATH,
                        listGAAccountsRequest,
                        new ParameterizedTypeReference<>() {});

        return listGAAccountsResponse.getData().stream()
                .filter(gaAccount -> gaAccountIds.contains(gaAccount.getId()))
                .toList();
    }

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

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

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

        // 2. 删除Matomo site - 通过data-bridge API
        OpenAPIRequest<String> deleteMatomoSiteRequest =
                this.buildOpenAPIRequest(googleGTM.getMatomoSiteId());
        String matomoSiteId =
                RestTemplateUtil.postForObject(
                                restTemplate,
                                dataBridgeApiHost + MATOMO_SITE_DELETE_API_PATH,
                                deleteMatomoSiteRequest,
                                new ParameterizedTypeReference<OpenAPIResponse<String>>() {})
                        .getData();
        log.info("为站点 {} 删除Matomo site: {}", siteCode, matomoSiteId);

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

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

        return true;
    }

    private <T> OpenAPIRequest<T> buildOpenAPIRequest(T data) {
        OpenAPIRequest<T> openAPIRequest = new OpenAPIRequest<>();
        openAPIRequest.setRequestServer(this.getClass().getSimpleName());
        openAPIRequest.setRequestTime(System.currentTimeMillis());
        openAPIRequest.setData(data);
        return openAPIRequest;
    }
}
