package service_test

import (
	"context"
	"testing"

	"github.com/user-management-system/internal/domain"
	"github.com/user-management-system/internal/repository"
	"github.com/user-management-system/internal/service"
	gormsqlite "gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// =============================================================================
// Custom Field Service Tests
// =============================================================================

func setupCustomFieldTestEnv(t *testing.T) (*service.CustomFieldService, *gorm.DB) {
	t.Helper()

	db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{
		DriverName: "sqlite",
		DSN:        "file:customfield_test?mode=memory&cache=shared",
	}), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Silent),
	})
	if err != nil {
		t.Fatalf("failed to connect database: %v", err)
	}

	if err := db.AutoMigrate(&domain.CustomField{}, &domain.UserCustomFieldValue{}); err != nil {
		t.Fatalf("failed to migrate: %v", err)
	}

	fieldRepo := repository.NewCustomFieldRepository(db)
	valueRepo := repository.NewUserCustomFieldValueRepository(db)
	svc := service.NewCustomFieldService(fieldRepo, valueRepo)

	return svc, db
}

func TestCustomFieldService_CreateField(t *testing.T) {
	svc, _ := setupCustomFieldTestEnv(t)
	ctx := context.Background()

	t.Run("Create field success", func(t *testing.T) {
		req := &service.CreateFieldRequest{
			Name:     "测试字段",
			FieldKey: "test_field",
			Type:     int(domain.CustomFieldTypeString),
			Required: false,
		}
		field, err := svc.CreateField(ctx, req)
		if err != nil {
			t.Fatalf("CreateField failed: %v", err)
		}
		if field.FieldKey != "test_field" {
			t.Errorf("Expected field key 'test_field', got %s", field.FieldKey)
		}
	})

	t.Run("Create field with duplicate key", func(t *testing.T) {
		req := &service.CreateFieldRequest{
			Name:     "重复字段",
			FieldKey: "test_field", // duplicate
			Type:     int(domain.CustomFieldTypeString),
		}
		_, err := svc.CreateField(ctx, req)
		if err == nil {
			t.Error("Expected error for duplicate field key")
		}
	})

	t.Run("Create number field", func(t *testing.T) {
		req := &service.CreateFieldRequest{
			Name:     "数字字段",
			FieldKey: "number_field",
			Type:     int(domain.CustomFieldTypeNumber),
			MinVal:   0,
			MaxVal:   100,
		}
		field, err := svc.CreateField(ctx, req)
		if err != nil {
			t.Fatalf("CreateField failed: %v", err)
		}
		if field.Type != domain.CustomFieldTypeNumber {
			t.Errorf("Expected type number, got %d", field.Type)
		}
	})

	t.Run("Create boolean field", func(t *testing.T) {
		req := &service.CreateFieldRequest{
			Name:     "布尔字段",
			FieldKey: "bool_field",
			Type:     int(domain.CustomFieldTypeBoolean),
		}
		_, err := svc.CreateField(ctx, req)
		if err != nil {
			t.Fatalf("CreateField failed: %v", err)
		}
	})

	t.Run("Create date field", func(t *testing.T) {
		req := &service.CreateFieldRequest{
			Name:     "日期字段",
			FieldKey: "date_field",
			Type:     int(domain.CustomFieldTypeDate),
		}
		_, err := svc.CreateField(ctx, req)
		if err != nil {
			t.Fatalf("CreateField failed: %v", err)
		}
	})
}

func TestCustomFieldService_UpdateField(t *testing.T) {
	svc, _ := setupCustomFieldTestEnv(t)
	ctx := context.Background()

	// Create test field
	req := &service.CreateFieldRequest{
		Name:     "更新测试",
		FieldKey: "update_field",
		Type:     int(domain.CustomFieldTypeString),
	}
	field, _ := svc.CreateField(ctx, req)

	t.Run("Update field name", func(t *testing.T) {
		updateReq := &service.UpdateFieldRequest{
			Name: "更新后名称",
		}
		updated, err := svc.UpdateField(ctx, field.ID, updateReq)
		if err != nil {
			t.Fatalf("UpdateField failed: %v", err)
		}
		if updated.Name != "更新后名称" {
			t.Errorf("Expected name '更新后名称', got %s", updated.Name)
		}
	})

	t.Run("Update field required", func(t *testing.T) {
		required := true
		updateReq := &service.UpdateFieldRequest{
			Required: &required,
		}
		updated, err := svc.UpdateField(ctx, field.ID, updateReq)
		if err != nil {
			t.Fatalf("UpdateField failed: %v", err)
		}
		if !updated.Required {
			t.Error("Expected required to be true")
		}
	})

	t.Run("Update non-existent field", func(t *testing.T) {
		updateReq := &service.UpdateFieldRequest{
			Name: "不存在",
		}
		_, err := svc.UpdateField(ctx, 9999, updateReq)
		if err == nil {
			t.Error("Expected error for non-existent field")
		}
	})
}

