// Package feishu provides compatibility tests to ensure the refactored Feishu
// client maintains backward compatibility with the legacy implementation.
//
// This file verifies that:
// - Approval instance ID format parsing is compatible
// - User email extraction produces the same results
// - Permission set parsing produces the same results
// - API request/response formats are compatible
//
// Requirements: 10.1, 10.2
package feishu

import (
	"encoding/json"
	"regexp"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// Legacy constants from feishu/progress_info.go for compatibility verification
const (
	// LegacyInstanceIDRegex is the regex pattern used in the legacy code
	// to match Feishu approval instance IDs
	LegacyInstanceIDRegex = `[0-9A-F]{8}-([0-9A-Z-]{4}-){3}[0-9A-Z]{12}`
)

// LegacyCloudAccountMapping represents the hardcoded account mappings from legacy code
// Used to verify that the refactored code produces compatible cloud type detection
var LegacyCloudAccountMapping = map[string]string{
	// AWS accounts
	"557537366020": "AWS",
	"380838443567": "AWS",
	"143458967504": "AWS",
	"730335266318": "AWS",
	"886436949658": "AWS",
	"182399704004": "AWS",
	"632330501419": "AWS",
	"296171618728": "AWS",
	// GCP projects
	"tidbcloud-prod-000":  "GCP",
	"dbaas-prod":          "GCP",
	"gcp-autonomous-prod": "GCP",
	"tidbcloud-auth0":     "GCP",
	"tidbcloud-test":      "GCP",
	// Azure subscriptions
	"tidb-dedicated-prod-controlplane":  "Azure",
	"tidb-dedicated-prod-dataplane-000": "Azure",
	"tidb-o11y":                         "Azure",
	// Alibaba accounts
	"5480039859161595": "Alibaba",
	"5108739859105002": "Alibaba",
}

// TestCompatibility_InstanceIDFormat verifies that the instance ID format
// used in the refactored code is compatible with the legacy regex pattern.
//
// The legacy code uses regex pattern: [0-9A-F]{8}-([0-9A-Z-]{4}-){3}[0-9A-Z]{12}
// Example: 81762D1E-68FE-4448-89C4-5F14288778C8
func TestCompatibility_InstanceIDFormat(t *testing.T) {
	legacyRegex := regexp.MustCompile(LegacyInstanceIDRegex)

	testCases := []struct {
		name        string
		instanceID  string
		shouldMatch bool
	}{
		{
			name:        "valid approval code format",
			instanceID:  "81762D1E-68FE-4448-89C4-5F14288778C8",
			shouldMatch: true,
		},
		{
			name:        "valid instance ID uppercase",
			instanceID:  "0CBDD647-7223-43B4-BA0C-1234567890AB",
			shouldMatch: true,
		},
		{
			name:        "valid instance ID mixed case",
			instanceID:  "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
			shouldMatch: true,
		},
		{
			name:        "invalid - lowercase",
			instanceID:  "81762d1e-68fe-4448-89c4-5f14288778c8",
			shouldMatch: false,
		},
		{
			name:        "invalid - wrong format",
			instanceID:  "not-a-valid-instance-id",
			shouldMatch: false,
		},
		{
			name:        "invalid - too short",
			instanceID:  "81762D1E-68FE-4448",
			shouldMatch: false,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			matched := legacyRegex.MatchString(tc.instanceID)
			assert.Equal(t, tc.shouldMatch, matched,
				"Instance ID %q should match=%v but got match=%v",
				tc.instanceID, tc.shouldMatch, matched)
		})
	}
}

