import { extractNumbers } from '@agiliza/utils/extractors'
import { AgenteApi, Configuration } from '@microcredito/client'

import { Broker } from '../domain'
import { SessionAdapters, SessionApiAdapters as Adapters, UserMappers } from '../mappers'
import { API_URL, mapUserAgentToString, SESSION_KEY, UserAgent } from './shared'

export interface SessionRepository {
  login(username: string, password: string): Promise<void>
  logout(): void
  connect(): Promise<Broker>
}

export class SessionRepositoryImpl implements SessionRepository {
  private api: AgenteApi
  private userAgent: string
  private loginApiAdapter: Adapters.LoginApiAdapter
  private errorAdapter: SessionAdapters.LoginErrorAdapter
  private userMapper: UserMappers.BrokerMapper
  constructor(userAgent: string) {
    this.errorAdapter = new SessionAdapters.LoginErrorAdapter()
    this.loginApiAdapter = new Adapters.LoginApiAdapter()
    this.userMapper = new UserMappers.BrokerMapper()
    this.userAgent = userAgent
    this.api = new AgenteApi(
      new Configuration({
        basePath: API_URL,
        headers: {
          'User-Agent': userAgent,
        },
      })
    )
  }

  public login = async (username: string, password: string) => {
    try {
      const params = this.loginApiAdapter.mapDomainToApiModel({ username: extractNumbers(username), password })
      const accessToken = await this.api.login(params)
      localStorage.setItem(SESSION_KEY, accessToken.token)
      // const clienteApi = new ClienteApi(
      //   new Configuration({
      //     basePath: API_URL,
      //     accessToken: accessToken.token,
      //     headers: {
      //       'User-Agent': this.customer,
      //     },
      //   })
      // )
      // const cliente = await clienteApi.obterUsuarioLogado()

      // return this.customerMapper.mapApiModelToDomain(cliente)
    } catch (e) {
      const result = await this.errorAdapter.mapApiModelToDomain(e)
      throw result
    }
  }
  public logout = () => {
    localStorage.removeItem(SESSION_KEY)
  }
  public connect = async () => {
    const accessToken = localStorage.getItem(SESSION_KEY)
    if (accessToken) {
      const api = new AgenteApi(
        new Configuration({
          basePath: API_URL,
          accessToken,
          headers: {
            'User-Agent': this.userAgent,
          },
        })
      )
      try {
        const usuario = await api.obterUsuarioLogado()
        return this.userMapper.mapApiModelToDomain(usuario)
      } catch (e) {
        localStorage.removeItem(SESSION_KEY)
        const result = await this.errorAdapter.mapApiModelToDomain(e)
        throw result
      }
    } else throw new Error()
  }
}

export class SessionRepositoryImplFactory {
  static create(userAgent: UserAgent) {
    console.log(userAgent)
    const repository = new SessionRepositoryImpl(mapUserAgentToString(userAgent))
    return repository
  }
}
