import {
  CreationOptional,
  DataTypes,
  InferAttributes,
  InferCreationAttributes,
  Model,
  NonAttribute,
  Sequelize,
} from "sequelize";
import { InvoiceItemCreationAttributes, InvoiceItemModel } from "./invoice-item.model";

export type InvoiceCreationAttributes = InferCreationAttributes<InvoiceModel, { omit: "items" }> & {
  items?: InvoiceItemCreationAttributes[];
};

export class InvoiceModel extends Model<
  InferAttributes<InvoiceModel>,
  InferCreationAttributes<InvoiceModel, { omit: "items" }>
> {
  declare id: string;

  declare invoice_status: string;
  declare invoice_series: CreationOptional<string>;
  declare invoice_number: CreationOptional<string>;
  declare issue_date: CreationOptional<string>;
  declare operation_date: CreationOptional<string>;
  declare invoice_language: string;
  declare invoice_currency: string;

  // Subtotal
  declare subtotal_amount: CreationOptional<number>;
  declare subtotal_scale: CreationOptional<number>;

  // Total
  declare total_amount: CreationOptional<number>;
  declare total_scale: CreationOptional<number>;

  // Relaciones
  declare items: NonAttribute<InvoiceItemModel[]>;
  //declare customer: NonAttribute<InvoiceParticipant_Model[]>;

  static associate(database: Sequelize) {
    const { InvoiceModel, InvoiceItemModel } = database.models;

    InvoiceModel.hasMany(InvoiceItemModel, {
      as: "items",
      foreignKey: "invoice_id",
      onDelete: "CASCADE",
    });
  }
}

export default (database: Sequelize) => {
  InvoiceModel.init(
    {
      id: {
        type: new DataTypes.UUID(),
        primaryKey: true,
      },

      invoice_status: {
        type: new DataTypes.STRING(),
        allowNull: false,
      },

      invoice_series: {
        type: new DataTypes.STRING(),
        allowNull: true,
        defaultValue: null,
      },

      invoice_number: {
        type: new DataTypes.STRING(),
        allowNull: true,
        defaultValue: null,
      },

      issue_date: {
        type: new DataTypes.DATEONLY(),
        allowNull: true,
        defaultValue: null,
      },

      operation_date: {
        type: new DataTypes.DATEONLY(),
        allowNull: true,
        defaultValue: null,
      },

      invoice_language: {
        type: new DataTypes.STRING(),
        allowNull: false,
      },

      invoice_currency: {
        type: new DataTypes.STRING(3), // ISO 4217
        allowNull: false,
      },

      subtotal_amount: {
        type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
        allowNull: true,
        defaultValue: null,
      },
      subtotal_scale: {
        type: new DataTypes.SMALLINT(),
        allowNull: true,
        defaultValue: null,
      },

      total_amount: {
        type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
        allowNull: true,
        defaultValue: null,
      },
      total_scale: {
        type: new DataTypes.SMALLINT(),
        allowNull: true,
        defaultValue: null,
      },
    },
    {
      sequelize: database,
      tableName: "invoices",

      paranoid: true, // softs deletes
      timestamps: true,

      createdAt: "created_at",
      updatedAt: "updated_at",
      deletedAt: "deleted_at",

      indexes: [{ unique: true, fields: ["invoice_number"] }],

      whereMergeStrategy: "and", // <- cómo tratar el merge de un scope

      defaultScope: {},

      scopes: {},
    }
  );

  return InvoiceModel;
};
