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"
)

// =============================================================================
// Export Service Tests
// =============================================================================

func setupExportTestEnv(t *testing.T) (*service.ExportService, *gorm.DB) {
	t.Helper()

	db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{
		DriverName: "sqlite",
		DSN:        "file:export_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.User{}); err != nil {
		t.Fatalf("failed to migrate: %v", err)
	}

	userRepo := repository.NewUserRepository(db)
	svc := service.NewExportService(userRepo, nil)

	return svc, db
}

func TestExportService_ExportUsers(t *testing.T) {
	svc, db := setupExportTestEnv(t)
	ctx := context.Background()

	// Create test users
	for i := 0; i < 3; i++ {
		user := &domain.User{
			Username: "export_user_" + string(rune('a'+i)),
			Password: "$2a$10$hash",
			Status:   domain.UserStatusActive,
		}
		db.Create(user)
	}

	t.Run("Export users as CSV", func(t *testing.T) {
		req := &service.ExportUsersRequest{
			Format: "csv",
		}
		data, filename, contentType, err := svc.ExportUsers(ctx, req)
		if err != nil {
			t.Fatalf("ExportUsers failed: %v", err)
		}
		if len(data) == 0 {
			t.Error("Expected export data")
		}
		if filename == "" {
			t.Error("Expected filename")
		}
		if contentType == "" {
			t.Error("Expected content type")
		}
	})

	t.Run("Export users as XLSX", func(t *testing.T) {
		req := &service.ExportUsersRequest{
			Format: "xlsx",
		}
		data, _, _, err := svc.ExportUsers(ctx, req)
		if err != nil {
			t.Fatalf("ExportUsers failed: %v", err)
		}
		if len(data) == 0 {
			t.Error("Expected export data")
		}
	})

	t.Run("Export users with invalid format", func(t *testing.T) {
		req := &service.ExportUsersRequest{
			Format: "invalid",
		}
		_, _, _, err := svc.ExportUsers(ctx, req)
		if err == nil {
			t.Error("Expected error for invalid format")
		}
	})

	t.Run("Export users with nil request", func(t *testing.T) {
		data, _, _, err := svc.ExportUsers(ctx, nil)
		if err != nil {
			t.Fatalf("ExportUsers with nil request failed: %v", err)
		}
		if len(data) == 0 {
			t.Error("Expected export data")
		}
	})
}

func TestExportService_ExportUsersCSV(t *testing.T) {
	svc, db := setupExportTestEnv(t)
	ctx := context.Background()

	// Create test user
	user := &domain.User{
		Username: "csv_user",
		Password: "$2a$10$hash",
		Status:   domain.UserStatusActive,
	}
	db.Create(user)

	t.Run("Export users CSV", func(t *testing.T) {
		data, filename, err := svc.ExportUsersCSV(ctx)
		if err != nil {
			t.Fatalf("ExportUsersCSV failed: %v", err)
		}
		if len(data) == 0 {
			t.Error("Expected CSV data")
		}
		if filename == "" {
			t.Error("Expected filename")
		}
	})
}

func TestExportService_ExportUsersXLSX(t *testing.T) {
	svc, db := setupExportTestEnv(t)
	ctx := context.Background()

	// Create test user
	user := &domain.User{
		Username: "xlsx_user",
		Password: "$2a$10$hash",
		Status:   domain.UserStatusActive,
	}
	db.Create(user)

	t.Run("Export users XLSX", func(t *testing.T) {
		data, filename, err := svc.ExportUsersXLSX(ctx)
		if err != nil {
			t.Fatalf("ExportUsersXLSX failed: %v", err)
		}
		if len(data) == 0 {
			t.Error("Expected XLSX data")
		}
		if filename == "" {
			t.Error("Expected filename")
		}
	})
}

func TestExportService_GetImportTemplate(t *testing.T) {
	svc, _ := setupExportTestEnv(t)

	t.Run("Get import template default", func(t *testing.T) {
		data, filename := svc.GetImportTemplate()
		if len(data) == 0 {
			t.Error("Expected template data")
		}
		if filename == "" {
			t.Error("Expected filename")
		}
	})

	t.Run("Get import template CSV", func(t *testing.T) {
		data, filename, contentType, err := svc.GetImportTemplateByFormat("csv")
		if err != nil {
			t.Fatalf("GetImportTemplateByFormat failed: %v", err)
		}
		if len(data) == 0 {
			t.Error("Expected template data")
		}
		if filename == "" {
			t.Error("Expected filename")
		}
		if contentType == "" {
			t.Error("Expected content type")
		}
	})

	t.Run("Get import template XLSX", func(t *testing.T) {
		data, _, _, err := svc.GetImportTemplateByFormat("xlsx")
		if err != nil {
			t.Fatalf("GetImportTemplateByFormat failed: %v", err)
		}
		if len(data) == 0 {
			t.Error("Expected template data")
		}
	})

	t.Run("Get import template invalid format", func(t *testing.T) {
		_, _, _, err := svc.GetImportTemplateByFormat("invalid")
		if err == nil {
			t.Error("Expected error for invalid format")
		}
	})
}