// TestCompatibility_EmailExtraction verifies that email extraction from
// approval data produces the same results as the legacy regex-based parsing.
//
// Legacy code patterns:
// - Chinese: 申请人邮箱\",\"type\":\"input\",\"ext\":null,\"value\":\"xxx@pingcap.com
// - English: applicant email（xxx@pingcap.com）\",\"type\":\"input\",\"ext\":null,\"value\":\"xxx@pingcap.com
func TestCompatibility_EmailExtraction(t *testing.T) {
	parser := NewParser()

	testCases := []struct {
		name          string
		fieldName     string
		emailValue    string
		expectedEmail string
	}{
		{
			name:          "Chinese field name",
			fieldName:     "申请人邮箱",
			emailValue:    "user@pingcap.com",
			expectedEmail: "user@pingcap.com",
		},
		{
			name:          "English field name",
			fieldName:     "applicant email（xxx@pingcap.com）",
			emailValue:    "test.user@pingcap.com",
			expectedEmail: "test.user@pingcap.com",
		},
		{
			name:          "email with dots",
			fieldName:     "申请人邮箱",
			emailValue:    "first.last@pingcap.com",
			expectedEmail: "first.last@pingcap.com",
		},
		{
			name:          "email with hyphen",
			fieldName:     "申请人邮箱",
			emailValue:    "user-name@pingcap.com",
			expectedEmail: "user-name@pingcap.com",
		},
		{
			name:          "email with spaces (should be trimmed)",
			fieldName:     "申请人邮箱",
			emailValue:    "  user@pingcap.com  ",
			expectedEmail: "user@pingcap.com",
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			formFields := []FormField{
				{
					ID:    "email_field",
					Name:  tc.fieldName,
					Type:  "input",
					Value: json.RawMessage(`"` + tc.emailValue + `"`),
				},
				{
					ID:    "app_type",
					Name:  "申请人选择申请类型",
					Type:  "radioV2",
					Value: json.RawMessage(`"生产账号申请（SSO）"`),
				},
				{
					ID:    "account",
					Name:  "生产账号选择",
					Type:  "radioV2",
					Value: json.RawMessage(`"AWS Prod (#557537366020)"`),
				},
				{
					ID:    "role",
					Name:  "选择生产 SSO Role",
					Type:  "checkboxV2",
					Value: json.RawMessage(`["viewonly"]`),
				},
			}

			formJSON, err := json.Marshal(formFields)
			require.NoError(t, err)

			response := InstanceDetailResponse{
				Code: 0,
				Msg:  "success",
				Data: InstanceDetailData{
					InstanceCode: "test-instance",
					Status:       "APPROVED",
					Form:         string(formJSON),
				},
			}

			responseJSON, err := json.Marshal(response)
			require.NoError(t, err)

			data, err := parser.ParseInstanceDetail(responseJSON)
			require.NoError(t, err)
			assert.Equal(t, tc.expectedEmail, data.Email)
		})
	}
}

// TestCompatibility_AccountIDExtraction verifies that account ID extraction
// produces the same results as the legacy regex-based parsing.
//
// Legacy code patterns:
// - AWS: (#123456789) format, extracts numeric ID
// - GCP: project ID directly or (#project-id) format
// - Azure: subscription name directly
// - Alibaba: (#123456789) format, extracts numeric ID
func TestCompatibility_AccountIDExtraction(t *testing.T) {
	parser := NewParser()

	testCases := []struct {
		name              string
		accountFieldValue string
		cloudType         string
		expectedAccountID string
	}{
		// AWS account formats
		{
			name:              "AWS with parentheses and hash",
			accountFieldValue: "AWS Prod Account (#557537366020)",
			cloudType:         "AWS",
			expectedAccountID: "557537366020",
		},
		{
			name:              "AWS with name and ID",
			accountFieldValue: "Production Main (#380838443567)",
			cloudType:         "AWS",
			expectedAccountID: "380838443567",
		},
		// GCP project formats
		{
			name:              "GCP project ID direct",
			accountFieldValue: "tidbcloud-prod-000",
			cloudType:         "GCP",
			expectedAccountID: "tidbcloud-prod-000",
		},
		{
			name:              "GCP project with parentheses",
			accountFieldValue: "GCP Project (#dbaas-prod)",
			cloudType:         "GCP",
			expectedAccountID: "dbaas-prod",
		},
		// Azure subscription formats
		{
			name:              "Azure subscription name direct",
			accountFieldValue: "tidb-dedicated-prod-controlplane",
			cloudType:         "Azure",
			expectedAccountID: "tidb-dedicated-prod-controlplane",
		},
		{
			name:              "Azure subscription with parentheses",
			accountFieldValue: "Azure Sub (#tidb-o11y)",
			cloudType:         "Azure",
			expectedAccountID: "tidb-o11y",
		},
		// Alibaba account formats
		{
			name:              "Alibaba with hash",
			accountFieldValue: "Alibaba Prod (#5480039859161595)",
			cloudType:         "Alibaba",
			expectedAccountID: "5480039859161595",
		},
		{
			name:              "Alibaba second account",
			accountFieldValue: "Alibaba Secondary (#5108739859105002)",
			cloudType:         "Alibaba",
			expectedAccountID: "5108739859105002",
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			result := parser.extractAccountID(tc.accountFieldValue, tc.cloudType)
			assert.Equal(t, tc.expectedAccountID, result,
				"Account ID extraction for %q (cloud=%s) should be %q but got %q",
				tc.accountFieldValue, tc.cloudType, tc.expectedAccountID, result)
		})
	}
}

