package autoregister

import (
	"os"
	"path/filepath"
	"strings"
	"testing"

	"go.uber.org/zap"
)

func TestNewGenerator(t *testing.T) {
	logger := zap.NewNop()
	generator := NewGenerator(logger)

	if generator == nil {
		t.Fatal("Expected generator to be created")
	}

	if generator.logger != logger {
		t.Error("Expected logger to be set")
	}
}

func TestGenerateRegistrationCode(t *testing.T) {
	logger := zap.NewNop()
	generator := NewGenerator(logger)

	services := []*ServiceInfo{
		{
			PackageName: "services",
			TypeName:    "UserService",
			FilePath:    "/test/user_service.go",
			ServiceName: "userservice",
		},
		{
			PackageName: "services",
			TypeName:    "OrderService",
			FilePath:    "/test/order_service.go",
			ServiceName: "orderservice",
		},
	}

	tempDir := t.TempDir()
	outputPath := filepath.Join(tempDir, "auto_register_generated.go")

	err := generator.GenerateRegistrationCode(services, outputPath)
	if err != nil {
		t.Fatalf("Failed to generate registration code: %v", err)
	}

	// 验证文件是否创建
	if _, err := os.Stat(outputPath); os.IsNotExist(err) {
		t.Fatal("Expected output file to be created")
	}

	// 读取生成的文件内容
	content, err := os.ReadFile(outputPath)
	if err != nil {
		t.Fatalf("Failed to read generated file: %v", err)
	}

	contentStr := string(content)

	// 验证生成的代码包含预期内容
	expectedContents := []string{
		"// Code generated by go-grpc-kit autoregister. DO NOT EDIT.",
		"package main",
		"import",
		"google.golang.org/grpc",
		"AutoRegisterServices",
		"GetAutoRegisteredServices",
		"UserService",
		"OrderService",
		"userservice",
		"orderservice",
	}

	for _, expected := range expectedContents {
		if !strings.Contains(contentStr, expected) {
			t.Errorf("Generated code should contain '%s'", expected)
		}
	}
}

func TestGenerateRegistrationCodeEmptyServices(t *testing.T) {
	logger := zap.NewNop()
	generator := NewGenerator(logger)

	services := []*ServiceInfo{}

	tempDir := t.TempDir()
	outputPath := filepath.Join(tempDir, "auto_register_generated.go")

	err := generator.GenerateRegistrationCode(services, outputPath)
	if err != nil {
		t.Fatalf("Failed to generate registration code for empty services: %v", err)
	}

	// 验证文件是否创建
	if _, err := os.Stat(outputPath); os.IsNotExist(err) {
		t.Fatal("Expected output file to be created even for empty services")
	}

	// 读取生成的文件内容
	content, err := os.ReadFile(outputPath)
	if err != nil {
		t.Fatalf("Failed to read generated file: %v", err)
	}

	contentStr := string(content)

	// 验证基本结构存在
	expectedContents := []string{
		"// Code generated by go-grpc-kit autoregister. DO NOT EDIT.",
		"package main",
		"AutoRegisterServices",
		"GetAutoRegisteredServices",
	}

	for _, expected := range expectedContents {
		if !strings.Contains(contentStr, expected) {
			t.Errorf("Generated code should contain '%s'", expected)
		}
	}
}

func TestGenerateRegistrationCodeInvalidPath(t *testing.T) {
	logger := zap.NewNop()
	generator := NewGenerator(logger)

	services := []*ServiceInfo{
		{
			PackageName: "services",
			TypeName:    "UserService",
			FilePath:    "/test/user_service.go",
			ServiceName: "userservice",
		},
	}

	// 使用无效路径（只读目录）
	outputPath := "/invalid/path/auto_register_generated.go"

	err := generator.GenerateRegistrationCode(services, outputPath)
	if err == nil {
		t.Error("Expected error when using invalid output path")
	}
}