// =============================================================================
// Export Users CSV Extended Tests
// =============================================================================

func TestExportService_ExportUsersCSV_Extended(t *testing.T) {
	svc, db := setupExportTestEnv(t)
	ctx := context.Background()

	// Create multiple test users with various fields
	email := "export@test.com"
	phone := "13800138000"
	users := []*domain.User{
		{Username: "csv_user1", Password: "$2a$10$hash", Status: domain.UserStatusActive, Email: &email, Phone: &phone, Nickname: "User One"},
		{Username: "csv_user2", Password: "$2a$10$hash", Status: domain.UserStatusInactive},
		{Username: "csv_user3", Password: "$2a$10$hash", Status: domain.UserStatusLocked},
	}
	for _, u := range users {
		db.Create(u)
	}

	t.Run("Export users CSV with data", func(t *testing.T) {
		data, filename, err := svc.ExportUsersCSV(ctx)
		if err != nil {
			t.Fatalf("ExportUsersCSV failed: %v", err)
		}
		if len(data) == 0 {
			t.Error("Expected CSV data")
		}
		if filename == "" {
			t.Error("Expected filename")
		}
	})
}

// =============================================================================
// Import Users Tests
// =============================================================================

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

	t.Run("Import CSV with empty data", func(t *testing.T) {
		successCount, failCount, errs := svc.ImportUsersCSV(ctx, []byte(""))
		_ = failCount
		_ = errs
		// Empty data should result in 0 successful imports
		if successCount != 0 {
			t.Errorf("Expected 0 success, got %d", successCount)
		}
	})
}

// =============================================================================
// Import Users Extended Tests
// =============================================================================

func TestExportService_ImportUsers(t *testing.T) {
	svc, db := setupExportTestEnv(t)
	ctx := context.Background()

	t.Run("Import users with invalid format", func(t *testing.T) {
		successCount, _, _ := svc.ImportUsers(ctx, []byte("test"), "invalid_format")
		if successCount != 0 {
			t.Errorf("Expected 0 success for invalid format, got %d", successCount)
		}
	})

	t.Run("Import valid CSV data", func(t *testing.T) {
		csvData := "用户名,密码,邮箱,手机号,昵称\nnewuser1,Password123!,new1@test.com,13800138001,User One\nnewuser2,Password123!,new2@test.com,13800138002,User Two"
		successCount, failCount, errs := svc.ImportUsersCSV(ctx, []byte(csvData))
		if successCount != 2 {
			t.Errorf("Expected 2 successful imports, got %d, errors: %v", successCount, errs)
		}
		_ = failCount
	})

	t.Run("Import CSV with missing username", func(t *testing.T) {
		csvData := "用户名,密码\n,Password123!"
		successCount, failCount, errs := svc.ImportUsersCSV(ctx, []byte(csvData))
		if successCount != 0 {
			t.Errorf("Expected 0 success, got %d", successCount)
		}
		if failCount == 0 {
			t.Error("Expected at least one failure")
		}
		if len(errs) == 0 {
			t.Error("Expected error message")
		}
	})

	t.Run("Import CSV with missing password", func(t *testing.T) {
		csvData := "用户名,密码\nnopwduser,"
		successCount, failCount, errs := svc.ImportUsersCSV(ctx, []byte(csvData))
		if successCount != 0 {
			t.Errorf("Expected 0 success, got %d", successCount)
		}
		if failCount == 0 {
			t.Error("Expected at least one failure")
		}
		_ = errs
	})

	t.Run("Import CSV with duplicate username", func(t *testing.T) {
		// Create existing user
		db.Create(&domain.User{Username: "duplicateuser", Password: "$2a$10$hash", Status: domain.UserStatusActive})

		csvData := "用户名,密码\nduplicateuser,Password123!"
		successCount, failCount, _ := svc.ImportUsersCSV(ctx, []byte(csvData))
		if successCount != 0 {
			t.Errorf("Expected 0 success for duplicate, got %d", successCount)
		}
		if failCount == 0 {
			t.Error("Expected failure for duplicate username")
		}
	})

	t.Run("Import CSV with only headers", func(t *testing.T) {
		csvData := "用户名,密码,邮箱"
		successCount, _, _ := svc.ImportUsersCSV(ctx, []byte(csvData))
		if successCount != 0 {
			t.Errorf("Expected 0 success for header-only CSV, got %d", successCount)
		}
	})
}

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

	t.Run("Import XLSX with invalid data", func(t *testing.T) {
		successCount, _, _ := svc.ImportUsersXLSX(ctx, []byte("not a valid xlsx"))
		if successCount != 0 {
			t.Errorf("Expected 0 success for invalid XLSX, got %d", successCount)
		}
	})
}