// TestCompatibility_PermissionSetParsing verifies that permission set parsing
// produces the same results as the legacy regex-based parsing.
//
// Legacy code patterns:
// - Array format: [\"viewonly\",\"oncall\"]
// - Single value: \"viewonly\"
func TestCompatibility_PermissionSetParsing(t *testing.T) {
	parser := NewParser()

	testCases := []struct {
		name                   string
		permissionFieldName    string
		permissionValue        string
		expectedPermissionSets []string
	}{
		// AWS permission formats
		{
			name:                   "AWS single permission",
			permissionFieldName:    "选择生产 SSO Role",
			permissionValue:        `["viewonly"]`,
			expectedPermissionSets: []string{"viewonly"},
		},
		{
			name:                   "AWS multiple permissions",
			permissionFieldName:    "选择生产 SSO Role",
			permissionValue:        `["viewonly", "oncall", "billing"]`,
			expectedPermissionSets: []string{"viewonly", "oncall", "billing"},
		},
		{
			name:                   "AWS English field name",
			permissionFieldName:    "Select the production SSO role",
			permissionValue:        `["DBaaS-Prod-ViewOnly-Role", "DBaaS-Prod-OnCall-Role"]`,
			expectedPermissionSets: []string{"DBaaS-Prod-ViewOnly-Role", "DBaaS-Prod-OnCall-Role"},
		},
		// GCP permission formats
		{
			name:                   "GCP permissions",
			permissionFieldName:    "Select the GCP production SSO role",
			permissionValue:        `["DBaaS-Prod-ViewOnly-Role", "DBaaS-Prod-Admin-Role"]`,
			expectedPermissionSets: []string{"DBaaS-Prod-ViewOnly-Role", "DBaaS-Prod-Admin-Role"},
		},
		// Azure permission formats
		{
			name:                   "Azure permissions",
			permissionFieldName:    "Select the Azure production SSO role",
			permissionValue:        `["Contributor", "Reader"]`,
			expectedPermissionSets: []string{"Contributor", "Reader"},
		},
		// Alibaba permission formats
		{
			name:                   "Alibaba permissions",
			permissionFieldName:    "Select the Alibaba production SSO role",
			permissionValue:        `["Admin", "ReadOnly"]`,
			expectedPermissionSets: []string{"Admin", "ReadOnly"},
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			// Determine cloud type based on field name
			cloudType := "AWS"
			if strings.Contains(tc.permissionFieldName, "GCP") {
				cloudType = "GCP"
			} else if strings.Contains(tc.permissionFieldName, "Azure") {
				cloudType = "Azure"
			} else if strings.Contains(tc.permissionFieldName, "Alibaba") {
				cloudType = "Alibaba"
			}

			// Build appropriate form fields based on cloud type
			formFields := buildFormFieldsForCloudType(cloudType, tc.permissionFieldName, tc.permissionValue)

			formJSON, err := json.Marshal(formFields)
			require.NoError(t, err)

			response := InstanceDetailResponse{
				Code: 0,
				Msg:  "success",
				Data: InstanceDetailData{
					InstanceCode: "test-instance",
					Status:       "APPROVED",
					Form:         string(formJSON),
				},
			}

			responseJSON, err := json.Marshal(response)
			require.NoError(t, err)

			data, err := parser.ParseInstanceDetail(responseJSON)
			require.NoError(t, err)
			assert.Equal(t, tc.expectedPermissionSets, data.PermissionSets,
				"Permission sets should match for field %q", tc.permissionFieldName)
		})
	}
}

// buildFormFieldsForCloudType creates form fields appropriate for the given cloud type
func buildFormFieldsForCloudType(cloudType, permFieldName, permValue string) []FormField {
	fields := []FormField{
		{
			ID:    "email",
			Name:  "申请人邮箱",
			Type:  "input",
			Value: json.RawMessage(`"user@pingcap.com"`),
		},
		{
			ID:    "app_type",
			Name:  "申请人选择申请类型",
			Type:  "radioV2",
			Value: json.RawMessage(`"生产账号申请（SSO）"`),
		},
	}

	// Add cloud-specific account field
	switch cloudType {
	case "GCP":
		fields = append(fields,
			FormField{
				ID:    "cloud_type",
				Name:  "GCP Account",
				Type:  "radioV2",
				Value: json.RawMessage(`"GCP"`),
			},
			FormField{
				ID:    "account",
				Name:  "GCP Project ID",
				Type:  "radioV2",
				Value: json.RawMessage(`"tidbcloud-prod-000"`),
			},
		)
	case "Azure":
		fields = append(fields,
			FormField{
				ID:    "cloud_type",
				Name:  "Azure Account",
				Type:  "radioV2",
				Value: json.RawMessage(`"Azure"`),
			},
			FormField{
				ID:    "account",
				Name:  "Azure Subscription",
				Type:  "radioV2",
				Value: json.RawMessage(`"tidb-dedicated-prod-controlplane"`),
			},
		)
	case "Alibaba":
		fields = append(fields,
			FormField{
				ID:    "cloud_type",
				Name:  "Alibaba Account",
				Type:  "radioV2",
				Value: json.RawMessage(`"Alibaba Prod (#5480039859161595)"`),
			},
		)
	default: // AWS
		fields = append(fields,
			FormField{
				ID:    "account",
				Name:  "生产账号选择",
				Type:  "radioV2",
				Value: json.RawMessage(`"AWS Prod (#557537366020)"`),
			},
		)
	}

	// Add permission field
	fields = append(fields, FormField{
		ID:    "permission",
		Name:  permFieldName,
		Type:  "checkboxV2",
		Value: json.RawMessage(permValue),
	})

	return fields
}