func TestCustomFieldService_DeleteField(t *testing.T) {
	svc, _ := setupCustomFieldTestEnv(t)
	ctx := context.Background()

	t.Run("Delete field success", func(t *testing.T) {
		req := &service.CreateFieldRequest{
			Name:     "待删除字段",
			FieldKey: "delete_field",
			Type:     int(domain.CustomFieldTypeString),
		}
		field, _ := svc.CreateField(ctx, req)

		err := svc.DeleteField(ctx, field.ID)
		if err != nil {
			t.Fatalf("DeleteField failed: %v", err)
		}
	})

	t.Run("Delete non-existent field", func(t *testing.T) {
		err := svc.DeleteField(ctx, 9999)
		if err == nil {
			t.Error("Expected error for non-existent field")
		}
	})
}

func TestCustomFieldService_GetField(t *testing.T) {
	svc, _ := setupCustomFieldTestEnv(t)
	ctx := context.Background()

	req := &service.CreateFieldRequest{
		Name:     "获取测试",
		FieldKey: "get_field",
		Type:     int(domain.CustomFieldTypeString),
	}
	created, _ := svc.CreateField(ctx, req)

	t.Run("Get field success", func(t *testing.T) {
		field, err := svc.GetField(ctx, created.ID)
		if err != nil {
			t.Fatalf("GetField failed: %v", err)
		}
		if field.FieldKey != "get_field" {
			t.Errorf("Expected field key 'get_field', got %s", field.FieldKey)
		}
	})
}

func TestCustomFieldService_ListFields(t *testing.T) {
	svc, _ := setupCustomFieldTestEnv(t)
	ctx := context.Background()

	// Create test fields
	for i := 0; i < 3; i++ {
		req := &service.CreateFieldRequest{
			Name:     "列表字段",
			FieldKey: string(rune('a' + i)),
			Type:     int(domain.CustomFieldTypeString),
		}
		svc.CreateField(ctx, req)
	}

	t.Run("List fields", func(t *testing.T) {
		fields, err := svc.ListFields(ctx)
		if err != nil {
			t.Fatalf("ListFields failed: %v", err)
		}
		if len(fields) < 3 {
			t.Errorf("Expected at least 3 fields, got %d", len(fields))
		}
	})

	t.Run("List all fields", func(t *testing.T) {
		fields, err := svc.ListAllFields(ctx)
		if err != nil {
			t.Fatalf("ListAllFields failed: %v", err)
		}
		if len(fields) < 3 {
			t.Errorf("Expected at least 3 fields, got %d", len(fields))
		}
	})
}

func TestCustomFieldService_SetUserFieldValue(t *testing.T) {
	svc, _ := setupCustomFieldTestEnv(t)
	ctx := context.Background()

	// Create test field
	req := &service.CreateFieldRequest{
		Name:     "用户字段",
		FieldKey: "user_field",
		Type:     int(domain.CustomFieldTypeString),
	}
	svc.CreateField(ctx, req)

	t.Run("Set user field value success", func(t *testing.T) {
		err := svc.SetUserFieldValue(ctx, 1, "user_field", "test value")
		if err != nil {
			t.Fatalf("SetUserFieldValue failed: %v", err)
		}
	})

	t.Run("Set user field value with non-existent field", func(t *testing.T) {
		err := svc.SetUserFieldValue(ctx, 1, "non_existent", "value")
		if err == nil {
			t.Error("Expected error for non-existent field")
		}
	})
}

func TestCustomFieldService_GetUserFieldValues(t *testing.T) {
	svc, _ := setupCustomFieldTestEnv(t)
	ctx := context.Background()

	// Create test field
	req := &service.CreateFieldRequest{
		Name:     "值字段",
		FieldKey: "value_field",
		Type:     int(domain.CustomFieldTypeString),
	}
	svc.CreateField(ctx, req)

	// Set value
	svc.SetUserFieldValue(ctx, 1, "value_field", "test value")

	t.Run("Get user field values", func(t *testing.T) {
		values, err := svc.GetUserFieldValues(ctx, 1)
		if err != nil {
			t.Fatalf("GetUserFieldValues failed: %v", err)
		}
		if len(values) == 0 {
			t.Error("Expected at least one field value")
		}
	})
}

