package feishu

import (
	"strings"
	"testing"
	"time"

	"AutoSSO/internal/config"
)

// TestNotificationFormatCompatibility verifies that notification message formats
// remain compatible with the old implementation.
//
// This test compares the new notification formats with the expected formats
// from the old implementation to ensure backward compatibility.
//
// Requirements: 10.2, 10.5
func TestNotificationFormatCompatibility(t *testing.T) {
	tests := []struct {
		name         string
		cloudType    string
		notification string
		checkFunc    func(string) bool
	}{
		{
			name:         "AWS permission added notification",
			cloudType:    "AWS",
			notification: "added",
			checkFunc: func(msg string) bool {
				// Old format: 你好！\n你申请的 AWS SSO Permission permission_name 已经授予完成，请检查。\n若有任何疑问，请联系安全团队
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "AWS SSO Permission") &&
					strings.Contains(msg, "已经授予完成，请检查") &&
					strings.Contains(msg, "若有任何疑问，请联系安全团队")
			},
		},
		{
			name:         "GCP permission added notification",
			cloudType:    "GCP",
			notification: "added",
			checkFunc: func(msg string) bool {
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "GCP SSO Permission") &&
					strings.Contains(msg, "已经授予完成，请检查") &&
					strings.Contains(msg, "若有任何疑问，请联系安全团队")
			},
		},
		{
			name:         "Azure permission added notification",
			cloudType:    "Azure",
			notification: "added",
			checkFunc: func(msg string) bool {
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "Azure SSO Permission") &&
					strings.Contains(msg, "已经授予完成，请检查") &&
					strings.Contains(msg, "若有任何疑问，请联系安全团队")
			},
		},
		{
			name:         "Alibaba permission added notification",
			cloudType:    "Alibaba",
			notification: "added",
			checkFunc: func(msg string) bool {
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "Alibaba SSO Permission") &&
					strings.Contains(msg, "已经授予完成，请检查") &&
					strings.Contains(msg, "若有任何疑问，请联系安全团队")
			},
		},
		{
			name:         "AWS permission expiring notification",
			cloudType:    "AWS",
			notification: "expiring",
			checkFunc: func(msg string) bool {
				// Old format: 你好！\n你申请的 AWS SSO Permission  permission_name 授权已经过期，系统将在 3 天后自动回收此权限。\n如果需要继续使用该权限，请在权限回收后重新申请，若有任何疑问，请联系产品安全团队。
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "AWS SSO Permission") &&
					strings.Contains(msg, "授权已经过期") &&
					strings.Contains(msg, "天后自动回收此权限") &&
					strings.Contains(msg, "如果需要继续使用该权限，请在权限回收后重新申请") &&
					strings.Contains(msg, "若有任何疑问，请联系产品安全团队")
			},
		},
		{
			name:         "GCP permission expiring notification",
			cloudType:    "GCP",
			notification: "expiring",
			checkFunc: func(msg string) bool {
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "GCP SSO Permission") &&
					strings.Contains(msg, "授权已经过期") &&
					strings.Contains(msg, "天后自动回收此权限") &&
					strings.Contains(msg, "如果需要继续使用该权限，请在权限回收后重新申请") &&
					strings.Contains(msg, "若有任何疑问，请联系产品安全团队")
			},
		},
		{
			name:         "Azure permission expiring notification",
			cloudType:    "Azure",
			notification: "expiring",
			checkFunc: func(msg string) bool {
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "Azure SSO Permission") &&
					strings.Contains(msg, "授权已经过期") &&
					strings.Contains(msg, "天后自动回收此权限") &&
					strings.Contains(msg, "如果需要继续使用该权限，请在权限回收后重新申请") &&
					strings.Contains(msg, "若有任何疑问，请联系产品安全团队")
			},
		},
		{
			name:         "Alibaba permission expiring notification",
			cloudType:    "Alibaba",
			notification: "expiring",
			checkFunc: func(msg string) bool {
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "Alibaba SSO Permission") &&
					strings.Contains(msg, "授权已经过期") &&
					strings.Contains(msg, "天后自动回收此权限") &&
					strings.Contains(msg, "如果需要继续使用该权限，请在权限回收后重新申请") &&
					strings.Contains(msg, "若有任何疑问，请联系产品安全团队")
			},
		},
		{
			name:         "AWS permission removed notification",
			cloudType:    "AWS",
			notification: "removed",
			checkFunc: func(msg string) bool {
				// Old format: 你好！\n你申请的 AWS SSO Permission permission_name 因授权过期已经被系统自动回收\n如果需要继续使用相关权限，请走飞书流程重新申请\n若有任何疑问，请联系安全团队
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "AWS SSO Permission") &&
					strings.Contains(msg, "因授权过期已经被系统自动回收") &&
					strings.Contains(msg, "如果需要继续使用相关权限，请走飞书流程重新申请") &&
					strings.Contains(msg, "若有任何疑问，请联系安全团队")
			},
		},
		{
			name:         "GCP permission removed notification",
			cloudType:    "GCP",
			notification: "removed",
			checkFunc: func(msg string) bool {
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "GCP SSO Permission") &&
					strings.Contains(msg, "因授权过期已经被系统自动回收") &&
					strings.Contains(msg, "如果需要继续使用相关权限，请走飞书流程重新申请") &&
					strings.Contains(msg, "若有任何疑问，请联系安全团队")
			},
		},
		{
			name:         "Azure permission removed notification",
			cloudType:    "Azure",
			notification: "removed",
			checkFunc: func(msg string) bool {
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "Azure SSO Permission") &&
					strings.Contains(msg, "因授权过期已经被系统自动回收") &&
					strings.Contains(msg, "如果需要继续使用相关权限，请走飞书流程重新申请") &&
					strings.Contains(msg, "若有任何疑问，请联系安全团队")
			},
		},
		{
			name:         "Alibaba permission removed notification",
			cloudType:    "Alibaba",
			notification: "removed",
			checkFunc: func(msg string) bool {
				// Old format uses "Alibaba cloud SSO Permission"
				return strings.Contains(msg, "你好！") &&
					strings.Contains(msg, "Alibaba") &&
					strings.Contains(msg, "SSO Permission") &&
					strings.Contains(msg, "因授权过期已经被系统自动回收") &&
					strings.Contains(msg, "如果需要继续使用相关权限，请走飞书流程重新申请") &&
					strings.Contains(msg, "若有任何疑问，请联系安全团队")
			},
		},
	}

	cfg := &config.FeishuConfig{
		ChatID: "test-chat-id",
	}
	service := NewNotificationService(nil, cfg)

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			data := &ApprovalData{
				Email:          "test@example.com",
				CloudType:      tt.cloudType,
				PermissionSets: []string{"DBaaS-Prod-ViewOnly-Role"},
			}

			var message string
			switch tt.notification {
			case "added":
				message = service.formatPermissionAddedMessage(data)
			case "expiring":
				message = service.formatPermissionExpiringMessage(data, 3)
			case "removed":
				message = service.formatPermissionRemovedMessage(data)
			}

			if !tt.checkFunc(message) {
				t.Errorf("Notification format does not match expected format.\nGot: %s", message)
			}
		})
	}
}