// TestCompatibility_CloudTypeDetection verifies that cloud type detection
// produces the same results as the legacy Is_AWS_GCP_Azure_Alibaba function.
//
// Legacy function: Is_AWS_GCP_Azure_Alibaba(account string) string
// Uses hardcoded switch-case to determine cloud type from account ID
func TestCompatibility_CloudTypeDetection(t *testing.T) {
	for accountID, expectedCloudType := range LegacyCloudAccountMapping {
		t.Run(accountID, func(t *testing.T) {
			// Simulate the legacy detection logic
			detectedType := legacyCloudTypeDetection(accountID)
			assert.Equal(t, expectedCloudType, detectedType,
				"Cloud type for account %q should be %q but got %q",
				accountID, expectedCloudType, detectedType)
		})
	}
}

// legacyCloudTypeDetection simulates the legacy Is_AWS_GCP_Azure_Alibaba function
func legacyCloudTypeDetection(account string) string {
	account = strings.TrimSpace(account)
	switch account {
	case "557537366020", "380838443567", "143458967504", "730335266318",
		"886436949658", "182399704004", "632330501419", "296171618728":
		return "AWS"
	case "tidbcloud-prod-000", "dbaas-prod", "gcp-autonomous-prod",
		"tidbcloud-auth0", "tidbcloud-test":
		return "GCP"
	case "tidb-dedicated-prod-controlplane", "tidb-dedicated-prod-dataplane-000", "tidb-o11y":
		return "Azure"
	case "5480039859161595", "5108739859105002":
		return "Alibaba"
	}
	return ""
}

// TestCompatibility_AppTypeDetection verifies that application type detection
// produces the same results as the legacy code.
//
// Legacy patterns:
// - Chinese: "生产账号申请（SSO）"
// - English: "Production account application（SSO）"
func TestCompatibility_AppTypeDetection(t *testing.T) {
	parser := NewParser()

	testCases := []struct {
		name            string
		appTypeValue    string
		expectedAppType bool
	}{
		{
			name:            "Chinese SSO type",
			appTypeValue:    "生产账号申请（SSO）",
			expectedAppType: true,
		},
		{
			name:            "English SSO type",
			appTypeValue:    "Production account application（SSO）",
			expectedAppType: true,
		},
		{
			name:            "Other type - should be false",
			appTypeValue:    "其他申请类型",
			expectedAppType: false,
		},
		{
			name:            "Permission change type - should be false",
			appTypeValue:    "生产权限变更",
			expectedAppType: false,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			formFields := []FormField{
				{
					ID:    "email",
					Name:  "申请人邮箱",
					Type:  "input",
					Value: json.RawMessage(`"user@pingcap.com"`),
				},
				{
					ID:    "app_type",
					Name:  "申请人选择申请类型",
					Type:  "radioV2",
					Value: json.RawMessage(`"` + tc.appTypeValue + `"`),
				},
				{
					ID:    "account",
					Name:  "生产账号选择",
					Type:  "radioV2",
					Value: json.RawMessage(`"AWS Prod (#557537366020)"`),
				},
				{
					ID:    "role",
					Name:  "选择生产 SSO Role",
					Type:  "checkboxV2",
					Value: json.RawMessage(`["viewonly"]`),
				},
			}

			formJSON, err := json.Marshal(formFields)
			require.NoError(t, err)

			response := InstanceDetailResponse{
				Code: 0,
				Msg:  "success",
				Data: InstanceDetailData{
					InstanceCode: "test-instance",
					Status:       "APPROVED",
					Form:         string(formJSON),
				},
			}

			responseJSON, err := json.Marshal(response)
			require.NoError(t, err)

			data, err := parser.ParseInstanceDetail(responseJSON)
			require.NoError(t, err)
			assert.Equal(t, tc.expectedAppType, data.AppType,
				"AppType for %q should be %v", tc.appTypeValue, tc.expectedAppType)
		})
	}
}

