import {
  ISequelizeMapper,
  MapperParamsType,
  SequelizeMapper,
} from "@/contexts/common/infrastructure";
import { DealerStatus } from "@/contexts/sales/domain";
import { Dealer_Model, DealerCreationAttributes } from "@/contexts/sales/infrastructure/sequelize";
import {
  CurrencyData,
  Language,
  Name,
  Percentage,
  TextValueObject,
  UniqueID,
} from "@shared/contexts";
import { IProfileProps, Profile } from "../../domain";
import { ProfileLogotype } from "../../domain/entities/ProfileLogotype";
import { IProfileContext } from "../Profile.context";

export interface IProfileMapper
  extends ISequelizeMapper<Dealer_Model, Partial<DealerCreationAttributes>, Profile> {}

class ProfileMapper
  extends SequelizeMapper<Dealer_Model, Partial<DealerCreationAttributes>, Profile>
  implements IProfileMapper
{
  public constructor(props: { context: IProfileContext }) {
    super(props);
  }

  protected toDomainMappingImpl(source: Dealer_Model, params: any): Profile {
    const name = this.mapsValue(source, "name", Name.create);
    const status = this.mapsValue(source, "status", DealerStatus.create);
    const language = this.mapsValue(source, "lang_code", Language.createFromCode);
    const currency = this.mapsValue(source, "currency_code", CurrencyData.createFromCode);
    const logo = this.mapsValue(source, "logo", ProfileLogotype.create);

    const contactInformation = this.mapsValue(
      source,
      "contact_information",
      TextValueObject.create
    );
    const defaultPaymentMethod = this.mapsValue(
      source,
      "default_payment_method",
      TextValueObject.create
    );
    const defaultNotes = this.mapsValue(source, "default_notes", TextValueObject.create);
    const defaultLegalTerms = this.mapsValue(source, "default_legal_terms", TextValueObject.create);
    const defaultQuoteValidity = this.mapsValue(
      source,
      "default_quote_validity",
      TextValueObject.create
    );

    const defaultTax = this.mapsValue(source, "default_tax", (tax) =>
      Percentage.create({
        amount: tax,
        scale: 2,
      })
    );

    const props: IProfileProps = {
      name,
      status,
      language,
      currency,

      contactInformation,
      defaultPaymentMethod,
      defaultNotes,
      defaultLegalTerms,
      defaultQuoteValidity,
      defaultTax,

      logo,
    };

    const id = this.mapsValue(source, "id", UniqueID.create);
    const userOrError = Profile.create(props, id);

    if (userOrError.isFailure) {
      throw userOrError.error;
    }

    return userOrError.object;
  }

  protected toPersistenceMappingImpl(source: Profile, params?: MapperParamsType | undefined) {
    return {
      id: source.id.toPrimitive(),

      contact_information: source.contactInformation.toPrimitive(),
      default_payment_method: source.defaultPaymentMethod.toPrimitive(),
      default_notes: source.defaultNotes.toPrimitive(),
      default_legal_terms: source.defaultLegalTerms.toPrimitive(),
      default_quote_validity: source.defaultQuoteValidity.toPrimitive(),
      default_tax: source.defaultTax.convertScale(2).toPrimitive(),
      logo: source.logo.toPrimitive(),
    };
  }
}

export const createProfileMapper = (context: IProfileContext): IProfileMapper =>
  new ProfileMapper({
    context,
  });
