import {
  IUseCase,
  IUseCaseError,
  IUseCaseRequest,
  UseCaseError,
} from "@/contexts/common/application/useCases";
import { IRepositoryManager } from "@/contexts/common/domain";
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
import { Result, UniqueID } from "@shared/contexts";
import { Dealer, IQuoteRepository } from "../../domain";

import { IInfrastructureError } from "@/contexts/common/infrastructure";
import { Quote } from "../../domain/entities/Quotes/Quote";
import { ISalesContext } from "../../infrastructure";

export interface IGetQuoteUseCaseRequest extends IUseCaseRequest {
  id: UniqueID;
}

export type GetQuoteResponseOrError =
  | Result<never, IUseCaseError> // Misc errors (value objects)
  | Result<Quote, never>; // Success!

export class GetQuoteUseCase
  implements IUseCase<IGetQuoteUseCaseRequest, Promise<GetQuoteResponseOrError>>
{
  private _adapter: ISequelizeAdapter;
  private _repositoryManager: IRepositoryManager;
  private _dealer?: Dealer;

  constructor(context: ISalesContext) {
    this._adapter = context.adapter;
    this._repositoryManager = context.repositoryManager;
    this._dealer = context.dealer;
  }

  async execute(request: IGetQuoteUseCaseRequest): Promise<GetQuoteResponseOrError> {
    const { id } = request;

    return await this.findQuote(id);
  }

  private async findQuote(id: UniqueID) {
    const transaction = this._adapter.startTransaction();
    const QuoteRepoBuilder = this._getQuoteRepository();

    let quote: Quote | null = null;

    try {
      await transaction.complete(async (t) => {
        const quoteRepo = QuoteRepoBuilder({ transaction: t });
        quote = await quoteRepo.getById(id);
      });

      if (!quote) {
        return Result.fail(UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, "Quote not found"));
      }

      return Result.ok<Quote>(quote!);
    } catch (error: unknown) {
      const _error = error as IInfrastructureError;
      return Result.fail(UseCaseError.create(UseCaseError.REPOSITORY_ERROR, "Query error", _error));
    }
  }

  private _getQuoteRepository() {
    return this._repositoryManager.getRepository<IQuoteRepository>("Quote");
  }
}
