import {
  AddBDProductService,
  BDAddress,
  BDProductService,
  BusinessData,
  CreateProposal,
  Document,
  StockSalesCosts,
  UpdateBDAddress,
  UpdateBDIdentification,
  UpdateBDProductService,
  UpdateBDStockSalesCosts
} from '@agiliza/api/domain'
import { extractNumbers } from '@agiliza/utils/extractors'
import {
  DadosNegocioEnderecoApiModel,
  DadosNegocioEstoqueVendasCustosApiModel,
  DadosNegocioIdentificacaoApiModel,
  DadosNegocioProdutoServicoApiModel,
  DocumentoApiModel
} from '@microcredito/client'
import {
  AtualizaProdutoServicoDadosNegocioRequest,
  AtualizarEnderecoDadosNegocioRequest,
  AtualizarEstoqueVendasCustosDadosNegocioRequest,
  AtualizarIdentificacaoDadosNegocioRequest,
  CriarProdutoServicoDadosNegocioRequest
} from '@microcredito/client/dist/apis/AgenteApi'
import { CriarPropostaRequest } from '@microcredito/client/dist/apis/ClienteApi'

import { ApiAdapter } from '../shared'
import { AddressApiMapper } from './customerData'

export class DocumentApiMapper implements ApiAdapter<Document, DocumentoApiModel> {
  private mapDocumentTypeToApi = (docType: Document['type']): DocumentoApiModel['tipoDocumento'] => ({
    codigo: docType.id,
    descricao: docType.description,
  })

  public mapDomainToApiModel = (doc: Document): DocumentoApiModel => ({
    id: doc.id,
    imagem: doc.url,
    tipoDocumento: doc.type ? this.mapDocumentTypeToApi(doc.type) : { codigo: '', descricao: '' },
    informacoesComplementares: doc.extraInformations,
  })
}

export class BDIdentificationApiMapper implements ApiAdapter<BusinessData['identification'], DadosNegocioIdentificacaoApiModel> {
  private documentAdapter: DocumentApiMapper
  constructor() {
    this.documentAdapter = new DocumentApiMapper()
  }
  public mapDomainToApiModel = (ident: BusinessData['identification']): DadosNegocioIdentificacaoApiModel => ({
    cnpj: extractNumbers(ident?.cnpj),
    codigoCNAE: ident?.codeCNAE,
    dataAbertura: ident?.openingDate !== null ? ident?.openingDate : undefined,
    documento: ident?.document ? this.documentAdapter.mapDomainToApiModel(ident.document) : undefined,
    inscricaoComercial: ident?.commercialRegistration,
    inscricaoEstadual: ident?.stateRegistration,
    inscricaoMunicipal: ident?.cityRegistration,
    local: ident?.local,
    nomeFantasia: ident?.fantasyName,
    opLiquidada: ident?.settledOP,
    razaoSocial: ident?.companyName,
    setorAtividade: ident?.activitySector,
  })
}

export class BDUpdateIdentificationApiMapper implements ApiAdapter<UpdateBDIdentification['Input'], AtualizarIdentificacaoDadosNegocioRequest> {
  private identificationApiMapper: BDIdentificationApiMapper
  constructor() {
    this.identificationApiMapper = new BDIdentificationApiMapper()
  }
  public mapDomainToApiModel = (input: UpdateBDIdentification['Input']): AtualizarIdentificacaoDadosNegocioRequest => ({
    projetoId: input.projectId,
    dadosNegocioIdentificacaoApiModel: this.identificationApiMapper.mapDomainToApiModel(input.identification),
  })
}

export class CreateProposalApiMapper implements ApiAdapter<CreateProposal['Input'], CriarPropostaRequest> {
  public mapDomainToApiModel = (input: CreateProposal['Input']): CriarPropostaRequest => ({
    criarPropostaRequestApiModel: {
      carencia: input.gracePeriodId,
      categoriaSimulacao: input.categoryId,
      quantidadeParcelas: input.installmentsNumber,
      valorInteresse: input.creditValue,
      subprodutoId: input.subproductId,
    },
  })
}

