import { GetSubProducts, SendProposal } from '@agiliza/api/domain/simulation/simulation'
import { ClienteApi, Configuration } from '@microcredito/client'
import { AnonimoApi } from '@microcredito/client/dist/apis/AnonimoApi'

import { ErrorMappers, SimulationApiMappers, SimulationMappers } from '../../mappers'
import { API_URL, mapUserAgentToString, SESSION_KEY, UserAgent } from '../shared'

export interface SimulationRepository {
  getSubproducts(input: GetSubProducts['Input']): Promise<GetSubProducts['Output']>
  sendProposal(input: SendProposal['Input']): Promise<SendProposal['Output']>
}

export class SimulationRepositoryImpl implements SimulationRepository {
  private api: AnonimoApi
  private getSubproductsApiMapper: SimulationApiMappers.GetSubProductsApiMapper
  private subproductMapper: SimulationMappers.SubProductMapper
  private errorAdapter: ErrorMappers.ResponseErrorAdapter
  private userAgent: string

  constructor(userAgent: string) {
    this.errorAdapter = new ErrorMappers.ResponseErrorAdapter()
    this.getSubproductsApiMapper = new SimulationApiMappers.GetSubProductsApiMapper()
    this.subproductMapper = new SimulationMappers.SubProductMapper()
    this.userAgent = userAgent
    this.api = new AnonimoApi(
      new Configuration({
        basePath: API_URL,
        headers: {
          'User-Agent': userAgent,
        },
      })
    )
  }

  public getSubproducts = async (input: GetSubProducts['Input']): Promise<GetSubProducts['Output']> => {
    try {
      const result = await this.api.anonimoObterSubprodutos({
        simularCreditoRequestApiModel: this.getSubproductsApiMapper.mapDomainToApiModel(input),
      })
      return result.map(this.subproductMapper.mapApiModelToDomain)
    } catch (e) {
      const result = await this.errorAdapter.mapApiModelToDomain(e)
      throw result
    }
  }

  public sendProposal = async (input: SendProposal['Input']): Promise<SendProposal['Output']> => {
    try {
      const accessToken = localStorage.getItem(SESSION_KEY) || ''
      const clientApi = new ClienteApi(
        new Configuration({
          basePath: API_URL,
          accessToken,
          headers: {
            'User-Agent': this.userAgent,
          },
        })
      )
      await clientApi.enviarProjeto({
        idprojeto: input.proposalId,
      })
    } catch (e) {
      const result = await this.errorAdapter.mapApiModelToDomain(e)
      throw result
    }
  }
}

export class SimulationRepositoryImplFactory {
  static create(userAgent: UserAgent) {
    const repository = new SimulationRepositoryImpl(mapUserAgentToString(userAgent))
    return repository
  }
}
