import { ContainerModule, type interfaces } from "inversify";

import type { IUsersRepository } from "../application/repositories/users.repository.interface";
import type { IAuthenticationService } from "../application/services/authentication.service.interface";
import { MockUsersRepository } from "../infrastructure/repositories/users.repository.mock";
import { MockAuthenticationService } from "../infrastructure/services/authentication.service.mock";
import {
  signInUseCase,
  type ISignInUseCase,
} from "../application/use-cases/sign-in.use-case";
import {
  signUpUseCase,
  type ISignUpUseCase,
} from "../application/use-cases/sign-up.use-case";
import {
  signOutUseCase,
  type ISignOutUseCase,
} from "../application/use-cases/sign-out.use-case";
import {
  signInController,
  type ISignInController,
} from "../interface-adapters/controllers/sign-in.controller";
import {
  signUpController,
  type ISignUpController,
} from "../interface-adapters/controllers/sign-up.controller";
import {
  signOutController,
  type ISignOutController,
} from "../interface-adapters/controllers/sign-out.controller";
import { AUTH_SYMBOLS } from "./symbols";

export const AuthModule = new ContainerModule((bind: interfaces.Bind) => {
  bind<IUsersRepository>(AUTH_SYMBOLS.IUsersRepository).to(MockUsersRepository);
  bind<IAuthenticationService>(AUTH_SYMBOLS.IAuthenticationService).to(
    MockAuthenticationService,
  );

  bind<ISignInUseCase>(AUTH_SYMBOLS.ISignInUseCase).toDynamicValue((ctx) =>
    signInUseCase(
      ctx.container.get<IUsersRepository>(AUTH_SYMBOLS.IUsersRepository),
      ctx.container.get<IAuthenticationService>(AUTH_SYMBOLS.IAuthenticationService),
    ),
  );

  bind<ISignUpUseCase>(AUTH_SYMBOLS.ISignUpUseCase).toDynamicValue((ctx) =>
    // No default bus — real cross-feature wiring runs through
    // bindProductionAuth / bindDevSeedAuth where bindAll() passes a shared
    // bus instance when @repo/core-events is scaffolded.
    signUpUseCase(
      ctx.container.get<IUsersRepository>(AUTH_SYMBOLS.IUsersRepository),
      ctx.container.get<IAuthenticationService>(AUTH_SYMBOLS.IAuthenticationService),
      undefined,
    ),
  );

  bind<ISignOutUseCase>(AUTH_SYMBOLS.ISignOutUseCase).toDynamicValue((ctx) =>
    signOutUseCase(
      ctx.container.get<IAuthenticationService>(AUTH_SYMBOLS.IAuthenticationService),
    ),
  );

  bind<ISignInController>(AUTH_SYMBOLS.ISignInController).toDynamicValue((ctx) =>
    signInController(
      ctx.container.get<ISignInUseCase>(AUTH_SYMBOLS.ISignInUseCase),
    ),
  );

  bind<ISignUpController>(AUTH_SYMBOLS.ISignUpController).toDynamicValue((ctx) =>
    signUpController(
      ctx.container.get<ISignUpUseCase>(AUTH_SYMBOLS.ISignUpUseCase),
    ),
  );

  bind<ISignOutController>(AUTH_SYMBOLS.ISignOutController).toDynamicValue((ctx) =>
    signOutController(
      ctx.container.get<ISignOutUseCase>(AUTH_SYMBOLS.ISignOutUseCase),
    ),
  );
});