// TestCompatibility_TimeExpiration verifies that time expiration detection
// produces the same results as the legacy Over_Time function.
//
// Legacy function: Over_Time(StrTime string) bool
// Returns true if the given time is in the past (expired)
func TestCompatibility_TimeExpiration(t *testing.T) {
	parser := NewParser()

	// Test with a past time (should be expired)
	pastTime := time.Now().Add(-24 * time.Hour).Format(time.RFC3339)
	// Test with a future time (should not be expired)
	futureTime := time.Now().Add(24 * time.Hour).Format(time.RFC3339)

	testCases := []struct {
		name            string
		endTime         string
		expectedExpired bool
	}{
		{
			name:            "past time - expired",
			endTime:         pastTime,
			expectedExpired: true,
		},
		{
			name:            "future time - not expired",
			endTime:         futureTime,
			expectedExpired: false,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			formFields := []FormField{
				{
					ID:    "email",
					Name:  "申请人邮箱",
					Type:  "input",
					Value: json.RawMessage(`"user@pingcap.com"`),
				},
				{
					ID:    "app_type",
					Name:  "申请人选择申请类型",
					Type:  "radioV2",
					Value: json.RawMessage(`"生产账号申请（SSO）"`),
				},
				{
					ID:    "account",
					Name:  "生产账号选择",
					Type:  "radioV2",
					Value: json.RawMessage(`"AWS Prod (#557537366020)"`),
				},
				{
					ID:    "role",
					Name:  "选择生产 SSO Role",
					Type:  "checkboxV2",
					Value: json.RawMessage(`["viewonly"]`),
				},
				{
					ID:    "time",
					Name:  "申请时间",
					Type:  "dateInterval",
					Value: json.RawMessage(`{"start": "2024-01-01T00:00:00+08:00", "end": "` + tc.endTime + `"}`),
				},
			}

			formJSON, err := json.Marshal(formFields)
			require.NoError(t, err)

			response := InstanceDetailResponse{
				Code: 0,
				Msg:  "success",
				Data: InstanceDetailData{
					InstanceCode: "test-instance",
					Status:       "APPROVED",
					Form:         string(formJSON),
				},
			}

			responseJSON, err := json.Marshal(response)
			require.NoError(t, err)

			data, err := parser.ParseInstanceDetail(responseJSON)
			require.NoError(t, err)
			assert.Equal(t, tc.expectedExpired, data.IsExpired,
				"IsExpired should be %v for end time %s", tc.expectedExpired, tc.endTime)
		})
	}
}

// TestCompatibility_ApprovalStatus verifies that approval status detection
// produces the same results as the legacy code.
//
// Legacy patterns:
// - "status":"PENDING" -> isapproved = false
// - "status":"APPROVED" -> isapproved = true
func TestCompatibility_ApprovalStatus(t *testing.T) {
	parser := NewParser()

	testCases := []struct {
		name             string
		status           string
		expectedApproved bool
	}{
		{
			name:             "APPROVED status",
			status:           "APPROVED",
			expectedApproved: true,
		},
		{
			name:             "PENDING status",
			status:           "PENDING",
			expectedApproved: false,
		},
		{
			name:             "REJECTED status",
			status:           "REJECTED",
			expectedApproved: false,
		},
		{
			name:             "CANCELED status",
			status:           "CANCELED",
			expectedApproved: false,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			formFields := []FormField{
				{
					ID:    "email",
					Name:  "申请人邮箱",
					Type:  "input",
					Value: json.RawMessage(`"user@pingcap.com"`),
				},
				{
					ID:    "app_type",
					Name:  "申请人选择申请类型",
					Type:  "radioV2",
					Value: json.RawMessage(`"生产账号申请（SSO）"`),
				},
				{
					ID:    "account",
					Name:  "生产账号选择",
					Type:  "radioV2",
					Value: json.RawMessage(`"AWS Prod (#557537366020)"`),
				},
				{
					ID:    "role",
					Name:  "选择生产 SSO Role",
					Type:  "checkboxV2",
					Value: json.RawMessage(`["viewonly"]`),
				},
			}

			formJSON, err := json.Marshal(formFields)
			require.NoError(t, err)

			response := InstanceDetailResponse{
				Code: 0,
				Msg:  "success",
				Data: InstanceDetailData{
					InstanceCode: "test-instance",
					Status:       tc.status,
					Form:         string(formJSON),
				},
			}

			responseJSON, err := json.Marshal(response)
			require.NoError(t, err)

			data, err := parser.ParseInstanceDetail(responseJSON)
			require.NoError(t, err)
			assert.Equal(t, tc.expectedApproved, data.IsApproved,
				"IsApproved should be %v for status %s", tc.expectedApproved, tc.status)
		})
	}
}

