import {
  Address,
  Home,
  InvolvedPerson,
  IPAddress,
  PersonalData,
  Reference,
  RG,
  SourceIncome,
  UpdateCDSpouseData,
  Vehicle,
  Workplace
} from '@agiliza/api/domain'
import {
  EnderecoApiModel,
  ProjetoPessoaEnvolvidaConjugeApiModel,
  ProjetoPessoaEnvolvidaConjugeDadosAdicionaisApiModel,
  ProjetoPessoaEnvolvidaConjugeDadosAdicionaisLocalTrabalhoApiModel,
  ProjetoPessoaEnvolvidaDadosMoradiaApiModel,
  ProjetoPessoaEnvolvidaDadosPessoaisApiModel,
  ProjetoPessoaEnvolvidaEnderecoApiModel,
  ProjetoPessoaEnvolvidaFonteRendaApiModel,
  ProjetoPessoaEnvolvidaIdentificacaoApiModel,
  ProjetoPessoaEnvolvidaReferenciaApiModel,
  ProjetoPessoaEnvolvidaRGApiModel,
  ProjetoPessoaEnvolvidaVeiculoApiModel
} from '@microcredito/client'

import { DomainAdapter } from '../shared'

export class AddressMapper implements DomainAdapter<EnderecoApiModel, Address> {
  public mapApiModelToDomain = (endereco: EnderecoApiModel): Address => ({
    id: endereco.id || '',
    cep: endereco.cep,
    city: endereco.municipio,
    state: endereco.estado,
    complement: endereco.complemento || '',
    district: endereco.bairro,
    street: endereco.logradouro,
    number: endereco.numero,
  })
}

export class CDIdentificationAdapter implements DomainAdapter<ProjetoPessoaEnvolvidaIdentificacaoApiModel, InvolvedPerson['identification']> {
  public mapContaBanestesToDomain = (
    conta: ProjetoPessoaEnvolvidaIdentificacaoApiModel['contaBanestes']
  ): InvolvedPerson['identification']['account'] => ({
    number: conta?.numeroConta,
    agencyNumber: conta?.numeroAgencia,
    cardPicture: conta?.fotoCartao,
  })

  public mapDadosTipoToDomain = (dados: ProjetoPessoaEnvolvidaIdentificacaoApiModel['dadosTipo']): InvolvedPerson['identification']['dataType'] => ({
    doesWithdrawal: dados?.fazRetirada,
    framework: dados?.enquadramento,
    participationPercentage: dados?.porcentagemParticipacao?.toString() ?? '',
  })

  public mapApiModelToDomain = (pessoa: ProjetoPessoaEnvolvidaIdentificacaoApiModel): InvolvedPerson['identification'] => ({
    id: pessoa.id || '',
    name: pessoa.nome,
    cpfcnpj: pessoa.cpfcnpj,
    gender: pessoa.sexo,
    type: pessoa.tipo,
    account: pessoa.contaBanestes ? this.mapContaBanestesToDomain(pessoa.contaBanestes) : undefined,
    dataType: pessoa.dadosTipo ? this.mapDadosTipoToDomain(pessoa.dadosTipo) : undefined,
  })
}

export class RGMapper implements DomainAdapter<ProjetoPessoaEnvolvidaRGApiModel, RG> {
  public mapApiModelToDomain = (rg: ProjetoPessoaEnvolvidaRGApiModel): RG => ({
    back: rg.verso || '',
    front: rg.frente || '',
    number: rg.numero || '',
    dispatcherAgency: rg.orgaoExpedidor || '',
  })
}

export class CDPersonalDataMapper implements DomainAdapter<ProjetoPessoaEnvolvidaDadosPessoaisApiModel, PersonalData> {
  private rgAdapter: RGMapper
  constructor() {
    this.rgAdapter = new RGMapper()
  }

