package s3

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/pingcap-inc/clinic/clinic_data_service/pkg/config"
	log2 "github.com/pingcap-inc/clinic/clinic_data_service/pkg/log"
)

type AwsCredentials struct {
	AccessKeyID     string `json:"access_key_id"`
	SecretAccessKey string `json:"secret_access_key"`
	SessionToken    string `json:"session_token"`
	Expiration      string `json:"expiration"` // optional
}

/*
func getClientDir() string {
	usr, _ := user.Current()
	return filepath.Join(usr.HomeDir, ".observability")
}

func getGithubToken() (string, error) {
	dir := getClientDir()
	tokenFile := filepath.Join(dir, ".github")

	if data, err := os.ReadFile(tokenFile); err == nil {
		return string(bytes.TrimSpace(data)), nil
	}

	fmt.Print("Please input GitHub token: ")
	var token string
	fmt.Scanln(&token)

	if err := os.MkdirAll(dir, 0700); err != nil {
		return "", err
	}

	if err := os.WriteFile(tokenFile, []byte(token), 0600); err != nil {
		return "", err
	}
	return token, nil
}
*/

func authenticate(githubToken string, authURL string) (*AwsCredentials, error) {
	body, _ := json.Marshal(map[string]string{
		"github_token": githubToken,
	})

	resp, err := http.Post(authURL, "application/json", bytes.NewBuffer(body))
	if err != nil {
		return nil, fmt.Errorf("request failed: %v", err)
	}
	defer resp.Body.Close()

	log2.PlainInfo("request: " + authURL)
	log2.PlainInfo("auth response status: " + resp.Status)
	if resp.StatusCode != http.StatusOK {
		data, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("auth failed: %s", string(data))
	}

	var creds AwsCredentials
	if err := json.NewDecoder(resp.Body).Decode(&creds); err != nil {
		return nil, fmt.Errorf("decode failed: %v", err)
	}
	return &creds, nil
}

// GetS3ClientByGithubToken uses a GitHub token to authenticate and get an S3 client.
func GetS3ClientByGithubToken(region string, s3Bucket ...string) (*S3Client, error) {
	// if err := config.LoadConfig(); err != nil {
	// 	log.Fatalf("Failed to load configuration: %v", err)
	cfg := &config.AppConfig
	githubToken := cfg.S3.GithubToken
	creds, err := authenticate(githubToken, cfg.S3.AuthURL)
	if err != nil {
		return nil, fmt.Errorf("authentication failed: %v", err)
	}

	sess, err := session.NewSession(&aws.Config{
		Region: aws.String(region), // keep actual AWS region
		Credentials: credentials.NewStaticCredentials(
			creds.AccessKeyID,
			creds.SecretAccessKey,
			creds.SessionToken,
		),
	})

	if err != nil {
		return nil, fmt.Errorf("failed to create aws session: %v", err)
	}
	//if config.IsDev(){
	//	log2.Info(context.Background(),"Credentials", zap.Any("creds", creds))
	//}
	// example: "o11y-prod-shared-us-east-1" or premium "o11y-prod-shared-us-east-1-premium"
	bucket := fmt.Sprintf("%s-%s", cfg.S3.Bucket, region)
	if len(s3Bucket) > 0 {
		bucket = s3Bucket[0]
	}
	client := s3.New(sess)
	myS3Client := &S3Client{
		client: client,
		bucket: bucket,
	}

	return myS3Client, nil

}

func GetS3CredsByGithubToken() (*AwsCredentials, error) {

	// 	log.Fatalf("Failed to load configuration: %v", err)
	cfg := &config.AppConfig
	githubToken := cfg.S3.GithubToken
	creds, err := authenticate(githubToken, cfg.S3.AuthURL)
	if err != nil {
		return nil, fmt.Errorf("authentication failed: %v", err)
	}
	return creds, nil

}
