import { ISequelizeMapper, SequelizeMapper } from "@/contexts/common/infrastructure";
import { Description, Language, Name, Quantity, Slug, UniqueID, UnitPrice } from "@shared/contexts";
import { ICatalogContext } from "..";
import { Article, ArticleIdentifier, IArticleProps } from "../../domain/entities";
import { ArticleCreationAttributes, Article_Model } from "../sequelize";

export interface IArticleMapper
  extends ISequelizeMapper<Article_Model, ArticleCreationAttributes, Article> {}

class ArticleMapper
  extends SequelizeMapper<Article_Model, ArticleCreationAttributes, Article>
  implements IArticleMapper
{
  public constructor(props: { context: ICatalogContext }) {
    super(props);
  }

  protected toDomainMappingImpl(source: Article_Model, params: any): Article {
    const catalog_name = this.mapsValue(source, "catalog_name", Name.create);
    const id_article = this.mapsValue(source, "id_article", ArticleIdentifier.create);
    const reference = this.mapsValue(source, "reference", Slug.create);
    const points = this.mapsValue(source, "points", (value: any) =>
      Quantity.create({ amount: value, scale: 2 })
    );
    const retail_price = this.mapsValue(source, "retail_price", (value: any) =>
      UnitPrice.create({ amount: value, scale: 2 })
    );

    const language = this.mapsValue(source, "lang_code", Language.createFromCode);
    const description = this.mapsValue(source, "description", Description.create);

    const props: IArticleProps = {
      catalog_name,
      id_article,
      reference,
      points,
      retail_price,
      language,
      description,
    };

    const id = this.mapsValue(source, "id", UniqueID.create);
    const productOrError = Article.create(props, id);

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

    return productOrError.object;
  }
}

export const createArticleMapper = (context: ICatalogContext): IArticleMapper =>
  new ArticleMapper({
    context,
  });