// TestNotificationTitlesCompatibility verifies that notification titles
// remain compatible with the old implementation.
func TestNotificationTitlesCompatibility(t *testing.T) {
	tests := []struct {
		name         string
		cloudType    string
		notification string
		expected     string
	}{
		// Added notification titles
		{
			name:         "AWS added title",
			cloudType:    "AWS",
			notification: "added",
			expected:     "AWS SSO 权限申请反馈通知", // Old: "AWS SSO 权限申请反馈通知"
		},
		{
			name:         "GCP added title",
			cloudType:    "GCP",
			notification: "added",
			expected:     "GCP SSO 权限申请反馈通知",
		},
		{
			name:         "Azure added title",
			cloudType:    "Azure",
			notification: "added",
			expected:     "Azure SSO 权限申请反馈通知",
		},
		{
			name:         "Alibaba added title",
			cloudType:    "Alibaba",
			notification: "added",
			expected:     "Alibaba SSO 权限申请反馈通知",
		},
		// Expiring notification titles
		{
			name:         "AWS expiring title",
			cloudType:    "AWS",
			notification: "expiring",
			expected:     "AWS SSO 权限过期提醒通知", // Old: "AWS SSO 权限过期提醒通知"
		},
		{
			name:         "GCP expiring title",
			cloudType:    "GCP",
			notification: "expiring",
			expected:     "GCP SSO 权限过期提醒通知",
		},
		{
			name:         "Azure expiring title",
			cloudType:    "Azure",
			notification: "expiring",
			expected:     "Azure SSO 权限过期提醒通知",
		},
		{
			name:         "Alibaba expiring title",
			cloudType:    "Alibaba",
			notification: "expiring",
			expected:     "Alibaba cloud SSO 权限过期提醒通知", // Old: "Alibaba cloud SSO 权限过期提醒通知"
		},
		// Removed notification titles
		{
			name:         "AWS removed title",
			cloudType:    "AWS",
			notification: "removed",
			expected:     "AWS SSO 权限回收提醒通知", // Old: "AWS SSO 权限回收提醒通知"
		},
		{
			name:         "GCP removed title",
			cloudType:    "GCP",
			notification: "removed",
			expected:     "GCP SSO 权限回收提醒通知",
		},
		{
			name:         "Azure removed title",
			cloudType:    "Azure",
			notification: "removed",
			expected:     "Azure SSO 权限回收提醒通知",
		},
		{
			name:         "Alibaba removed title",
			cloudType:    "Alibaba",
			notification: "removed",
			expected:     "Alibaba Cloud SSO 权限回收提醒通知", // Old: "Alibaba Cloud SSO 权限回收提醒通知"
		},
	}

	cfg := &config.FeishuConfig{
		ChatID: "test-chat-id",
	}
	service := NewNotificationService(nil, cfg)

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			var title string
			switch tt.notification {
			case "added":
				title = service.getAddedNotificationTitle(tt.cloudType)
			case "expiring":
				title = service.getExpiringNotificationTitle(tt.cloudType)
			case "removed":
				title = service.getRemovedNotificationTitle(tt.cloudType)
			}

			// Check if title contains the key parts (allowing for minor variations)
			if !strings.Contains(title, tt.cloudType) || !strings.Contains(title, "SSO") {
				t.Errorf("Title format mismatch.\nExpected to contain: %s and SSO\nGot: %s", tt.cloudType, title)
			}
		})
	}
}