// TestCompatibility_DayCalculation verifies that day number calculation
// produces the same results as the legacy Minus_Time function.
//
// Legacy function: Minus_Time(start_time string, end_time string) (string, error)
// Calculates the number of days between start and end time
func TestCompatibility_DayCalculation(t *testing.T) {
	parser := NewParser()

	testCases := []struct {
		name         string
		startTime    string
		endTime      string
		expectedDays int
	}{
		{
			name:         "9 days",
			startTime:    "2024-01-01T00:00:00+08:00",
			endTime:      "2024-01-10T00:00:00+08:00",
			expectedDays: 9,
		},
		{
			name:         "1 day",
			startTime:    "2024-01-01T00:00:00+08:00",
			endTime:      "2024-01-02T00:00:00+08:00",
			expectedDays: 1,
		},
		{
			name:         "same day - should be 1",
			startTime:    "2024-01-01T00:00:00+08:00",
			endTime:      "2024-01-01T12:00:00+08:00",
			expectedDays: 1,
		},
		{
			name:         "30 days",
			startTime:    "2024-01-01T00:00:00+08:00",
			endTime:      "2024-01-31T00:00:00+08:00",
			expectedDays: 30,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			formFields := []FormField{
				{
					ID:    "email",
					Name:  "申请人邮箱",
					Type:  "input",
					Value: json.RawMessage(`"user@pingcap.com"`),
				},
				{
					ID:    "app_type",
					Name:  "申请人选择申请类型",
					Type:  "radioV2",
					Value: json.RawMessage(`"生产账号申请（SSO）"`),
				},
				{
					ID:    "account",
					Name:  "生产账号选择",
					Type:  "radioV2",
					Value: json.RawMessage(`"AWS Prod (#557537366020)"`),
				},
				{
					ID:    "role",
					Name:  "选择生产 SSO Role",
					Type:  "checkboxV2",
					Value: json.RawMessage(`["viewonly"]`),
				},
				{
					ID:    "time",
					Name:  "申请时间",
					Type:  "dateInterval",
					Value: json.RawMessage(`{"start": "` + tc.startTime + `", "end": "` + tc.endTime + `"}`),
				},
			}

			formJSON, err := json.Marshal(formFields)
			require.NoError(t, err)

			response := InstanceDetailResponse{
				Code: 0,
				Msg:  "success",
				Data: InstanceDetailData{
					InstanceCode: "test-instance",
					Status:       "APPROVED",
					Form:         string(formJSON),
				},
			}

			responseJSON, err := json.Marshal(response)
			require.NoError(t, err)

			data, err := parser.ParseInstanceDetail(responseJSON)
			require.NoError(t, err)
			assert.Equal(t, tc.expectedDays, data.DayNum,
				"DayNum should be %d for period %s to %s", tc.expectedDays, tc.startTime, tc.endTime)
		})
	}
}

