package eks

import (
	"context"
	"fmt"
	"time"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

	"github.com/tidbcloud/eks-provider/controllers/imports/task"
	"github.com/tidbcloud/infra-provider/pkg/deploy"
)

// Credentials is a task to handle AWS credentials for import
type Credentials struct {
	*task.BaseTask
}

// NewCredentials creates a new Credentials task
func NewCredentials(ctx *task.Context) *Credentials {
	return &Credentials{
		BaseTask: &task.BaseTask{Context: ctx},
	}
}

// Name returns the name of the task
func (t *Credentials) Name() string {
	return "Credentials"
}

// Create creates the AWS credentials secret
func (t *Credentials) Create(ctx context.Context) deploy.Result {
	// Generate AWS credentials content
	credContent, err := t.getCredentialsContent()
	if err != nil {
		return deploy.Error(err).WithRequeuAfter(time.Second * 20)
	}

	// Create secret with AWS credentials
	secret := &corev1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Name:      t.Import.Name + "-aws-credentials",
			Namespace: t.GetClusterNameSpace(),
			Labels:    t.LightningLabels,
		},
		Data: map[string][]byte{
			"credentials": credContent,
		},
	}

	clusterCli := t.EnvProvider.GetClient()
	if _, err := controllerutil.CreateOrUpdate(ctx, clusterCli, secret, func() error { return nil }); err != nil {
		return deploy.Error(err)
	}

	return deploy.Done()
}

func (t *Credentials) PostCreate(ctx context.Context) deploy.Result {
	t.LightningVolumes.Envs = append(t.LightningVolumes.Envs, []corev1.EnvVar{
		{
			Name:  "AWS_SDK_LOAD_CONFIG",
			Value: "true",
		},
		{
			Name:  "AWS_SHARED_CREDENTIALS_FILE",
			Value: "/.aws/credentials",
		},
		{
			Name:  "AWS_CONFIG_FILE",
			Value: "/.aws/credentials",
		},
		{
			Name:  "AWS_WEB_IDENTITY_TOKEN_FILE",
			Value: "", // Explicitly disable IRSA token usage
		},
	}...)

	t.LightningVolumes.Volumes = append(t.LightningVolumes.Volumes, corev1.Volume{
		Name: "aws-credentials",
		VolumeSource: corev1.VolumeSource{
			Secret: &corev1.SecretVolumeSource{
				SecretName: t.Import.Name + "-aws-credentials",
			},
		},
	})

	t.LightningVolumes.Mounts = append(t.LightningVolumes.Mounts, corev1.VolumeMount{
		Name:      "aws-credentials",
		MountPath: "/.aws",
		ReadOnly:  true,
	})

	return deploy.Done()
}

// Delete deletes the AWS credentials secret
func (t *Credentials) Delete(ctx context.Context) deploy.Result {
	if !t.IsClusterExist() {
		return deploy.Done()
	}

	secret := &corev1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Name:      t.Import.Name + "-aws-credentials",
			Namespace: t.GetClusterNameSpace(),
		},
	}

	clusterCli := t.EnvProvider.GetClient()
	err := clusterCli.Delete(ctx, secret)
	if client.IgnoreNotFound(err) != nil {
		return deploy.Error(err)
	}

	return deploy.Done()
}

// getCredentialsContent gets the AWS credentials content for the import task
// This mimics the logic in infra-api/controllers/imports/env.go:awsCredentials
func (t *Credentials) getCredentialsContent() ([]byte, error) {
	// Check if RoleArn is specified in AccessConfig
	if t.Import.Spec.AccessConfig.RoleArn != "" {
		return t.getCrossAccountCredentials(), nil
	}

	// If no RoleArn specified, use the default role ARN from the network
	roleARN := t.Import.Status.AWSNodeRoleARN
	if roleARN == "" {
		return nil, fmt.Errorf("AWS node role ARN not found in import status")
	}

	// Create AWS credentials config with explicit settings to ensure proper role assumption
	format := `[default]
aws_access_key_id =
aws_secret_access_key =
role_arn = %s
credential_source = Ec2InstanceMetadata
region = %s
role_session_name = lightning-import-%s
`
	return []byte(fmt.Sprintf(format, roleARN, t.Config.Network.Region, t.Import.Name)), nil
}

// getCrossAccountCredentials creates AWS cross-account credentials configuration
// This mimics the logic in infra-api/controllers/imports/env.go:awsCrossAccountCredentials
func (t *Credentials) getCrossAccountCredentials() []byte {
	// Format credentials file for cross-account access with explicit settings
	format := `[default]
aws_access_key_id =
aws_secret_access_key =
role_arn = %s
external_id = %s
credential_source = Ec2InstanceMetadata
region = %s
role_session_name = lightning-import-%s
`
	return []byte(fmt.Sprintf(format,
		t.Import.Spec.AccessConfig.RoleArn,
		t.GetAWSNodeRoleExternalID(),
		t.Config.Network.Region,
		t.Import.Name))
}
