package utils

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strings"
	"time"

	"go.uber.org/zap"
)

var readRemote = map[string]string{
	"aws/ap-northeast-1":      "https://www.ds.ap-northeast-1.aws.observability.tidbcloud.com/internal/metrics/541521b7-b5eb-47c7-a015-b1f4f97c2744",
	"aws/ap-southeast-1":      "https://www.ds.ap-southeast-1.aws.observability.tidbcloud.com/internal/metrics/d39797d5-f75d-4871-84f8-d7b4f87b5d88",
	"aws/eu-central-1":        "https://www.ds.eu-central-1.aws.observability.tidbcloud.com/internal/metrics/934f05ea-66b2-4040-9202-d10f35f0561b",
	"aws/us-east-1":           "https://www.ds.us-east-1.aws.observability.tidbcloud.com/internal/metrics/f502cc26-7a0e-4a42-a92e-8816c323ccc7",
	"aws/us-west-2":           "https://www.ds.us-west-2.aws.observability.tidbcloud.com/internal/metrics/7055cf36-ea60-4c77-926d-60d3178162cf",
	"aws/ap-east-1":           "https://www.ds.ap-east-1.aws.observability.tidbcloud.com/internal/metrics/e34ee972-ad7c-46ea-ac74-be4975bde7f7",
	"alicloud/ap-southeast-1": "https://www.ds.ap-southeast-1.alicloud.observability.tidbcloud.com/internal/metrics/254b6105-4bbd-4047-ba39-7c2c3ae06587",
	"alicloud/ap-northeast-1": "https://www.ds.ap-northeast-1.alicloud.observability.tidbcloud.com/internal/metrics/09ffa49e-14d4-4dfd-8cd7-6046e4225bfa",
	"alicloud/na-south-1":     "https://www.ds.na-south-1.alicloud.observability.tidbcloud.com/internal/metrics/9af0222d-4871-4cde-912f-f07036b6263d",
	"alilcoud/us-east-1":      "https://www.ds.us-east-1.alicloud.observability.tidbcloud.com/internal/metrics/57167955-8be7-4344-b785-b2d0fca915b2",
	"alicloud/ap-southeast-5": "https://www.ds.ap-southeast-5.alicloud.observability.tidbcloud.com/internal/metrics/6b0a0712-1c7c-43d3-aba9-f104373ebad5",
}

type TenantInfo struct {
	TenantId   string `json:"tenantId"`
	ClusterId  string `json:"cluster_id"`
	Region     string `json:"region"`
	Type       string `json:"type"`
	Kubernetes string `json:"kubernetes"`
}
type Result struct {
	Metric TenantInfo    `json:"metric"`
	Value  []interface{} `json:"value"`
}

type Response struct {
	Status string `json:"status"`
	Data   struct {
		ResultType string   `json:"resultType"`
		Result     []Result `json:"result"`
	} `json:"data"`
}

// {"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1655274755.512,"2"]}]}}

func DoO11yQueryALL(logger *zap.Logger, q, date string) (results []Result, err error) {
	logger.Info("DoO11yQueryALL start...")
	defer logger.Info("DoO11yQueryALL end...", zap.Error(err))

	tm, _ := time.Parse("2006-01-02 15:04:05", date+" 23:59:59")
	for _, addr := range readRemote {
		if strings.Contains(addr, "observability") && strings.Contains(q, "tenantId") {
			q = strings.Replace(q, "tenantId", "tenant_id", -1)
		}
		urlString := fmt.Sprintf("%s/api/v1/query?query=%s&time=%v", addr, url.QueryEscape(q), tm.Unix())
		logger.Info("date=["+date+" 23:59:59]", zap.Any("query_url", urlString))
		req, err := http.NewRequest("GET", urlString, nil)
		if err != nil {
			logger.Info("query failed", zap.Error(err))
			continue
		}
		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			logger.Info("query failed", zap.Error(err))
			continue
		}
		if resp.StatusCode == http.StatusOK {
			o11yRespResult := Response{}
			err = json.NewDecoder(resp.Body).Decode(&o11yRespResult)
			if err == nil && o11yRespResult.Status == "success" {
				results = append(results, o11yRespResult.Data.Result...)
			}
		}
		resp.Body.Close()
	}
	return results, nil
}

func DoO11yQueryWithRegion(logger *zap.Logger, promQL, date string) (results map[string][]Result, err error) {
	logger.Info("DoO11yQueryWithRegion start...")
	defer logger.Info("DoO11yQueryWithRegion end...", zap.Error(err))

	results = make(map[string][]Result)
	tm, _ := time.Parse("2006-01-02 15:04:05", date+" 23:59:59")
	for region, addr := range readRemote {
		urlString := fmt.Sprintf("%s/api/v1/query?query=%s&time=%v", addr, url.QueryEscape(promQL), tm.Unix())
		logger.Info("querys, date=[%s 23:59:59]", zap.Any("url", urlString))
		req, err := http.NewRequest("GET", urlString, nil)
		if err != nil {
			logger.Info("query failed", zap.Error(err))
			continue
		}
		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			logger.Info("query failed", zap.Error(err))
			continue
		}
		if resp.StatusCode == http.StatusOK {
			o11yRespResult := Response{}
			err = json.NewDecoder(resp.Body).Decode(&o11yRespResult)
			if err == nil && o11yRespResult.Status == "success" {
				results[region] = o11yRespResult.Data.Result
			}
		}
		logger.Info("query result", zap.Any("result", results[region]))
		resp.Body.Close()
	}
	return results, nil
}
