// Package aws provides the AWS SSO (IAM Identity Center) provider implementation.
// This file contains unit tests for the AWS provider.
//
// Requirements: 3.2, 3.3, 3.4, 3.6
package aws

import (
	"context"
	"testing"
	"time"

	"AutoSSO/internal/config"
	"AutoSSO/internal/provider"
)

func TestNewAWSProvider(t *testing.T) {
	t.Run("nil config returns error", func(t *testing.T) {
		_, err := NewAWSProvider(nil)
		if err == nil {
			t.Error("NewAWSProvider(nil) should return error")
		}
	})

	t.Run("empty IdentityCenterARN returns error", func(t *testing.T) {
		cfg := &config.AWSConfig{
			IdentityStoreID: "d-95670a3c83",
			Region:          "ap-northeast-1",
		}
		_, err := NewAWSProvider(cfg)
		if err == nil {
			t.Error("NewAWSProvider with empty IdentityCenterARN should return error")
		}
	})

	t.Run("empty IdentityStoreID returns error", func(t *testing.T) {
		cfg := &config.AWSConfig{
			IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
			Region:            "ap-northeast-1",
		}
		_, err := NewAWSProvider(cfg)
		if err == nil {
			t.Error("NewAWSProvider with empty IdentityStoreID should return error")
		}
	})

	t.Run("valid config creates provider", func(t *testing.T) {
		cfg := &config.AWSConfig{
			IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
			IdentityStoreID:   "d-95670a3c83",
			Region:            "ap-northeast-1",
		}
		p, err := NewAWSProvider(cfg)
		if err != nil {
			t.Fatalf("NewAWSProvider() error = %v", err)
		}
		if p == nil {
			t.Fatal("NewAWSProvider() returned nil provider")
		}
		defer p.Close()

		// Verify provider name
		if p.Name() != "AWS" {
			t.Errorf("Name() = %v, want AWS", p.Name())
		}
	})

	t.Run("default region is used when not specified", func(t *testing.T) {
		cfg := &config.AWSConfig{
			IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
			IdentityStoreID:   "d-95670a3c83",
			Region:            "", // Empty region should use default
		}
		p, err := NewAWSProvider(cfg)
		if err != nil {
			t.Fatalf("NewAWSProvider() error = %v", err)
		}
		defer p.Close()

		// Provider should be created successfully even with empty region
		// The AWS SDK will use the default region from shared config
		if p == nil {
			t.Fatal("NewAWSProvider() returned nil provider")
		}
	})
}

func TestAWSProvider_Name(t *testing.T) {
	cfg := &config.AWSConfig{
		IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
		IdentityStoreID:   "d-95670a3c83",
		Region:            "ap-northeast-1",
	}
	p, err := NewAWSProvider(cfg)
	if err != nil {
		t.Fatalf("NewAWSProvider() error = %v", err)
	}
	defer p.Close()

	if p.Name() != string(provider.ProviderAWS) {
		t.Errorf("Name() = %v, want %v", p.Name(), provider.ProviderAWS)
	}
}

func TestAWSProvider_Close(t *testing.T) {
	cfg := &config.AWSConfig{
		IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
		IdentityStoreID:   "d-95670a3c83",
		Region:            "ap-northeast-1",
	}
	p, err := NewAWSProvider(cfg)
	if err != nil {
		t.Fatalf("NewAWSProvider() error = %v", err)
	}

	// First close should succeed
	err = p.Close()
	if err != nil {
		t.Errorf("Close() error = %v", err)
	}

	// Second close should also succeed (idempotent)
	err = p.Close()
	if err != nil {
		t.Errorf("Second Close() error = %v", err)
	}
}

func TestAWSProvider_AddPermission_Validation(t *testing.T) {
	cfg := &config.AWSConfig{
		IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
		IdentityStoreID:   "d-95670a3c83",
		Region:            "ap-northeast-1",
	}
	p, err := NewAWSProvider(cfg)
	if err != nil {
		t.Fatalf("NewAWSProvider() error = %v", err)
	}
	defer p.Close()

	ctx := context.Background()

	t.Run("nil request returns error", func(t *testing.T) {
		err := p.AddPermission(ctx, nil)
		if err == nil {
			t.Error("AddPermission(nil) should return error")
		}
	})

	t.Run("empty account ID returns error", func(t *testing.T) {
		req := &provider.PermissionRequest{
			AccountID:      "",
			UserEmail:      "user@example.com",
			PermissionSets: []string{"ReadOnly"},
		}
		err := p.AddPermission(ctx, req)
		if err == nil {
			t.Error("AddPermission with empty AccountID should return error")
		}
	})

	t.Run("empty user email returns error", func(t *testing.T) {
		req := &provider.PermissionRequest{
			AccountID:      "123456789012",
			UserEmail:      "",
			PermissionSets: []string{"ReadOnly"},
		}
		err := p.AddPermission(ctx, req)
		if err == nil {
			t.Error("AddPermission with empty UserEmail should return error")
		}
	})

	t.Run("empty permission sets returns error", func(t *testing.T) {
		req := &provider.PermissionRequest{
			AccountID:      "123456789012",
			UserEmail:      "user@example.com",
			PermissionSets: []string{},
		}
		err := p.AddPermission(ctx, req)
		if err == nil {
			t.Error("AddPermission with empty PermissionSets should return error")
		}
	})
}

