import { UniqueID } from "@/core/common/domain";
import { Collection, Result } from "@repo/rdx-utils";
import { Transaction } from "sequelize";
import { Account, IAccountProps } from "../aggregates";
import { IAccountRepository } from "../repositories";
import { IAccountService } from "./account-service.interface";

export class AccountService implements IAccountService {
  constructor(private readonly repo: IAccountRepository) {}

  async findAccounts(transaction?: Transaction): Promise<Result<Collection<Account>, Error>> {
    const accountsOrError = await this.repo.findAll(transaction);
    if (accountsOrError.isFailure) {
      return Result.fail(accountsOrError.error);
    }

    // Solo devolver usuarios activos
    //const allAccounts = accountsOrError.data.filter((account) => account.isActive);
    //return Result.ok(new Collection(allAccounts));

    return accountsOrError;
  }

  async findAccountById(accountId: UniqueID, transaction?: Transaction): Promise<Result<Account>> {
    return await this.repo.findById(accountId, transaction);
  }

  async updateAccountById(
    accountId: UniqueID,
    data: Partial<IAccountProps>,
    transaction?: Transaction
  ): Promise<Result<Account, Error>> {
    // Verificar si la cuenta existe
    const accountOrError = await this.repo.findById(accountId, transaction);
    if (accountOrError.isFailure) {
      return Result.fail(new Error("Account not found"));
    }

    const updatedAccountOrError = Account.update(accountOrError.data, data);
    if (updatedAccountOrError.isFailure) {
      return Result.fail(
        new Error(`Error updating account: ${updatedAccountOrError.error.message}`)
      );
    }

    const updateAccount = updatedAccountOrError.data;

    await this.repo.update(updateAccount, transaction);
    return Result.ok(updateAccount);
  }

  async createAccount(
    accountId: UniqueID,
    data: IAccountProps,
    transaction?: Transaction
  ): Promise<Result<Account, Error>> {
    // Verificar si la cuenta existe
    const accountOrError = await this.repo.findById(accountId, transaction);
    if (accountOrError.isSuccess) {
      return Result.fail(new Error("Account exists"));
    }

    const newAccountOrError = Account.create(data, accountId);
    if (newAccountOrError.isFailure) {
      return Result.fail(new Error(`Error creating account: ${newAccountOrError.error.message}`));
    }

    const newAccount = newAccountOrError.data;

    await this.repo.create(newAccount, transaction);
    return Result.ok(newAccount);
  }

  async activateAccount(id: UniqueID, transaction?: Transaction): Promise<Result<Account, Error>> {
    const accountOrError = await this.repo.findById(id, transaction);

    if (accountOrError.isFailure) {
      return Result.fail(new Error("Account not found"));
    }

    const account = accountOrError.data;
    if (account.activate()) {
      await this.repo.update(account, transaction);
      return Result.ok();
    }
    return Result.fail(new Error("Error activating account"));
  }

  async deactivateAccount(
    id: UniqueID,
    transaction?: Transaction
  ): Promise<Result<Account, Error>> {
    const accountOrError = await this.repo.findById(id, transaction);
    if (accountOrError.isFailure) {
      return Result.fail(new Error("Account not found"));
    }

    const account = accountOrError.data;
    if (account.deactivate()) {
      await this.repo.update(account, transaction);
      return Result.ok();
    }
    return Result.fail(new Error("Error deactivating account"));
  }
}