export class BDProductServiceApiMapper implements ApiAdapter<BDProductService, DadosNegocioProdutoServicoApiModel> {
  public mapPriceAmountToDomain = (pA: { price: string; amount: string }): DadosNegocioProdutoServicoApiModel['custosVariaveis'] => ({
    precoUnitario: Number(pA.price),
    quantidade: Number(pA.amount),
  })
  public mapDomainToApiModel = (pS: BDProductService): DadosNegocioProdutoServicoApiModel => ({
    id: pS.id,
    unidade: pS.unit,
    descricao: pS.description,
    custosVariaveis: this.mapPriceAmountToDomain(pS.variableCosts),
    estoque: this.mapPriceAmountToDomain(pS.stock),
    vendasMensais: this.mapPriceAmountToDomain(pS.monthlySales),
  })
}

export class BDAddProductServiceApiMapper implements ApiAdapter<AddBDProductService['Input'], CriarProdutoServicoDadosNegocioRequest> {
  private bdProductServiceApiMapper: BDProductServiceApiMapper
  constructor() {
    this.bdProductServiceApiMapper = new BDProductServiceApiMapper()
  }
  public mapDomainToApiModel = (input: AddBDProductService['Input']): CriarProdutoServicoDadosNegocioRequest => ({
    projetoId: input.projectId,
    dadosNegocioProdutoServicoApiModel: this.bdProductServiceApiMapper.mapDomainToApiModel(input.productService),
  })
}

export class BDUpdateProductServiceApiMapper implements ApiAdapter<UpdateBDProductService['Input'], AtualizaProdutoServicoDadosNegocioRequest> {
  private bdProductServiceApiMapper: BDProductServiceApiMapper
  constructor() {
    this.bdProductServiceApiMapper = new BDProductServiceApiMapper()
  }
  public mapDomainToApiModel = (input: UpdateBDProductService['Input']): AtualizaProdutoServicoDadosNegocioRequest => ({
    projetoId: input.projectId,
    prdSrvId: input.productServiceId,
    dadosNegocioProdutoServicoApiModel: this.bdProductServiceApiMapper.mapDomainToApiModel(input.productService),
  })
}

export class BDAddressApiMapper implements ApiAdapter<BDAddress, DadosNegocioEnderecoApiModel> {
  private addressApiMapper: AddressApiMapper
  constructor() {
    this.addressApiMapper = new AddressApiMapper()
  }
  public mapDomainToApiModel = ({ proof, referencePoint, ...adr }: BDAddress): DadosNegocioEnderecoApiModel => ({
    comprovante: proof,
    pontoReferencia: referencePoint,
    endereco: this.addressApiMapper.mapDomainToApiModel(adr),
  })
}

export class BDUpdateAddressApiMapper implements ApiAdapter<UpdateBDAddress['Input'], AtualizarEnderecoDadosNegocioRequest> {
  private bdAddressApiMapper: BDAddressApiMapper
  constructor() {
    this.bdAddressApiMapper = new BDAddressApiMapper()
  }
  public mapDomainToApiModel = (input: UpdateBDAddress['Input']): AtualizarEnderecoDadosNegocioRequest => ({
    projetoId: input.projectId,
    dadosNegocioEnderecoApiModel: this.bdAddressApiMapper.mapDomainToApiModel(input.address),
  })
}

export class BDStockSalesCostsApiAdapter implements ApiAdapter<StockSalesCosts, DadosNegocioEstoqueVendasCustosApiModel> {
  private documentApiAdapter: DocumentApiMapper
  constructor() {
    this.documentApiAdapter = new DocumentApiMapper()
  }
  public mapDomainToApiModel = (sSC: StockSalesCosts): DadosNegocioEstoqueVendasCustosApiModel => ({
    classificacaoMes: sSC.monthRating,
    comissaoVendas: Number(sSC.salesCommission),
    documento: sSC.document && this.documentApiAdapter.mapDomainToApiModel(sSC.document),
    mesAnoReferencia: sSC.monthYearReference,
  })
}

export class BDUpdateStockSalesCosts implements ApiAdapter<UpdateBDStockSalesCosts['Input'], AtualizarEstoqueVendasCustosDadosNegocioRequest> {
  private stockSalesCostsApiMapper: BDStockSalesCostsApiAdapter
  constructor() {
    this.stockSalesCostsApiMapper = new BDStockSalesCostsApiAdapter()
  }
  public mapDomainToApiModel = (input: UpdateBDStockSalesCosts['Input']): AtualizarEstoqueVendasCustosDadosNegocioRequest => ({
    projetoId: input.projectId,
    dadosNegocioEstoqueVendasCustosApiModel: this.stockSalesCostsApiMapper.mapDomainToApiModel(input.stockSalesCosts),
  })
}