func TestCustomFieldService_ValidateFieldValue(t *testing.T) {
	svc, _ := setupCustomFieldTestEnv(t)
	ctx := context.Background()

	t.Run("Validate required field", func(t *testing.T) {
		req := &service.CreateFieldRequest{
			Name:     "必填字段",
			FieldKey: "required_field",
			Type:     int(domain.CustomFieldTypeString),
			Required: true,
		}
		svc.CreateField(ctx, req)

		err := svc.SetUserFieldValue(ctx, 1, "required_field", "")
		if err == nil {
			t.Error("Expected error for empty required field")
		}
	})

	t.Run("Validate number field", func(t *testing.T) {
		req := &service.CreateFieldRequest{
			Name:     "数字验证",
			FieldKey: "num_validate",
			Type:     int(domain.CustomFieldTypeNumber),
			MinVal:   0,
			MaxVal:   100,
		}
		svc.CreateField(ctx, req)

		// Valid number
		err := svc.SetUserFieldValue(ctx, 1, "num_validate", "50")
		if err != nil {
			t.Fatalf("SetUserFieldValue failed: %v", err)
		}

		// Invalid number
		err = svc.SetUserFieldValue(ctx, 1, "num_validate", "not_a_number")
		if err == nil {
			t.Error("Expected error for invalid number")
		}

		// Number too large
		err = svc.SetUserFieldValue(ctx, 1, "num_validate", "200")
		if err == nil {
			t.Error("Expected error for number too large")
		}
	})

	t.Run("Validate boolean field", func(t *testing.T) {
		req := &service.CreateFieldRequest{
			Name:     "布尔验证",
			FieldKey: "bool_validate",
			Type:     int(domain.CustomFieldTypeBoolean),
		}
		svc.CreateField(ctx, req)

		// Valid boolean
		err := svc.SetUserFieldValue(ctx, 1, "bool_validate", "true")
		if err != nil {
			t.Fatalf("SetUserFieldValue failed: %v", err)
		}

		// Invalid boolean
		err = svc.SetUserFieldValue(ctx, 1, "bool_validate", "yes")
		if err == nil {
			t.Error("Expected error for invalid boolean")
		}
	})

	t.Run("Validate date field", func(t *testing.T) {
		req := &service.CreateFieldRequest{
			Name:     "日期验证",
			FieldKey: "date_validate",
			Type:     int(domain.CustomFieldTypeDate),
		}
		svc.CreateField(ctx, req)

		// Valid date
		err := svc.SetUserFieldValue(ctx, 1, "date_validate", "2024-01-15")
		if err != nil {
			t.Fatalf("SetUserFieldValue failed: %v", err)
		}

		// Invalid date
		err = svc.SetUserFieldValue(ctx, 1, "date_validate", "not_a_date")
		if err == nil {
			t.Error("Expected error for invalid date")
		}
	})
}

func TestCustomFieldService_DeleteUserFieldValue(t *testing.T) {
	svc, _ := setupCustomFieldTestEnv(t)
	ctx := context.Background()

	// Create test field
	req := &service.CreateFieldRequest{
		Name:     "删除值字段",
		FieldKey: "delete_value_field",
		Type:     int(domain.CustomFieldTypeString),
	}
	svc.CreateField(ctx, req)

	// Set value
	svc.SetUserFieldValue(ctx, 1, "delete_value_field", "test")

	t.Run("Delete user field value", func(t *testing.T) {
		err := svc.DeleteUserFieldValue(ctx, 1, "delete_value_field")
		if err != nil {
			t.Fatalf("DeleteUserFieldValue failed: %v", err)
		}
	})

	t.Run("Delete non-existent field value", func(t *testing.T) {
		err := svc.DeleteUserFieldValue(ctx, 1, "non_existent")
		if err == nil {
			t.Error("Expected error for non-existent field")
		}
	})
}

func TestCustomFieldService_BatchSetUserFieldValues(t *testing.T) {
	svc, _ := setupCustomFieldTestEnv(t)
	ctx := context.Background()

	// Create test fields
	svc.CreateField(ctx, &service.CreateFieldRequest{
		Name:     "批量字段1",
		FieldKey: "batch_field1",
		Type:     int(domain.CustomFieldTypeString),
	})
	svc.CreateField(ctx, &service.CreateFieldRequest{
		Name:     "批量字段2",
		FieldKey: "batch_field2",
		Type:     int(domain.CustomFieldTypeString),
	})

	t.Run("Batch set user field values success", func(t *testing.T) {
		values := map[string]string{
			"batch_field1": "value1",
			"batch_field2": "value2",
		}
		err := svc.BatchSetUserFieldValues(ctx, 1, values)
		if err != nil {
			t.Fatalf("BatchSetUserFieldValues failed: %v", err)
		}

		// Verify values were set
		userValues, err := svc.GetUserFieldValues(ctx, 1)
		if err != nil {
			t.Fatalf("GetUserFieldValues failed: %v", err)
		}
		if len(userValues) < 2 {
			t.Errorf("Expected at least 2 field values, got %d", len(userValues))
		}
	})

	t.Run("Batch set with non-existent field", func(t *testing.T) {
		values := map[string]string{
			"non_existent_field": "value",
		}
		err := svc.BatchSetUserFieldValues(ctx, 1, values)
		if err == nil {
			t.Error("Expected error for non-existent field")
		}
	})

	t.Run("Batch set with empty map", func(t *testing.T) {
		values := map[string]string{}
		err := svc.BatchSetUserFieldValues(ctx, 1, values)
		if err != nil {
			t.Fatalf("BatchSetUserFieldValues with empty map should succeed: %v", err)
		}
	})

	t.Run("Batch set with invalid value", func(t *testing.T) {
		// Create a number field with validation
		svc.CreateField(ctx, &service.CreateFieldRequest{
			Name:     "批量数字字段",
			FieldKey: "batch_number",
			Type:     int(domain.CustomFieldTypeNumber),
			MinVal:   0,
			MaxVal:   100,
		})

		values := map[string]string{
			"batch_number": "200", // exceeds max
		}
		err := svc.BatchSetUserFieldValues(ctx, 1, values)
		if err == nil {
			t.Error("Expected error for invalid value")
		}
	})
}
