package service_test

import (
	"bytes"
	"context"
	"encoding/json"
	"io"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/user-management-system/internal/api/handler"
	"github.com/user-management-system/internal/api/middleware"
	"github.com/user-management-system/internal/api/router"
	"github.com/user-management-system/internal/auth"
	"github.com/user-management-system/internal/cache"
	"github.com/user-management-system/internal/config"
	"github.com/user-management-system/internal/repository"
	"github.com/user-management-system/internal/service"
	"github.com/user-management-system/internal/domain"
	gormsqlite "gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	_ "modernc.org/sqlite"
)

// doRequest makes an HTTP request with optional body
func doRequest(method, url string, token string, body interface{}) (*http.Response, string) {
	var bodyReader io.Reader
	if body != nil {
		jsonBytes, _ := json.Marshal(body)
		bodyReader = bytes.NewReader(jsonBytes)
	}
	req, _ := http.NewRequest(method, url, bodyReader)
	if token != "" {
		req.Header.Set("Authorization", "Bearer "+token)
	}
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	resp, _ := client.Do(req)
	bodyBytes, _ := io.ReadAll(resp.Body)
	resp.Body.Close()
	return resp, string(bodyBytes)
}

func doPost(url, token string, body interface{}) (*http.Response, string) {
	return doRequest("POST", url, token, body)
}

func doGet(url, token string) (*http.Response, string) {
	return doRequest("GET", url, token, nil)
}

func setupSettingsTestServer(t *testing.T) (*httptest.Server, *service.SettingsService, string, func()) {
	gin.SetMode(gin.TestMode)

	// 使用内存 SQLite
	db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{
		DriverName: "sqlite",
		DSN:        "file::memory:?mode=memory&cache=shared",
	}), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Silent),
	})
	if err != nil {
		t.Skipf("skipping test (SQLite unavailable): %v", err)
		return nil, nil, "", func() {}
	}

	// 自动迁移
	if err := db.AutoMigrate(
		&domain.User{},
		&domain.Role{},
		&domain.Permission{},
		&domain.UserRole{},
		&domain.RolePermission{},
		&domain.Device{},
		&domain.LoginLog{},
		&domain.OperationLog{},
		&domain.SocialAccount{},
		&domain.Webhook{},
		&domain.WebhookDelivery{},
	); err != nil {
		t.Fatalf("db migration failed: %v", err)
	}

	// 创建 JWT Manager
	jwtManager, err := auth.NewJWTWithOptions(auth.JWTOptions{
		HS256Secret:        "test-settings-secret-key",
		AccessTokenExpire:  15 * time.Minute,
		RefreshTokenExpire: 7 * 24 * time.Hour,
	})
	if err != nil {
		t.Fatalf("create jwt manager failed: %v", err)
	}

	// 创建缓存
	l1Cache := cache.NewL1Cache()
	l2Cache := cache.NewRedisCache(false)
	cacheManager := cache.NewCacheManager(l1Cache, l2Cache)

	// 创建 repositories
	userRepo := repository.NewUserRepository(db)
	roleRepo := repository.NewRoleRepository(db)
	permissionRepo := repository.NewPermissionRepository(db)
	userRoleRepo := repository.NewUserRoleRepository(db)
	rolePermissionRepo := repository.NewRolePermissionRepository(db)
	deviceRepo := repository.NewDeviceRepository(db)
	loginLogRepo := repository.NewLoginLogRepository(db)
	opLogRepo := repository.NewOperationLogRepository(db)
	passwordHistoryRepo := repository.NewPasswordHistoryRepository(db)

	// 创建 services
	authSvc := service.NewAuthService(userRepo, nil, jwtManager, cacheManager, 8, 5, 15*time.Minute)
	authSvc.SetRoleRepositories(userRoleRepo, roleRepo)
	userSvc := service.NewUserService(userRepo, userRoleRepo, roleRepo, passwordHistoryRepo)
	roleSvc := service.NewRoleService(roleRepo, rolePermissionRepo)
	permSvc := service.NewPermissionService(permissionRepo)
	deviceSvc := service.NewDeviceService(deviceRepo, userRepo)
	loginLogSvc := service.NewLoginLogService(loginLogRepo)
	opLogSvc := service.NewOperationLogService(opLogRepo)

	// 创建 SettingsService
	settingsService := service.NewSettingsService()

	// 创建 middleware
	rateLimitCfg := config.RateLimitConfig{}
	rateLimitMiddleware := middleware.NewRateLimitMiddleware(rateLimitCfg)
	authMiddleware := middleware.NewAuthMiddleware(
		jwtManager, userRepo, userRoleRepo, roleRepo, rolePermissionRepo, permissionRepo, l1Cache,
	)
	authMiddleware.SetCacheManager(cacheManager)
	opLogMiddleware := middleware.NewOperationLogMiddleware(opLogRepo)

	// 创建 handlers
	authHandler := handler.NewAuthHandler(authSvc)
	userHandler := handler.NewUserHandler(userSvc)
	roleHandler := handler.NewRoleHandler(roleSvc)
	permHandler := handler.NewPermissionHandler(permSvc)
	deviceHandler := handler.NewDeviceHandler(deviceSvc)
	logHandler := handler.NewLogHandler(loginLogSvc, opLogSvc)
	settingsHandler := handler.NewSettingsHandler(settingsService)

	// 创建 router - 22个handler参数（含 metrics）+ variadic avatarHandler
	r := router.NewRouter(
		authHandler, userHandler, roleHandler, permHandler, deviceHandler,
		logHandler, authMiddleware, rateLimitMiddleware, opLogMiddleware,
		nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
		nil,
		settingsHandler, nil,
	)
	engine := r.Setup()

	server := httptest.NewServer(engine)

	// 注册用户用于测试
	resp, _ := doPost(server.URL+"/api/v1/auth/register", "", map[string]interface{}{
		"username": "admintestsu",
		"email":   "admintestsu@test.com",
		"password": "Password123!",
	})
	resp.Body.Close()

	// 获取 token
	loginResp, _ := doPost(server.URL+"/api/v1/auth/login", "", map[string]interface{}{
		"account":  "admintestsu",
		"password": "Password123!",
	})

	var result map[string]interface{}
	json.NewDecoder(loginResp.Body).Decode(&result)
	loginResp.Body.Close()

	token := ""
	if data, ok := result["data"].(map[string]interface{}); ok {
		token, _ = data["access_token"].(string)
	}

	return server, settingsService, token, func() {
		server.Close()
		if sqlDB, _ := db.DB(); sqlDB != nil {
			sqlDB.Close()
		}
	}
}