  public mapApiModelToDomain = (pessoa: ProjetoPessoaEnvolvidaDadosPessoaisApiModel): PersonalData => ({
    rg: pessoa.rg ? this.rgAdapter.mapApiModelToDomain(pessoa.rg) : undefined,
    birthday: pessoa.dataNascimento || null,
    userCRAS: pessoa.usuarioCRAS ?? false,
    mothersName: pessoa.nomeMae ?? '',
    fathersName: pessoa.nomePai ?? '',
    occupation: pessoa.profissao ?? '',
    schooling: pessoa.escolaridade ?? '',
    maritalStatus: pessoa.estadoCivil ?? '',
    dependents: pessoa.dependentes ?? '',
    primaryEmail: pessoa.emailPrimario ?? '',
    secundaryEmail: pessoa.emailSecundario ?? '',
    mobile: pessoa.telefone ?? '',
    landline: pessoa.telefoneFixo ?? '',
  })
}

export class CDUpdateAddressMapper implements DomainAdapter<ProjetoPessoaEnvolvidaEnderecoApiModel, IPAddress> {
  public mapApiModelToDomain = ({ endereco, comprovante }: ProjetoPessoaEnvolvidaEnderecoApiModel): IPAddress => ({
    id: endereco?.id || '',
    proof: comprovante || '',
    cep: endereco?.cep || '',
    number: endereco?.numero || '',
    state: endereco?.estado || '',
    city: endereco?.municipio || '',
    district: endereco?.bairro || '',
    complement: endereco?.complemento || '',
    street: endereco?.logradouro || '',
  })
}

export class CDSourceIncomeAdapter implements DomainAdapter<ProjetoPessoaEnvolvidaFonteRendaApiModel, SourceIncome> {
  private addressAdapter: AddressMapper
  constructor() {
    this.addressAdapter = new AddressMapper()
  }

  public mapApiModelToDomain = (fonteRenda: ProjetoPessoaEnvolvidaFonteRendaApiModel): SourceIncome => ({
    cnpj: fonteRenda.cnpj || '',
    admissionDate: fonteRenda.dataAdmissao || null,
    companyName: fonteRenda.razaoSocial || '',
    position: fonteRenda.cargoFuncao || '',
    mobile: fonteRenda.telefone || '',
    netIncome: fonteRenda.rendaLiquida ? fonteRenda.rendaLiquida.toFixed(2) : '',
    proofAddress: fonteRenda.fotoComprovante || '',
    address: fonteRenda.endereco ? this.addressAdapter.mapApiModelToDomain(fonteRenda.endereco) : undefined,
  })
}

export class WorkplaceAdapter implements DomainAdapter<ProjetoPessoaEnvolvidaConjugeDadosAdicionaisLocalTrabalhoApiModel, Workplace> {
  public mapApiModelToDomain = (localTrabalho: ProjetoPessoaEnvolvidaConjugeDadosAdicionaisLocalTrabalhoApiModel): Workplace => ({
    // address: localTrabalho.endereco ? this.addressAdapter.mapApiModelToDomain(localTrabalho.endereco) : undefined,
    admissionDate: localTrabalho.dataAdmissao,
    netIncome: localTrabalho.rendaLiquida?.toFixed(2),
    phone: localTrabalho.telefone,
    proof: localTrabalho.comprovanteRenda,
    role: localTrabalho.cargo,
    workplaceName: localTrabalho.razaoSocial,
    cnpj: localTrabalho.cnpj,
  })
}

