import { Test, TestingModule } from '@nestjs/testing';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { LoginCoreService } from './login_core.service';
import { UsersService } from '../db/users/users.service';
import { EmailService } from '../utils/email/email.service';
import { VerificationService } from '../utils/verification/verification.service';

describe('LoginCoreModule', () => {
  let module: TestingModule;
  let loginCoreService: LoginCoreService;
  let configService: ConfigService;

  beforeEach(async () => {
    const mockConfigService = {
      get: jest.fn((key: string, defaultValue?: any) => {
        switch (key) {
          case 'JWT_SECRET':
            return 'test-jwt-secret-key';
          case 'JWT_EXPIRES_IN':
            return defaultValue || '7d';
          default:
            return defaultValue;
        }
      }),
    };

    const mockUsersService = {
      findByUsername: jest.fn(),
      findByEmail: jest.fn(),
      findAll: jest.fn(),
      findOne: jest.fn(),
      create: jest.fn(),
      update: jest.fn(),
      remove: jest.fn(),
      findByGithubId: jest.fn(),
    };

    const mockEmailService = {
      sendVerificationCode: jest.fn(),
      sendWelcomeEmail: jest.fn(),
    };

    const mockVerificationService = {
      generateCode: jest.fn(),
      verifyCode: jest.fn(),
      clearCooldown: jest.fn(),
      debugCodeInfo: jest.fn(),
    };

    const mockJwtService = {
      signAsync: jest.fn(),
      verifyAsync: jest.fn(),
    };

    module = await Test.createTestingModule({
      providers: [
        LoginCoreService,
        {
          provide: ConfigService,
          useValue: mockConfigService,
        },
        {
          provide: 'UsersService',
          useValue: mockUsersService,
        },
        {
          provide: EmailService,
          useValue: mockEmailService,
        },
        {
          provide: VerificationService,
          useValue: mockVerificationService,
        },
        {
          provide: JwtService,
          useValue: mockJwtService,
        },
      ],
    }).compile();

    loginCoreService = module.get<LoginCoreService>(LoginCoreService);
    configService = module.get<ConfigService>(ConfigService);
  });

  afterEach(async () => {
    if (module) {
      await module.close();
    }
  });

  it('should be defined', () => {
    expect(module).toBeDefined();
  });

  describe('Service Providers', () => {
    it('should provide LoginCoreService', () => {
      expect(loginCoreService).toBeDefined();
      expect(loginCoreService).toBeInstanceOf(LoginCoreService);
    });

    it('should provide ConfigService', () => {
      expect(configService).toBeDefined();
      // ConfigService is mocked, so we check if it has the expected methods
      expect(configService.get).toBeDefined();
      expect(typeof configService.get).toBe('function');
    });
  });

  describe('JWT Configuration', () => {
    it('should have access to JWT configuration', () => {
      // Test that the mock ConfigService can provide JWT configuration
      const jwtSecret = configService.get('JWT_SECRET');
      const jwtExpiresIn = configService.get('JWT_EXPIRES_IN', '7d');
      
      expect(jwtSecret).toBe('test-jwt-secret-key');
      expect(jwtExpiresIn).toBe('7d');
    });
  });

  describe('Module Dependencies', () => {
    it('should import required modules', () => {
      expect(module).toBeDefined();
      expect(loginCoreService).toBeDefined();
    });

    it('should not have circular dependencies', () => {
      expect(module).toBeDefined();
    });
  });

  describe('Module Exports', () => {
    it('should export LoginCoreService', () => {
      expect(loginCoreService).toBeDefined();
      expect(loginCoreService).toBeInstanceOf(LoginCoreService);
    });

    it('should make LoginCoreService available for injection', () => {
      const service = module.get<LoginCoreService>(LoginCoreService);
      expect(service).toBe(loginCoreService);
    });
  });

  describe('Configuration Validation', () => {
    it('should validate JWT configuration completeness', () => {
      // Test that all required configuration keys are accessible
      expect(configService.get('JWT_SECRET')).toBeDefined();
      expect(configService.get('JWT_EXPIRES_IN', '7d')).toBeDefined();
    });
  });
});