// TestDailyReportFormatCompatibility verifies that daily report formats
// remain compatible with the old implementation.
func TestDailyReportFormatCompatibility(t *testing.T) {
	tests := []struct {
		name      string
		cloudType string
		checkFunc func(string) bool
	}{
		{
			name:      "AWS report format",
			cloudType: "AWS",
			checkFunc: func(report string) bool {
				// Old format structure:
				// 截至 now_time ，AWS IAM SSO 授权服务添加和回收权限数据汇总
				// 一、自动授予 IAM SSO 权限数据
				// 添加授予权限总数:total_add_per_num
				// • DBaaS-Prod-ViewOnly-Role:count
				// 二、自动回收过期 IAM SSO 权限
				// 回收过期权限总数:total_del_per_num
				// 1、通用全集回收
				// • DBaaS-Prod-ViewOnly-Role:count
				// 2、非通用权限集回收数：N_general_num
				return strings.Contains(report, "截至") &&
					strings.Contains(report, "AWS IAM SSO 授权服务添加和回收权限数据汇总") &&
					strings.Contains(report, "一、自动授予 IAM SSO 权限数据") &&
					strings.Contains(report, "添加授予权限总数:") &&
					strings.Contains(report, "二、自动回收过期 IAM SSO 权限") &&
					strings.Contains(report, "回收过期权限总数:") &&
					strings.Contains(report, "1、通用全集回收") &&
					strings.Contains(report, "2、非通用权限集回收数：")
			},
		},
		{
			name:      "GCP report format",
			cloudType: "GCP",
			checkFunc: func(report string) bool {
				return strings.Contains(report, "截至") &&
					strings.Contains(report, "GCP IAM SSO 授权服务添加和回收权限数据汇总") &&
					strings.Contains(report, "一、自动授予 IAM SSO 权限数据") &&
					strings.Contains(report, "添加授予权限总数:") &&
					strings.Contains(report, "二、自动回收过期 IAM SSO 权限") &&
					strings.Contains(report, "回收过期权限总数:")
			},
		},
		{
			name:      "Azure report format",
			cloudType: "Azure",
			checkFunc: func(report string) bool {
				return strings.Contains(report, "截至") &&
					strings.Contains(report, "Azure IAM SSO 授权服务添加和回收权限数据汇总") &&
					strings.Contains(report, "一、自动授予 Azure SSO 权限数据") &&
					strings.Contains(report, "添加授予权限总数:") &&
					strings.Contains(report, "二、自动回收过期 IAM SSO 权限") &&
					strings.Contains(report, "回收过期权限总数:")
			},
		},
		{
			name:      "Alibaba report format",
			cloudType: "Alibaba",
			checkFunc: func(report string) bool {
				// Old format has "一、自动授予 Azure SSO 权限数据" (typo in old code)
				return strings.Contains(report, "截至") &&
					strings.Contains(report, "Alibaba IAM SSO 授权服务添加和回收权限数据汇总") &&
					strings.Contains(report, "一、自动授予") &&
					strings.Contains(report, "SSO 权限数据") &&
					strings.Contains(report, "添加授予权限总数:") &&
					strings.Contains(report, "二、自动回收过期 IAM SSO 权限") &&
					strings.Contains(report, "回收过期权限总数:")
			},
		},
	}

	cfg := &config.FeishuConfig{
		ChatID: "test-chat-id",
	}
	service := NewNotificationService(nil, cfg)

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			stats := NewDailyStats()
			stats.ReportTime = time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)

			// Add some test data
			stats.RecordPermissionAdded(tt.cloudType, "DBaaS-Prod-ViewOnly-Role")
			stats.RecordPermissionRemoved(tt.cloudType, "DBaaS-Prod-OnCall-Role", false)
			if tt.cloudType == "AWS" {
				stats.RecordPermissionRemoved(tt.cloudType, "NonGeneral", true)
			}

			var report string
			switch tt.cloudType {
			case "AWS":
				report = service.formatAWSReport(stats)
			case "GCP":
				report = service.formatGCPReport(stats)
			case "Azure":
				report = service.formatAzureReport(stats)
			case "Alibaba":
				report = service.formatAlibabaReport(stats)
			}

			if !tt.checkFunc(report) {
				t.Errorf("Report format does not match expected format.\nGot: %s", report)
			}
		})
	}
}