export class CDUpdateSpouseDataMapper implements DomainAdapter<ProjetoPessoaEnvolvidaConjugeApiModel, UpdateCDSpouseData['Output']> {
  private rgMapper: RGMapper
  private workspaceMapper: WorkplaceAdapter
  constructor() {
    this.rgMapper = new RGMapper()
    this.workspaceMapper = new WorkplaceAdapter()
  }
  public mapApiModelToDomain = (
    pessoa: ProjetoPessoaEnvolvidaConjugeApiModel & ProjetoPessoaEnvolvidaConjugeDadosAdicionaisApiModel
  ): UpdateCDSpouseData['Output'] => ({
    rg: pessoa.rg ? this.rgMapper.mapApiModelToDomain(pessoa.rg) : undefined,
    birthday: pessoa.dataNascimento,
    userCRAS: pessoa.usuarioCRAS ?? false,
    mothersName: pessoa.nomeMae ?? '',
    fathersName: pessoa.nomePai ?? '',
    occupation: pessoa.profissao ?? '',
    schooling: pessoa.escolaridade?.toString() ?? '',
    maritalStatus: pessoa.estadoCivil?.toString() ?? '',
    dependents: pessoa.dependentes?.toString() ?? '',
    participationPercentage: pessoa.porcentagemParticipacao?.toString() ?? undefined,
    name: pessoa.nome ?? '',
    cpf: pessoa.cpf ?? '',
    marriageCertificate: pessoa.certidaoCasamento ?? '',
    landline: pessoa.telefoneFixo ?? '',
    mobile: pessoa.telefoneCelular ?? '',
    primaryEmail: pessoa.emailPrimario ?? '',
    secundaryEmail: pessoa.emailSecundario ?? '',
    workplace: pessoa.localTrabalho ? this.workspaceMapper.mapApiModelToDomain(pessoa.localTrabalho) : undefined,
  })
}

export class ReferenceMapper implements DomainAdapter<ProjetoPessoaEnvolvidaReferenciaApiModel, Reference> {
  public mapApiModelToDomain = (ref: ProjetoPessoaEnvolvidaReferenciaApiModel): Reference => ({
    concept: ref.conceito || '',
    extraInfo: ref.outrasInformacoes || '',
    id: ref.id || '',
    name: ref.nome || '',
    photo: ref.foto ? ref.foto : '',
    telephone: ref.telefone || '',
    type: ref.tipo ? ref.tipo.toString() : '',
  })
}

export class CDUpdateHomeMapper implements DomainAdapter<ProjetoPessoaEnvolvidaDadosMoradiaApiModel, Home> {
  private addressAdapter: AddressMapper
  constructor() {
    this.addressAdapter = new AddressMapper()
  }
  public mapApiModelToDomain = (moradia: ProjetoPessoaEnvolvidaDadosMoradiaApiModel): Home => ({
    address: moradia.endereco
      ? this.addressAdapter.mapApiModelToDomain(moradia.endereco)
      : { id: '', cep: '', city: '', complement: '', district: '', number: '', state: '', street: '' },
    cityResideTime: (moradia.tempoMunicipio && moradia.tempoMunicipio.toString()) || '',
    deed: moradia.escritura || '',
    deedRecord: (moradia.registroEscritura && moradia.registroEscritura.toString()) || '',
    hasOnus: moradia.possuiOnus || false,
    marketValue: (moradia.valorMercado && moradia.valorMercado.toFixed(2)) || '',
    reside: moradia.resideImovel || false,
    resideTime: (moradia.tempoLocal && moradia.tempoLocal.toString()) || '',
    type: (moradia.tipo && moradia.tipo.toString()) || '',
    proof: '',
  })
}

export class VehicleMapper implements DomainAdapter<ProjetoPessoaEnvolvidaVeiculoApiModel, Vehicle> {
  public mapApiModelToDomain = (vcl: ProjetoPessoaEnvolvidaVeiculoApiModel): Vehicle => ({
    id: vcl.id || '',
    document: vcl.documento || '',
    hasInsurance: vcl.possuiSeguro || false,
    hasOnus: vcl.possuiOnus || false,
    licensePlate: vcl.placa || '',
    marketValue: vcl.valorMercado ? vcl.valorMercado.toFixed(2) : '',
    model: vcl.modelo || '',
    brand: vcl.marca || '',
    year: vcl.ano ? vcl.ano.toString() : '',
  })
}
