package auth

import (
	"time"

	"veza-backend-api/internal/models"

	"github.com/google/uuid"
	"github.com/stretchr/testify/mock"
)

// MockJWTService is a mock implementation of JWTServiceInterface
type MockJWTService struct {
	mock.Mock
}

func (m *MockJWTService) GenerateAccessToken(user *models.User) (string, error) {
	args := m.Called(user)
	return args.String(0), args.Error(1)
}

func (m *MockJWTService) GenerateRefreshToken(user *models.User) (string, error) {
	args := m.Called(user)
	return args.String(0), args.Error(1)
}

func (m *MockJWTService) GenerateTokenPair(user *models.User) (*models.TokenPair, error) {
	args := m.Called(user)
	if args.Get(0) == nil {
		return nil, args.Error(1)
	}
	return args.Get(0).(*models.TokenPair), args.Error(1)
}

func (m *MockJWTService) ValidateToken(tokenString string) (*models.CustomClaims, error) {
	args := m.Called(tokenString)
	if args.Get(0) == nil {
		return nil, args.Error(1)
	}
	return args.Get(0).(*models.CustomClaims), args.Error(1)
}

func (m *MockJWTService) ExtractUserID(tokenString string) (uuid.UUID, error) {
	args := m.Called(tokenString)
	return args.Get(0).(uuid.UUID), args.Error(1)
}

func (m *MockJWTService) GetConfig() *models.JWTConfig {
	args := m.Called()
	if args.Get(0) == nil {
		return &models.JWTConfig{
			AccessTokenTTL:            5 * time.Minute, // Action 5.1.1.4: Updated to match new default
			RefreshTokenTTL:           7 * 24 * time.Hour,
			RememberMeRefreshTokenTTL: 30 * 24 * time.Hour,
		}
	}
	return args.Get(0).(*models.JWTConfig)
}

// MockEmailVerificationService is a mock implementation of EmailVerificationServiceInterface
type MockEmailVerificationService struct {
	mock.Mock
}

func (m *MockEmailVerificationService) GenerateToken() (string, error) {
	args := m.Called()
	return args.String(0), args.Error(1)
}

func (m *MockEmailVerificationService) StoreToken(userID uuid.UUID, email, token string) error {
	args := m.Called(userID, email, token)
	return args.Error(0)
}

func (m *MockEmailVerificationService) VerifyToken(token string) (uuid.UUID, error) {
	args := m.Called(token)
	return args.Get(0).(uuid.UUID), args.Error(1)
}

func (m *MockEmailVerificationService) InvalidateOldTokens(userID uuid.UUID) error {
	args := m.Called(userID)
	return args.Error(0)
}

func (m *MockEmailVerificationService) ResendVerificationEmail(userID uuid.UUID, email string) error {
	args := m.Called(userID, email)
	return args.Error(0)
}

// MockRefreshTokenService is a mock implementation of RefreshTokenServiceInterface
type MockRefreshTokenService struct {
	mock.Mock
}

func (m *MockRefreshTokenService) Store(userID uuid.UUID, token string, ttl time.Duration) error {
	args := m.Called(userID, token, ttl)
	return args.Error(0)
}

func (m *MockRefreshTokenService) Validate(userID uuid.UUID, token string) error {
	args := m.Called(userID, token)
	return args.Error(0)
}

func (m *MockRefreshTokenService) Rotate(userID uuid.UUID, oldToken, newToken string, ttl time.Duration) error {
	args := m.Called(userID, oldToken, newToken, ttl)
	return args.Error(0)
}

func (m *MockRefreshTokenService) Revoke(userID uuid.UUID, token string) error {
	args := m.Called(userID, token)
	return args.Error(0)
}

func (m *MockRefreshTokenService) RevokeAll(userID uuid.UUID) error {
	args := m.Called(userID)
	return args.Error(0)
}

// MockPasswordResetService is a mock implementation of PasswordResetServiceInterface
type MockPasswordResetService struct {
	mock.Mock
}

func (m *MockPasswordResetService) GenerateToken() (string, error) {
	args := m.Called()
	return args.String(0), args.Error(1)
}

func (m *MockPasswordResetService) StoreToken(userID uuid.UUID, token string) error {
	args := m.Called(userID, token)
	return args.Error(0)
}

func (m *MockPasswordResetService) VerifyToken(token string) (uuid.UUID, error) {
	args := m.Called(token)
	return args.Get(0).(uuid.UUID), args.Error(1)
}

func (m *MockPasswordResetService) MarkTokenAsUsed(token string) error {
	args := m.Called(token)
	return args.Error(0)
}

func (m *MockPasswordResetService) InvalidateOldTokens(userID uuid.UUID) error {
	args := m.Called(userID)
	return args.Error(0)
}

// MockPasswordService is a mock implementation of PasswordServiceInterface
type MockPasswordService struct {
	mock.Mock
}

func (m *MockPasswordService) ValidatePassword(password string) error {
	args := m.Called(password)
	return args.Error(0)
}

func (m *MockPasswordService) UpdatePassword(userID uuid.UUID, newPassword string) error {
	args := m.Called(userID, newPassword)
	return args.Error(0)
}

func (m *MockPasswordService) Hash(password string) (string, error) {
	args := m.Called(password)
	return args.String(0), args.Error(1)
}

func (m *MockPasswordService) Compare(hashedPassword, password string) bool {
	args := m.Called(hashedPassword, password)
	return args.Bool(0)
}

// MockEmailService is a mock implementation of EmailServiceInterface
type MockEmailService struct {
	mock.Mock
}

func (m *MockEmailService) SendVerificationEmail(email, token string) error {
	args := m.Called(email, token)
	return args.Error(0)
}

func (m *MockEmailService) SendVerificationEmailWithUserID(userID uuid.UUID, email string) error {
	args := m.Called(userID, email)
	return args.Error(0)
}

func (m *MockEmailService) SendPasswordResetEmail(userID uuid.UUID, email string, token string) error {
	args := m.Called(userID, email, token)
	return args.Error(0)
}

func (m *MockEmailService) SendWelcomeEmail(email, username string) error {
	args := m.Called(email, username)
	return args.Error(0)
}

func (m *MockEmailService) SendNotificationEmail(email, subject, message, notificationType string) error {
	args := m.Called(email, subject, message, notificationType)
	return args.Error(0)
}

// MockJobWorker is a mock implementation of JobWorkerInterface
type MockJobWorker struct {
	mock.Mock
}

func (m *MockJobWorker) EnqueueEmailJobWithTemplate(to, subject, templateName string, templateData map[string]interface{}) {
	m.Called(to, subject, templateName, templateData)
}
