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

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

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

export class SessionRepositoryImpl implements SessionRepository {
  private customer: string
  private api: ClienteApi
  private loginApiAdapter: Adapters.LoginApiAdapter
  private errorAdapter: SessionAdapters.LoginErrorAdapter
  private customerMapper: CustomerMappers.CustomerMapper
  constructor(userAgent: string) {
    this.customer = userAgent
    this.errorAdapter = new SessionAdapters.LoginErrorAdapter()
    this.loginApiAdapter = new Adapters.LoginApiAdapter()
    this.customerMapper = new CustomerMappers.CustomerMapper()
    this.api = new ClienteApi(
      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 = () => {
    const sessionKey = localStorage.getItem(SESSION_KEY) || 'a'
    if (sessionKey) return
    else throw new Error()
    // return await new Promise<void>((res, rej) => {
    // })
  }
}

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