import { IUseCaseError, UseCaseError } from "@/contexts/common/application/useCases";
import { IServerError } from "@/contexts/common/domain/errors";
import { IInfrastructureError, InfrastructureError } from "@/contexts/common/infrastructure";
import { ExpressController } from "@/contexts/common/infrastructure/express";
import { SendIncidenceUseCase } from "@/contexts/support/application/SendIncidence.useCase";
import {
  ensureSendIncidence_Request_DTOIsValid,
  ISendIncidence_Request_DTO,
} from "@shared/contexts";
import { ISupportContext } from "../../../Support.context";

export class SendIncidenceController extends ExpressController {
  private useCase: SendIncidenceUseCase;
  private context: ISupportContext;

  constructor(props: { useCase: SendIncidenceUseCase }, context: ISupportContext) {
    super();

    const { useCase } = props;
    this.useCase = useCase;
    this.context = context;
  }

  async executeImpl(): Promise<any> {
    try {
      const incidenceDTO: ISendIncidence_Request_DTO = this.req.body;

      // Validar DTO de datos
      const incidenceDTOOrError = ensureSendIncidence_Request_DTOIsValid(incidenceDTO);

      if (incidenceDTOOrError.isFailure) {
        const errorMessage = "Incidence data not valid";
        const infraError = InfrastructureError.create(
          InfrastructureError.INVALID_INPUT_DATA,
          errorMessage,
          incidenceDTOOrError.error
        );
        return this.invalidInputError(errorMessage, infraError);
      }

      // Llamar al caso de uso
      const result = await this.useCase.execute({
        incidenceDTO: incidenceDTOOrError.object,
      });

      if (result.isFailure) {
        return this._handleExecuteError(result.error);
      }
      return this.noContent();
    } catch (e: unknown) {
      return this.fail(e as IServerError);
    }
  }

  private _handleExecuteError(error: IUseCaseError) {
    let errorMessage: string;
    let infraError: IInfrastructureError;

    switch (error.code) {
      case UseCaseError.UNEXCEPTED_ERROR:
        errorMessage = error.message;

        infraError = InfrastructureError.create(
          InfrastructureError.UNEXCEPTED_ERROR,
          errorMessage,
          error
        );
        return this.internalServerError(errorMessage, infraError);
        break;

      default:
        errorMessage = error.message;
        return this.clientError(errorMessage);
    }
  }
}
