import { Configuration, DominioApi } from '@microcredito/client'

import { City, State } from '../domain'
import { ContextMappers, ErrorMappers } from '../mappers'
import { API_URL, mapUserAgentToString, UserAgent } from './shared'

export interface ContextRepository {
  fetchCities(): Promise<City[]>
  fetchStates(): Promise<State[]>
}

export class ContextRepositoryImpl implements ContextRepository {
  private api: DominioApi
  private stateAdapter: ContextMappers.StateAdapter
  private cityAdapter: ContextMappers.CityAdapter
  private errorAdapter: ErrorMappers.ResponseErrorAdapter

  constructor(userAgent: string) {
    this.errorAdapter = new ErrorMappers.ResponseErrorAdapter()
    this.stateAdapter = new ContextMappers.StateAdapter()
    this.cityAdapter = new ContextMappers.CityAdapter()
    this.api = new DominioApi(
      new Configuration({
        basePath: API_URL,
        headers: {
          'User-Agent': userAgent,
        },
      })
    )
  }

  public fetchCities = async (): Promise<City[]> => {
    try {
      const result = await this.api.obterMunicipios()
      return result.map(this.cityAdapter.mapApiModelToDomain)
    } catch (e) {
      const result = await this.errorAdapter.mapApiModelToDomain(e)
      throw result
    }
  }

  public fetchStates = async (): Promise<State[]> => {
    try {
      const result = await this.api.obterEstados()
      return result.map(this.stateAdapter.mapApiModelToDomain)
    } catch (e) {
      const result = await this.errorAdapter.mapApiModelToDomain(e)
      throw result
    }
  }
}

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