package trafficjobclient

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"time"
)

const (
	bucket        = "delicated-healthcheck"
	assumeRoleARN = "arn:aws:iam::552185537300:role/clinic-job-role"
)

type TrafficComparisonReportStorage struct {
	s3 Storage
}

func NewTrafficComparisonReportStorage(ctx context.Context) *TrafficComparisonReportStorage {
	return &TrafficComparisonReportStorage{
		s3: NewAWSStorage(ctx, "us-west-2", assumeRoleARN),
	}
}

func (s *TrafficComparisonReportStorage) MetricsDiffExists(ctx context.Context, args *Request) (bool, error) {
	return s.s3.ObjectExists(ctx, bucket, genMetricsDiffKey(args))
}

func (s *TrafficComparisonReportStorage) GetSQLDiff(ctx context.Context, args *Request) (any, error) {
	return s.getJsonObj(ctx, genSQLDiffKey(args), genSQLDiffKeyLegacy(args))
}

func (s *TrafficComparisonReportStorage) GetMetricsDiff(ctx context.Context, args *Request) (any, error) {
	return s.getJsonObj(ctx, genMetricsDiffKey(args), genMetricsDiffKeyLegacy(args))
}

func (s *TrafficComparisonReportStorage) getJsonObj(ctx context.Context, key, fallbackKey string) (any, error) {
	obj, err := s.s3.Object(ctx, bucket, key)
	if err != nil {
		if errors.Is(err, ErrNotFound) && fallbackKey != "" {
			// Try fallback key for backward compatibility
			obj, err = s.s3.Object(ctx, bucket, fallbackKey)
		}
		if err != nil {
			return nil, err
		}
	}
	defer obj.Reader.Close()
	b, err := io.ReadAll(obj.Reader)
	if err != nil {
		return nil, err
	}
	var result any
	if err := json.Unmarshal(b, &result); err != nil {
		return nil, err
	}
	return result, nil
}

func genSQLDiffKey(args *Request) string {
	return genKey(args, "sql_diff", true)
}

func genSQLDiffKeyLegacy(args *Request) string {
	return genKey(args, "sql_diff", false)
}

func genMetricsDiffKey(args *Request) string {
	return genKey(args, "metrics_diff", true)
}

func genMetricsDiffKeyLegacy(args *Request) string {
	return genKey(args, "metrics_diff", false)
}

func genKey(args *Request, tp string, withReportID bool) string {
	cluster1 := args.ClusterA.ClusterID
	cluster2 := args.ClusterB.ClusterID
	startTime, _ := time.Parse(time.RFC3339, args.ClusterA.TimeRange.Start)
	endTime, _ := time.Parse(time.RFC3339, args.ClusterA.TimeRange.End)
	startTimeStr := startTime.UTC().Format("2006-01-02_15-04")
	endTimeStr := endTime.UTC().Format("2006-01-02_15-04")
	if withReportID && args.Options.ReportID != "" {
		return fmt.Sprintf("traffic-comparison-report/%s_%s_%s_%s_%s_%s.json", tp, cluster1, cluster2, startTimeStr, endTimeStr, args.Options.ReportID)
	}
	return fmt.Sprintf("traffic-comparison-report/%s_%s_%s_%s_%s.json", tp, cluster1, cluster2, startTimeStr, endTimeStr)
}