// TestCompatibility_FullWorkflow tests a complete approval workflow
// to ensure end-to-end compatibility with the legacy system.
func TestCompatibility_FullWorkflow(t *testing.T) {
	parser := NewParser()

	// Simulate a complete AWS approval workflow
	t.Run("AWS full workflow", func(t *testing.T) {
		formFields := []FormField{
			{
				ID:    "widget1",
				Name:  "申请人邮箱",
				Type:  "input",
				Value: json.RawMessage(`"developer@pingcap.com"`),
			},
			{
				ID:    "widget2",
				Name:  "申请人选择申请类型",
				Type:  "radioV2",
				Value: json.RawMessage(`"生产账号申请（SSO）"`),
			},
			{
				ID:    "widget3",
				Name:  "生产账号选择",
				Type:  "radioV2",
				Value: json.RawMessage(`"AWS Production Main (#557537366020)"`),
			},
			{
				ID:    "widget4",
				Name:  "选择生产 SSO Role",
				Type:  "checkboxV2",
				Value: json.RawMessage(`["viewonly", "oncall"]`),
			},
			{
				ID:    "widget5",
				Name:  "申请时间",
				Type:  "dateInterval",
				Value: json.RawMessage(`{"start": "2024-06-01T00:00:00+08:00", "end": "2024-06-10T00:00:00+08:00"}`),
			},
		}

		formJSON, err := json.Marshal(formFields)
		require.NoError(t, err)

		response := InstanceDetailResponse{
			Code: 0,
			Msg:  "success",
			Data: InstanceDetailData{
				InstanceCode: "81762D1E-68FE-4448-89C4-5F14288778C8",
				Status:       "APPROVED",
				Form:         string(formJSON),
			},
		}

		responseJSON, err := json.Marshal(response)
		require.NoError(t, err)

		data, err := parser.ParseInstanceDetail(responseJSON)
		require.NoError(t, err)

		// Verify all fields match expected legacy behavior
		assert.Equal(t, "developer@pingcap.com", data.Email)
		assert.True(t, data.AppType)
		assert.Equal(t, "557537366020", data.AccountID)
		assert.Equal(t, []string{"viewonly", "oncall"}, data.PermissionSets)
		assert.True(t, data.IsApproved)
		assert.Equal(t, "AWS", data.CloudType)
		assert.Equal(t, 9, data.DayNum)

		// Verify IsValidApprovalData matches legacy validation
		assert.True(t, data.IsValidApprovalData())
	})

	// Simulate a complete GCP approval workflow
	t.Run("GCP full workflow", func(t *testing.T) {
		formFields := []FormField{
			{
				ID:    "widget1",
				Name:  "applicant email（xxx@pingcap.com）",
				Type:  "input",
				Value: json.RawMessage(`"gcpdev@pingcap.com"`),
			},
			{
				ID:    "widget2",
				Name:  "Applicant selects application type",
				Type:  "radioV2",
				Value: json.RawMessage(`"Production account application（SSO）"`),
			},
			{
				ID:    "widget3",
				Name:  "GCP Account",
				Type:  "radioV2",
				Value: json.RawMessage(`"GCP"`),
			},
			{
				ID:    "widget4",
				Name:  "GCP Project ID",
				Type:  "radioV2",
				Value: json.RawMessage(`"tidbcloud-prod-000"`),
			},
			{
				ID:    "widget5",
				Name:  "Select the GCP production SSO role",
				Type:  "checkboxV2",
				Value: json.RawMessage(`["DBaaS-Prod-ViewOnly-Role"]`),
			},
			{
				ID:    "widget6",
				Name:  "申请时间",
				Type:  "dateInterval",
				Value: json.RawMessage(`{"start": "2024-06-01T00:00:00+08:00", "end": "2024-06-15T00:00:00+08:00"}`),
			},
		}

		formJSON, err := json.Marshal(formFields)
		require.NoError(t, err)

		response := InstanceDetailResponse{
			Code: 0,
			Msg:  "success",
			Data: InstanceDetailData{
				InstanceCode: "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
				Status:       "APPROVED",
				Form:         string(formJSON),
			},
		}

		responseJSON, err := json.Marshal(response)
		require.NoError(t, err)

		data, err := parser.ParseInstanceDetail(responseJSON)
		require.NoError(t, err)

		// Verify all fields match expected legacy behavior
		assert.Equal(t, "gcpdev@pingcap.com", data.Email)
		assert.True(t, data.AppType)
		assert.Equal(t, "tidbcloud-prod-000", data.AccountID)
		assert.Equal(t, []string{"DBaaS-Prod-ViewOnly-Role"}, data.PermissionSets)
		assert.True(t, data.IsApproved)
		assert.Equal(t, "GCP", data.CloudType)
		assert.Equal(t, 14, data.DayNum)
	})
}