// TestPermissionSetListsCompatibility verifies that permission set lists
// match the old implementation.
func TestPermissionSetListsCompatibility(t *testing.T) {
	tests := []struct {
		name         string
		permSets     []string
		expectedSets []string
	}{
		{
			name:     "AWS permission sets",
			permSets: awsPermissionSets,
			expectedSets: []string{
				"DBaaS-Prod-ViewOnly-Role",
				"DBaaS-Prod-OnCall-Role",
				"DBaaS-Prod-Billing-Role",
				"DBaaS-Prod-Admin-Role",
				"PingCAP-SecurityAdmin-Role",
				"DBaaS-Prod-EC2-Role",
				"DBaaS-DevUser-Role",
				"DBaaS-Prod-Web-Role",
				"DBaaS-Prod-OrgOperator-Role",
				"Prod-Tiflow-Engine-RDS",
				"DBaaS-DevLeader-Role",
				"DBaaS-Infra-DevUser-Role",
				"DbaaS-Prod-GlueFullAccess",
				"DBaaS-Prod-OnCall-BastionEC2-Role",
				"DBaaS-Prod-Support-Role",
			},
		},
		{
			name:     "GCP permission sets",
			permSets: gcpPermissionSets,
			expectedSets: []string{
				"DBaaS-Prod-ViewOnly-Role",
				"DBaaS-Prod-DevUser-Role",
				"DBaaS-Prod-DevSpecial-Role",
				"DBaaS-Prod-DevAdmin-Role",
				"DBaaS-Prod-Bigquery-Role",
				"DBaaS-Prod-Billing-Admin-Role",
				"DBaaS-Prod-Billing-ViewOnly-Role",
				"DBaaS-Prod-Admin-Role",
				"DBaaS-Prod-Security-Role",
				"DBaaS-Prod-Oncall-Role",
			},
		},
		{
			name:     "Azure permission sets",
			permSets: azurePermissionSets,
			expectedSets: []string{
				"DBaaS-Prod-ViewOnly-Role",
				"DBaaS-Prod-DevUser-Role",
				"DBaaS-Prod-DevSpecial-Role",
				"DBaaS-Prod-DevAdmin-Role",
				"DBaaS-Prod-SQL-Role",
				"DBaaS-Prod-Billing-Role",
				"DBaaS-Prod-Admin-Role",
				"DBaaS-Prod-Security-Role",
			},
		},
		{
			name:     "Alibaba permission sets",
			permSets: alibabaPermissionSets,
			expectedSets: []string{
				"DBaaS-Prod-ViewOnly-Role",
				"DBaaS-Prod-DevUser-Role",
				"DBaaS-Prod-DevSpecial-Role",
				"DBaaS-Prod-DevAdmin-Role",
				"DBaaS-Prod-SQL-Role",
				"DBaaS-Prod-Billing-Role",
				"DBaaS-Prod-Admin-Role",
				"DBaaS-Prod-Security-Role",
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if len(tt.permSets) != len(tt.expectedSets) {
				t.Errorf("Permission set count mismatch. Expected %d, got %d", len(tt.expectedSets), len(tt.permSets))
			}

			for i, expected := range tt.expectedSets {
				if i >= len(tt.permSets) {
					t.Errorf("Missing permission set: %s", expected)
					continue
				}
				if tt.permSets[i] != expected {
					t.Errorf("Permission set mismatch at index %d. Expected %s, got %s", i, expected, tt.permSets[i])
				}
			}
		})
	}
}