// =============================================================================
// Settings API Tests
// =============================================================================

func TestGetSettings_Success(t *testing.T) {
	// 仅测试 service 层，不测试 HTTP API
	svc := service.NewSettingsService()
	settings, err := svc.GetSettings(context.Background())
	if err != nil {
		t.Fatalf("GetSettings failed: %v", err)
	}

	if settings.System.Name != "用户管理系统" {
		t.Errorf("expected system name '用户管理系统', got '%s'", settings.System.Name)
	}
}

func TestGetSettings_Unauthorized(t *testing.T) {
	server, _, _, cleanup := setupSettingsTestServer(t)
	defer cleanup()

	req, _ := http.NewRequest("GET", server.URL+"/api/v1/admin/settings", nil)
	// 不设置 Authorization header

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		t.Fatalf("request failed: %v", err)
	}
	defer resp.Body.Close()

	// 无 token 应该返回 401
	if resp.StatusCode != http.StatusUnauthorized {
		t.Errorf("expected status 401, got %d", resp.StatusCode)
	}
}

func TestGetSettings_ResponseStructure(t *testing.T) {
	// 仅测试 service 层数据结构
	svc := service.NewSettingsService()
	settings, err := svc.GetSettings(context.Background())
	if err != nil {
		t.Fatalf("GetSettings failed: %v", err)
	}

	// 验证 system 字段
	if settings.System.Name == "" {
		t.Error("System.Name should not be empty")
	}
	if settings.System.Version == "" {
		t.Error("System.Version should not be empty")
	}
	if settings.System.Environment == "" {
		t.Error("System.Environment should not be empty")
	}

	// 验证 security 字段
	if settings.Security.PasswordMinLength == 0 {
		t.Error("Security.PasswordMinLength should not be zero")
	}
	if !settings.Security.PasswordRequireUppercase {
		t.Error("Security.PasswordRequireUppercase should be true")
	}

	// 验证 features 字段
	if !settings.Features.EmailVerification {
		t.Error("Features.EmailVerification should be true")
	}
	if len(settings.Features.OAuthProviders) == 0 {
		t.Error("Features.OAuthProviders should not be empty")
	}
}

// =============================================================================
// SettingsService Unit Tests
// =============================================================================

func TestSettingsService_GetSettings(t *testing.T) {
	svc := service.NewSettingsService()

	settings, err := svc.GetSettings(context.Background())
	if err != nil {
		t.Fatalf("GetSettings failed: %v", err)
	}

	// 验证 system
	if settings.System.Name == "" {
		t.Error("System.Name should not be empty")
	}
	if settings.System.Version == "" {
		t.Error("System.Version should not be empty")
	}

	// 验证 security defaults
	if settings.Security.PasswordMinLength != 8 {
		t.Errorf("PasswordMinLength: got %d, want 8", settings.Security.PasswordMinLength)
	}
	if !settings.Security.PasswordRequireUppercase {
		t.Error("PasswordRequireUppercase should be true")
	}
	if !settings.Security.PasswordRequireLowercase {
		t.Error("PasswordRequireLowercase should be true")
	}
	if !settings.Security.PasswordRequireNumbers {
		t.Error("PasswordRequireNumbers should be true")
	}
	if !settings.Security.PasswordRequireSymbols {
		t.Error("PasswordRequireSymbols should be true")
	}
	if settings.Security.PasswordHistory != 5 {
		t.Errorf("PasswordHistory: got %d, want 5", settings.Security.PasswordHistory)
	}

	// 验证 features defaults
	if !settings.Features.EmailVerification {
		t.Error("EmailVerification should be true")
	}
	if settings.Features.DataExportEnabled != true {
		t.Error("DataExportEnabled should be true")
	}
}