// TestCompatibility_NotificationMessageFormat verifies that notification messages
// maintain the same format as the legacy code.
func TestCompatibility_NotificationMessageFormat(t *testing.T) {
	// Test that notification messages contain expected content patterns
	testCases := []struct {
		name           string
		cloudType      string
		permissionSets []string
		messageType    string // "added", "expiring", "removed"
	}{
		{
			name:           "AWS permission added",
			cloudType:      "AWS",
			permissionSets: []string{"viewonly"},
			messageType:    "added",
		},
		{
			name:           "GCP permission expiring",
			cloudType:      "GCP",
			permissionSets: []string{"DBaaS-Prod-ViewOnly-Role"},
			messageType:    "expiring",
		},
		{
			name:           "Azure permission removed",
			cloudType:      "Azure",
			permissionSets: []string{"Contributor"},
			messageType:    "removed",
		},
		{
			name:           "Alibaba permission added",
			cloudType:      "Alibaba",
			permissionSets: []string{"Admin"},
			messageType:    "added",
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			data := &ApprovalData{
				Email:          "user@pingcap.com",
				CloudType:      tc.cloudType,
				PermissionSets: tc.permissionSets,
			}

			// Create notification service with mock client
			ns := &NotificationService{}

			var message string
			switch tc.messageType {
			case "added":
				message = ns.formatPermissionAddedMessage(data)
			case "expiring":
				message = ns.formatPermissionExpiringMessage(data, 3)
			case "removed":
				message = ns.formatPermissionRemovedMessage(data)
			}

			// Verify message contains expected patterns from legacy code
			assert.Contains(t, message, tc.cloudType+" SSO Permission")
			assert.Contains(t, message, tc.permissionSets[0])

			switch tc.messageType {
			case "added":
				assert.Contains(t, message, "已经授予完成")
			case "expiring":
				assert.Contains(t, message, "授权已经过期")
				assert.Contains(t, message, "3 天后自动回收")
			case "removed":
				assert.Contains(t, message, "已经被系统自动回收")
			}
		})
	}
}

// TestCompatibility_APIRequestFormat verifies that API request formats
// are compatible with the Feishu API expectations.
func TestCompatibility_APIRequestFormat(t *testing.T) {
	// Verify token request format
	t.Run("token request format", func(t *testing.T) {
		req := tokenRequest{
			AppID:     "test_app_id",
			AppSecret: "test_app_secret",
		}

		jsonBytes, err := json.Marshal(req)
		require.NoError(t, err)

		// Verify JSON structure matches legacy format
		var parsed map[string]string
		err = json.Unmarshal(jsonBytes, &parsed)
		require.NoError(t, err)

		assert.Equal(t, "test_app_id", parsed["app_id"])
		assert.Equal(t, "test_app_secret", parsed["app_secret"])
	})

	// Verify instance list response parsing
	t.Run("instance list response format", func(t *testing.T) {
		responseJSON := `{
			"code": 0,
			"msg": "success",
			"data": {
				"instance_code_list": ["81762D1E-68FE-4448-89C4-5F14288778C8", "A1B2C3D4-E5F6-7890-ABCD-EF1234567890"],
				"page_token": "",
				"has_more": false
			}
		}`

		var resp instanceListResponse
		err := json.Unmarshal([]byte(responseJSON), &resp)
		require.NoError(t, err)

		assert.Equal(t, 0, resp.Code)
		assert.Len(t, resp.Data.InstanceCodeList, 2)
		assert.Equal(t, "81762D1E-68FE-4448-89C4-5F14288778C8", resp.Data.InstanceCodeList[0])
	})

	// Verify user ID response parsing
	t.Run("user ID response format", func(t *testing.T) {
		responseJSON := `{
			"code": 0,
			"msg": "success",
			"data": {
				"user_list": [
					{
						"user_id": "ou_test123456",
						"email": "user@pingcap.com"
					}
				]
			}
		}`

		var resp userIDResponse
		err := json.Unmarshal([]byte(responseJSON), &resp)
		require.NoError(t, err)

		assert.Equal(t, 0, resp.Code)
		assert.Len(t, resp.Data.UserList, 1)
		assert.Equal(t, "ou_test123456", resp.Data.UserList[0].UserID)
	})
}

// TestCompatibility_InteractiveCardFormat verifies that interactive card messages
// are formatted correctly for Feishu.
func TestCompatibility_InteractiveCardFormat(t *testing.T) {
	title := "Test Title"
	message := "Test message content"

	cardJSON := buildInteractiveCard(title, message)

	// Parse the card JSON to verify structure
	var card map[string]interface{}
	err := json.Unmarshal([]byte(cardJSON), &card)
	require.NoError(t, err)

	// Verify card structure
	assert.Contains(t, card, "config")
	assert.Contains(t, card, "header")
	assert.Contains(t, card, "elements")

	// Verify header
	header := card["header"].(map[string]interface{})
	assert.Equal(t, "turquoise", header["template"])

	headerTitle := header["title"].(map[string]interface{})
	assert.Equal(t, title, headerTitle["content"])
	assert.Equal(t, "plain_text", headerTitle["tag"])

	// Verify elements
	elements := card["elements"].([]interface{})
	assert.Len(t, elements, 1)

	element := elements[0].(map[string]interface{})
	assert.Equal(t, "div", element["tag"])

	text := element["text"].(map[string]interface{})
	assert.Equal(t, message, text["content"])
	assert.Equal(t, "lark_md", text["tag"])
}