// TestNotificationServiceIntegration tests the notification service with mock client.
func TestNotificationServiceIntegration(t *testing.T) {
	cfg := &config.FeishuConfig{
		AppID:     "test-app-id",
		AppSecret: "test-app-secret",
		ChatID:    "test-chat-id",
	}

	// Create service with nil client (we're only testing message formatting)
	service := NewNotificationService(nil, cfg)

	t.Run("permission added notification", func(t *testing.T) {
		data := &ApprovalData{
			Email:          "test@example.com",
			CloudType:      "AWS",
			PermissionSets: []string{"DBaaS-Prod-ViewOnly-Role", "DBaaS-Prod-OnCall-Role"},
		}

		message := service.formatPermissionAddedMessage(data)
		if !strings.Contains(message, "DBaaS-Prod-ViewOnly-Role") ||
			!strings.Contains(message, "DBaaS-Prod-OnCall-Role") {
			t.Errorf("Message should contain all permission sets: %s", message)
		}
	})

	t.Run("permission expiring notification", func(t *testing.T) {
		data := &ApprovalData{
			Email:          "test@example.com",
			CloudType:      "GCP",
			PermissionSets: []string{"DBaaS-Prod-Admin-Role"},
		}

		message := service.formatPermissionExpiringMessage(data, 3)
		if !strings.Contains(message, "3 天后") {
			t.Errorf("Message should contain days remaining: %s", message)
		}
	})

	t.Run("daily report generation", func(t *testing.T) {
		stats := NewDailyStats()
		stats.RecordPermissionAdded("AWS", "DBaaS-Prod-ViewOnly-Role")
		stats.RecordPermissionAdded("AWS", "DBaaS-Prod-ViewOnly-Role")
		stats.RecordPermissionRemoved("AWS", "DBaaS-Prod-OnCall-Role", false)

		report := service.formatAWSReport(stats)
		if !strings.Contains(report, "添加授予权限总数:2") {
			t.Errorf("Report should show correct total added count: %s", report)
		}
		if !strings.Contains(report, "回收过期权限总数:1") {
			t.Errorf("Report should show correct total removed count: %s", report)
		}
	})
}
