package provider

import (
	"context"
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/service/eks"
	ekstypes "github.com/aws/aws-sdk-go-v2/service/eks/types"

	calent "github.com/tidbcloud/devops/entity/k8scalendar"
)

type eksProvider struct {
	client *eks.Client
}

func (p *eksProvider) Cloud() string {
	return calent.CloudEKS
}

func (p *eksProvider) Fetch(ctx context.Context) ([]*calent.VersionLifecycle, error) {
	now := time.Now().UTC()
	seen := make(map[string]struct{})
	var out []*calent.VersionLifecycle

	var nextToken *string
	for {
		resp, err := p.client.DescribeClusterVersions(ctx, &eks.DescribeClusterVersionsInput{
			IncludeAll: aws.Bool(true),
			NextToken:  nextToken,
		})
		if err != nil {
			return nil, fmt.Errorf("eks DescribeClusterVersions: %w", err)
		}
		for _, info := range resp.ClusterVersions {
			v := mapEKSClusterVersion(info, now)
			if v == nil {
				continue
			}
			key := v.Cloud + "-" + v.Version
			if _, ok := seen[key]; ok {
				continue
			}
			seen[key] = struct{}{}
			out = append(out, v)
		}
		if resp.NextToken == nil || *resp.NextToken == "" {
			break
		}
		nextToken = resp.NextToken
	}
	if len(out) == 0 {
		return nil, fmt.Errorf("eks DescribeClusterVersions: no versions returned")
	}
	return out, nil
}

func mapEKSClusterVersion(info ekstypes.ClusterVersionInformation, scrapedAt time.Time) *calent.VersionLifecycle {
	if info.ClusterType != nil && *info.ClusterType != "" && *info.ClusterType != "eks" {
		return nil
	}
	ver := ""
	if info.ClusterVersion != nil {
		ver = normalizeVersion(*info.ClusterVersion)
	}
	if ver == "" {
		return nil
	}
	if info.ReleaseDate == nil || info.EndOfStandardSupportDate == nil {
		return nil
	}

	v := &calent.VersionLifecycle{
		Cloud:                calent.CloudEKS,
		Version:              ver,
		CloudProvider:        calent.CloudToProvider(calent.CloudEKS),
		LifecycleStart:       info.ReleaseDate.UTC(),
		EndOfStandardSupport: info.EndOfStandardSupportDate.UTC(),
		ReleasePrecision:     calent.ReleasePrecisionDay,
		ScrapedAt:            scrapedAt,
	}
	if info.EndOfExtendedSupportDate != nil {
		t := info.EndOfExtendedSupportDate.UTC()
		v.EndOfExtendedSupport = &t
	}
	v.Fingerprint = v.ComputeFingerprint()
	return v
}

// NewEKS builds an EKS provider backed by an injected AWS SDK EKS client.
func NewEKS(client *eks.Client) Provider {
	return &eksProvider{client: client}
}
