import { Provider } from '@nestjs/common';
import { AuthService } from './AuthService';

// Import interfaces and concrete implementations
import type { IAuthRepository } from '@core/identity/domain/repositories/IAuthRepository';
import { IUserRepository, StoredUser } from '@core/identity/domain/repositories/IUserRepository';
import type { IPasswordHashingService } from '@core/identity/domain/services/PasswordHashingService';
import type { Logger } from '@core/shared/application';

import { InMemoryAuthRepository } from '@adapters/identity/persistence/inmemory/InMemoryAuthRepository';
import { InMemoryUserRepository } from '@adapters/identity/persistence/inmemory/InMemoryUserRepository';
import { InMemoryPasswordHashingService } from '@adapters/identity/services/InMemoryPasswordHashingService';
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
import { IdentitySessionPort } from '@core/identity/application/ports/IdentitySessionPort';
import { CookieIdentitySessionAdapter } from '@adapters/identity/session/CookieIdentitySessionAdapter';

// Define the tokens for dependency injection
export const AUTH_REPOSITORY_TOKEN = 'IAuthRepository';
export const USER_REPOSITORY_TOKEN = 'IUserRepository';
export const PASSWORD_HASHING_SERVICE_TOKEN = 'IPasswordHashingService';
export const LOGGER_TOKEN = 'Logger';
export const IDENTITY_SESSION_PORT_TOKEN = 'IdentitySessionPort';

export const AuthProviders: Provider[] = [
  AuthService, // Provide the service itself
  {
    provide: AUTH_REPOSITORY_TOKEN,
    useFactory: (userRepository: IUserRepository, passwordHashingService: IPasswordHashingService, logger: Logger) => {
      // Seed initial users for InMemoryUserRepository
      const initialUsers: StoredUser[] = [
        // Example user (replace with actual test users as needed)
        {
          id: 'user-1',
          email: 'test@example.com',
          passwordHash: 'demo_salt_moc.elpmaxe@tset', // "test@example.com" reversed
          displayName: 'Test User',
          salt: '', // Handled by hashing service
          createdAt: new Date(),
        },
      ];
      const inMemoryUserRepository = new InMemoryUserRepository(logger, initialUsers);
      return new InMemoryAuthRepository(inMemoryUserRepository, passwordHashingService, logger);
    },
    inject: [USER_REPOSITORY_TOKEN, PASSWORD_HASHING_SERVICE_TOKEN, LOGGER_TOKEN],
  },
  {
    provide: USER_REPOSITORY_TOKEN,
    useFactory: (logger: Logger) => new InMemoryUserRepository(logger), // Factory for InMemoryUserRepository
    inject: [LOGGER_TOKEN],
  },
  {
    provide: PASSWORD_HASHING_SERVICE_TOKEN,
    useClass: InMemoryPasswordHashingService,
  },
  {
    provide: LOGGER_TOKEN,
    useClass: ConsoleLogger,
  },
  {
    provide: IDENTITY_SESSION_PORT_TOKEN,
    useFactory: (logger: Logger) => new CookieIdentitySessionAdapter(logger),
    inject: [LOGGER_TOKEN],
  },
];
