import { config } from "@/config";
import { IAdapter, Password, RepositoryBuilder } from "@/contexts/common/domain";
import { Dealer, DealerLogotype, DealerStatus, IDealerRepository } from "@/contexts/sales/domain";
import { CurrencyData, Email, KeyValueMap, Language, Name, UniqueID } from "@shared/contexts";
import { IUserRepository, User, UserRole } from "../domain";

export const existsUserByID = async (
  id: UniqueID,
  adapter: IAdapter,
  repository: RepositoryBuilder<IUserRepository>
): Promise<boolean> => {
  return await adapter
    .startTransaction()
    .complete(async (t) => repository({ transaction: t }).existsUserWithId(id));
};

export const existsUserByName = async (
  name: Name,
  adapter: IAdapter,
  repository: RepositoryBuilder<IUserRepository>
): Promise<boolean> => {
  return await adapter
    .startTransaction()
    .complete(async (t) => repository({ transaction: t }).existsUserWithName(name));
};

export const findUserByID = async (
  id: UniqueID,
  adapter: IAdapter,
  repository: RepositoryBuilder<IUserRepository>
): Promise<User | null> => {
  return await adapter
    .startTransaction()
    .complete(async (t) => repository({ transaction: t }).getById(id));
};

export const existsUserByEmail = async (
  email: Email,
  adapter: IAdapter,
  repository: RepositoryBuilder<IUserRepository>
): Promise<boolean> => {
  return await adapter
    .startTransaction()
    .complete(async (t) => repository({ transaction: t }).existsUserWithEmail(email));
};

export const findUserByEmail = async (
  email: Email,
  adapter: IAdapter,
  repository: RepositoryBuilder<IUserRepository>
): Promise<User | null> => {
  return await adapter
    .startTransaction()
    .complete(async (t) => repository({ transaction: t }).findUserByEmail(email));
};

export const initializeAdmin = async (
  adapter: IAdapter,
  repository: RepositoryBuilder<IUserRepository>
) => {
  return await adapter.startTransaction().complete(async (t) => {
    const adminExists = await repository({ transaction: t }).existsAdminUser();

    if (!adminExists) {
      const admin = User.create(
        {
          name: Name.create(config.admin.name).object,
          email: Email.create(config.admin.email).object,
          password: Password.createFromPlainTextPassword(config.admin.password).object,
          language: Language.createFromCode(config.admin.language).object,
          roles: [UserRole.ROLE_ADMIN],
        },
        UniqueID.generateNewID().object
      ).object;
      await repository({ transaction: t }).create(admin);
      console.log("Usuario administrador creado");
    }
  });
};

export const initializeSampleUser = async (
  adapter: IAdapter,
  repository: RepositoryBuilder<IUserRepository>
) => {
  return await adapter.startTransaction().complete(async (t) => {
    const email = Email.create(config.sample_dealer.email).object;
    const userExists = await repository({ transaction: t }).existsUserWithEmail(email);

    if (!userExists) {
      const user = User.create(
        {
          name: Name.create(config.sample_dealer.name).object,
          email,
          password: Password.createFromPlainTextPassword(config.sample_dealer.password).object,
          language: Language.createFromCode(config.sample_dealer.language).object,
          roles: [UserRole.ROLE_USER],
        },
        UniqueID.generateNewID().object
      ).object;
      await repository({ transaction: t }).create(user);
      console.log("Usuario creado");
      return user;
    } else {
      return false;
    }
  });
};

export const initializeSampleDealer = async (
  user: User,
  adapter: IAdapter,
  repository: RepositoryBuilder<IDealerRepository>
) => {
  return await adapter.startTransaction().complete(async (t) => {
    const dealerExists = await repository({ transaction: t }).getByUserId(user.id);

    if (!dealerExists) {
      const additionalInfoOrError = KeyValueMap.create([
        ["contact_information", ""],
        ["default_payment_method", ""],
        ["default_notes", ""],
        ["default_legal_terms", ""],
        ["default_quote_validity", ""],
      ]);

      const dealer = Dealer.create(
        {
          name: Name.create(config.sample_dealer.name).object,
          user_id: user.id,
          language: Language.createDefaultCode().object,
          status: DealerStatus.createActived(),
          currency: CurrencyData.createDefaultCode().object,
          additionalInfo: additionalInfoOrError.object,
          logo: DealerLogotype.create("").object,
        },
        UniqueID.generateNewID().object
      ).object;
      await repository({ transaction: t }).create(dealer);
      console.log("Dealer creado");
    }
  });
};