func TestAWSProvider_RemovePermission_Validation(t *testing.T) {
	cfg := &config.AWSConfig{
		IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
		IdentityStoreID:   "d-95670a3c83",
		Region:            "ap-northeast-1",
	}
	p, err := NewAWSProvider(cfg)
	if err != nil {
		t.Fatalf("NewAWSProvider() error = %v", err)
	}
	defer p.Close()

	ctx := context.Background()

	t.Run("nil request returns error", func(t *testing.T) {
		err := p.RemovePermission(ctx, nil)
		if err == nil {
			t.Error("RemovePermission(nil) should return error")
		}
	})

	t.Run("empty account ID returns error", func(t *testing.T) {
		req := &provider.PermissionRequest{
			AccountID:      "",
			UserEmail:      "user@example.com",
			PermissionSets: []string{"ReadOnly"},
		}
		err := p.RemovePermission(ctx, req)
		if err == nil {
			t.Error("RemovePermission with empty AccountID should return error")
		}
	})

	t.Run("empty user email returns error", func(t *testing.T) {
		req := &provider.PermissionRequest{
			AccountID:      "123456789012",
			UserEmail:      "",
			PermissionSets: []string{"ReadOnly"},
		}
		err := p.RemovePermission(ctx, req)
		if err == nil {
			t.Error("RemovePermission with empty UserEmail should return error")
		}
	})

	t.Run("empty permission sets returns error", func(t *testing.T) {
		req := &provider.PermissionRequest{
			AccountID:      "123456789012",
			UserEmail:      "user@example.com",
			PermissionSets: []string{},
		}
		err := p.RemovePermission(ctx, req)
		if err == nil {
			t.Error("RemovePermission with empty PermissionSets should return error")
		}
	})
}

func TestAWSProvider_waitBeforeOperation_CanceledContext(t *testing.T) {
	originalDelay := waitBeforeOperationDelay
	waitBeforeOperationDelay = 250 * time.Millisecond
	defer func() {
		waitBeforeOperationDelay = originalDelay
	}()

	p := &AWSProvider{}
	ctx, cancel := context.WithCancel(context.Background())
	cancel()

	start := time.Now()
	err := p.waitBeforeOperation(ctx)
	elapsed := time.Since(start)

	if err == nil {
		t.Fatalf("expected error for canceled context, got nil")
	}
	if elapsed >= 100*time.Millisecond {
		t.Fatalf("expected wait to return quickly on cancel, took %v", elapsed)
	}
}

func TestAWSProvider_GetUserID_Validation(t *testing.T) {
	cfg := &config.AWSConfig{
		IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
		IdentityStoreID:   "d-95670a3c83",
		Region:            "ap-northeast-1",
	}
	p, err := NewAWSProvider(cfg)
	if err != nil {
		t.Fatalf("NewAWSProvider() error = %v", err)
	}
	defer p.Close()

	ctx := context.Background()

	t.Run("empty email returns error", func(t *testing.T) {
		_, err := p.GetUserID(ctx, "")
		if err == nil {
			t.Error("GetUserID with empty email should return error")
		}
	})
}

func TestAWSProvider_ClosedProvider(t *testing.T) {
	cfg := &config.AWSConfig{
		IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
		IdentityStoreID:   "d-95670a3c83",
		Region:            "ap-northeast-1",
	}
	p, err := NewAWSProvider(cfg)
	if err != nil {
		t.Fatalf("NewAWSProvider() error = %v", err)
	}

	// Close the provider
	p.Close()

	ctx := context.Background()

	t.Run("AddPermission on closed provider returns error", func(t *testing.T) {
		req := &provider.PermissionRequest{
			AccountID:      "123456789012",
			UserEmail:      "user@example.com",
			PermissionSets: []string{"ReadOnly"},
		}
		err := p.AddPermission(ctx, req)
		if err == nil {
			t.Error("AddPermission on closed provider should return error")
		}
	})

	t.Run("RemovePermission on closed provider returns error", func(t *testing.T) {
		req := &provider.PermissionRequest{
			AccountID:      "123456789012",
			UserEmail:      "user@example.com",
			PermissionSets: []string{"ReadOnly"},
		}
		err := p.RemovePermission(ctx, req)
		if err == nil {
			t.Error("RemovePermission on closed provider should return error")
		}
	})

	t.Run("GetUserID on closed provider returns error", func(t *testing.T) {
		_, err := p.GetUserID(ctx, "user@example.com")
		if err == nil {
			t.Error("GetUserID on closed provider should return error")
		}
	})

	t.Run("ValidateCredentials on closed provider returns error", func(t *testing.T) {
		err := p.ValidateCredentials(ctx)
		if err == nil {
			t.Error("ValidateCredentials on closed provider should return error")
		}
	})
}

func TestAWSProvider_ImplementsInterface(t *testing.T) {
	cfg := &config.AWSConfig{
		IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
		IdentityStoreID:   "d-95670a3c83",
		Region:            "ap-northeast-1",
	}
	p, err := NewAWSProvider(cfg)
	if err != nil {
		t.Fatalf("NewAWSProvider() error = %v", err)
	}
	defer p.Close()

	// Verify that AWSProvider implements the Provider interface
	var _ provider.Provider = p
}