func TestExtractImports(t *testing.T) {
	logger := zap.NewNop()
	generator := NewGenerator(logger)

	services := []*ServiceInfo{
		{
			PackageName: "userservice",
			TypeName:    "UserService",
			FilePath:    "/test/pkg/userservice/user_service.go",
			ServiceName: "userservice",
		},
		{
			PackageName: "orderservice",
			TypeName:    "OrderService",
			FilePath:    "/test/pkg/orderservice/order_service.go",
			ServiceName: "orderservice",
		},
		{
			PackageName: "userservice", // 重复包名
			TypeName:    "UserProfileService",
			FilePath:    "/test/pkg/userservice/profile_service.go",
			ServiceName: "userprofileservice",
		},
	}

	imports := generator.extractImports(services)

	// 验证导入包的数量（去重后应该是2个）
	expectedImports := 2
	if len(imports) != expectedImports {
		t.Errorf("Expected %d imports, got %d", expectedImports, len(imports))
	}

	// 验证包含预期的导入
	expectedPackages := []string{"userservice", "orderservice"}
	for _, expectedPkg := range expectedPackages {
		found := false
		for _, imp := range imports {
			if strings.Contains(imp, expectedPkg) {
				found = true
				break
			}
		}
		if !found {
			t.Errorf("Expected import for package '%s' not found", expectedPkg)
		}
	}
}

func TestGenerateRegistrationCodeWithComplexServices(t *testing.T) {
	logger := zap.NewNop()
	generator := NewGenerator(logger)

	services := []*ServiceInfo{
		{
			PackageName: "user",
			TypeName:    "UserManagementService",
			FilePath:    "/test/user/management_service.go",
			ServiceName: "usermanagementservice",
		},
		{
			PackageName: "payment",
			TypeName:    "PaymentGatewayService",
			FilePath:    "/test/payment/gateway_service.go",
			ServiceName: "paymentgatewayservice",
		},
		{
			PackageName: "notification",
			TypeName:    "EmailNotificationService",
			FilePath:    "/test/notification/email_service.go",
			ServiceName: "emailnotificationservice",
		},
	}

	tempDir := t.TempDir()
	outputPath := filepath.Join(tempDir, "complex_auto_register.go")

	err := generator.GenerateRegistrationCode(services, outputPath)
	if err != nil {
		t.Fatalf("Failed to generate registration code for complex services: %v", err)
	}

	// 读取生成的文件内容
	content, err := os.ReadFile(outputPath)
	if err != nil {
		t.Fatalf("Failed to read generated file: %v", err)
	}

	contentStr := string(content)

	// 验证所有服务都被包含
	for _, service := range services {
		if !strings.Contains(contentStr, service.TypeName) {
			t.Errorf("Generated code should contain service type '%s'", service.TypeName)
		}
		if !strings.Contains(contentStr, service.ServiceName) {
			t.Errorf("Generated code should contain service name '%s'", service.ServiceName)
		}
		if !strings.Contains(contentStr, service.PackageName) {
			t.Errorf("Generated code should contain package name '%s'", service.PackageName)
		}
	}

	// 验证注册函数的结构
	if !strings.Contains(contentStr, "func AutoRegisterServices(server grpc.ServiceRegistrar)") {
		t.Error("Generated code should contain AutoRegisterServices function")
	}

	if !strings.Contains(contentStr, "func GetAutoRegisteredServices() []string") {
		t.Error("Generated code should contain GetAutoRegisteredServices function")
	}

	// 验证每个服务的注册调用
	for _, service := range services {
		expectedCall := service.PackageName + ".Register" + service.ServiceName + "Server"
		if !strings.Contains(contentStr, expectedCall) {
			t.Errorf("Generated code should contain registration call '%s'", expectedCall)
		}
	}
}

func TestGenerateRegistrationCodeDirectoryCreation(t *testing.T) {
	logger := zap.NewNop()
	generator := NewGenerator(logger)

	services := []*ServiceInfo{
		{
			PackageName: "services",
			TypeName:    "TestService",
			FilePath:    "/test/test_service.go",
			ServiceName: "testservice",
		},
	}

	tempDir := t.TempDir()
	// 创建嵌套目录路径
	outputPath := filepath.Join(tempDir, "nested", "deep", "auto_register_generated.go")

	err := generator.GenerateRegistrationCode(services, outputPath)
	if err != nil {
		t.Fatalf("Failed to generate registration code with nested directories: %v", err)
	}

	// 验证嵌套目录和文件都被创建
	if _, err := os.Stat(outputPath); os.IsNotExist(err) {
		t.Fatal("Expected output file to be created in nested directory")
	}

	// 验证目录结构
	nestedDir := filepath.Join(tempDir, "nested", "deep")
	if _, err := os.Stat(nestedDir); os.IsNotExist(err) {
		t.Fatal("Expected nested directories to be created")
	}
}