package services

import (
	"context"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
)

func TestAuditService_RecordLogin(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("Failed to create mock db: %v", err)
	}
	defer db.Close()

	service := NewAuditService(db)
	ctx := context.Background()

	t.Run("records login successfully", func(t *testing.T) {
		ipAddress := "192.168.1.1"
		userAgent := "Mozilla/5.0"

		mock.ExpectExec("INSERT INTO login_audit").
			WithArgs("user-123", "test@example.com", "admin,recruiter", &ipAddress, &userAgent).
			WillReturnResult(sqlmock.NewResult(1, 1))

		err := service.RecordLogin(ctx, LoginAuditInput{
			UserID:     "user-123",
			Identifier: "test@example.com",
			Roles:      []string{"admin", "recruiter"},
			IPAddress:  &ipAddress,
			UserAgent:  &userAgent,
		})
		if err != nil {
			t.Fatalf("Unexpected error: %v", err)
		}

		if err := mock.ExpectationsWereMet(); err != nil {
			t.Errorf("Unmet expectations: %v", err)
		}
	})

	t.Run("records login without optional fields", func(t *testing.T) {
		mock.ExpectExec("INSERT INTO login_audit").
			WithArgs("user-456", "admin@test.com", "superadmin", nil, nil).
			WillReturnResult(sqlmock.NewResult(2, 1))

		err := service.RecordLogin(ctx, LoginAuditInput{
			UserID:     "user-456",
			Identifier: "admin@test.com",
			Roles:      []string{"superadmin"},
			IPAddress:  nil,
			UserAgent:  nil,
		})
		if err != nil {
			t.Fatalf("Unexpected error: %v", err)
		}

		if err := mock.ExpectationsWereMet(); err != nil {
			t.Errorf("Unmet expectations: %v", err)
		}
	})
}

func TestAuditService_ListLogins(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("Failed to create mock db: %v", err)
	}
	defer db.Close()

	service := NewAuditService(db)
	ctx := context.Background()

	t.Run("returns empty list when no audits", func(t *testing.T) {
		mock.ExpectQuery("SELECT id, user_id, identifier, roles, ip_address, user_agent, created_at FROM login_audit").
			WithArgs(50).
			WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "identifier", "roles", "ip_address", "user_agent", "created_at"}))

		audits, err := service.ListLogins(ctx, 0) // Should default to 50
		if err != nil {
			t.Fatalf("Unexpected error: %v", err)
		}
		if len(audits) != 0 {
			t.Errorf("Expected 0 audits, got %d", len(audits))
		}

		if err := mock.ExpectationsWereMet(); err != nil {
			t.Errorf("Unmet expectations: %v", err)
		}
	})

	t.Run("respects custom limit", func(t *testing.T) {
		mock.ExpectQuery("SELECT id, user_id, identifier, roles, ip_address, user_agent, created_at FROM login_audit").
			WithArgs(10).
			WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "identifier", "roles", "ip_address", "user_agent", "created_at"}))

		_, err := service.ListLogins(ctx, 10)
		if err != nil {
			t.Fatalf("Unexpected error: %v", err)
		}

		if err := mock.ExpectationsWereMet(); err != nil {
			t.Errorf("Unmet expectations: %v", err)
		}
	})
}
