import {
  CreationOptional,
  DataTypes,
  InferAttributes,
  InferCreationAttributes,
  Model,
  NonAttribute,
  Sequelize,
} from "sequelize";
import {
  CustomerInvoiceItemTaxCreationAttributes,
  CustomerInvoiceItemTaxModel,
} from "./customer-invoice-item-tax.model";
import { CustomerInvoiceModel } from "./customer-invoice.model";

export type CustomerInvoiceItemCreationAttributes = InferCreationAttributes<
  CustomerInvoiceItemModel,
  { omit: "invoice" | "taxes" }
> & {
  taxes?: CustomerInvoiceItemTaxCreationAttributes[];
};

export class CustomerInvoiceItemModel extends Model<
  InferAttributes<CustomerInvoiceItemModel>,
  InferCreationAttributes<CustomerInvoiceItemModel, { omit: "invoice" | "taxes" }>
> {
  declare item_id: string;
  declare invoice_id: string;

  declare position: number;

  declare description: CreationOptional<string | null>;

  declare quantity_value: CreationOptional<number | null>;
  declare quantity_scale: number;

  declare unit_amount_value: CreationOptional<number | null>;
  declare unit_amount_scale: number;

  // Subtotal
  declare subtotal_amount_value: CreationOptional<number | null>;
  declare subtotal_amount_scale: number;

  // Discount percentage
  declare discount_percentage_value: CreationOptional<number | null>;
  declare discount_percentage_scale: number;

  // Discount amount
  declare discount_amount_value: CreationOptional<number | null>;
  declare discount_amount_scale: number;

  // Taxable amount (base imponible)
  declare taxable_amount_value: CreationOptional<number | null>;
  declare taxable_amount_scale: number;

  // Total taxes amount / taxes total
  declare taxes_amount_value: CreationOptional<number | null>;
  declare taxes_amount_scale: number;

  // Total
  declare total_amount_value: CreationOptional<number | null>;
  declare total_amount_scale: number;

  // Relaciones
  declare invoice: NonAttribute<CustomerInvoiceModel>;
  declare taxes: NonAttribute<CustomerInvoiceItemTaxModel[]>;

  static associate(database: Sequelize) {
    const { CustomerInvoiceModel, CustomerInvoiceItemModel, CustomerInvoiceItemTaxModel } =
      database.models;

    CustomerInvoiceItemModel.belongsTo(CustomerInvoiceModel, {
      as: "invoice",
      targetKey: "id",
      foreignKey: "invoice_id",
      onDelete: "CASCADE",
      onUpdate: "CASCADE",
    });

    CustomerInvoiceItemModel.hasMany(CustomerInvoiceItemTaxModel, {
      as: "taxes",
      foreignKey: "item_id",
      sourceKey: "item_id",
      constraints: true,
      onDelete: "CASCADE",
      onUpdate: "CASCADE",
    });
  }
}

export default (database: Sequelize) => {
  CustomerInvoiceItemModel.init(
    {
      item_id: {
        type: DataTypes.UUID,
        primaryKey: true,
      },

      invoice_id: {
        type: DataTypes.UUID,
        allowNull: false,
      },

      position: {
        type: new DataTypes.MEDIUMINT().UNSIGNED,
        autoIncrement: false,
        allowNull: false,
      },

      description: {
        type: new DataTypes.TEXT(),
        allowNull: true,
        defaultValue: null,
      },

      quantity_value: {
        type: new DataTypes.BIGINT(),
        allowNull: true,
        defaultValue: null,
      },

      quantity_scale: {
        type: new DataTypes.SMALLINT(),
        allowNull: false,
        defaultValue: 2,
      },

      unit_amount_value: {
        type: new DataTypes.BIGINT(),
        allowNull: true,
        defaultValue: null,
      },

      unit_amount_scale: {
        type: new DataTypes.SMALLINT(),
        allowNull: false,
        defaultValue: 4,
      },

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

      subtotal_amount_scale: {
        type: new DataTypes.SMALLINT(),
        allowNull: false,
        defaultValue: 4,
      },

      discount_percentage_value: {
        type: new DataTypes.SMALLINT(),
        allowNull: true,
        defaultValue: null,
      },

      discount_percentage_scale: {
        type: new DataTypes.SMALLINT(),
        allowNull: false,
        defaultValue: 2,
      },

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

      discount_amount_scale: {
        type: new DataTypes.SMALLINT(),
        allowNull: false,
        defaultValue: 4,
      },

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

      taxable_amount_scale: {
        type: new DataTypes.SMALLINT(),
        allowNull: false,
        defaultValue: 4,
      },

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

      taxes_amount_scale: {
        type: new DataTypes.SMALLINT(),
        allowNull: false,
        defaultValue: 4,
      },

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

      total_amount_scale: {
        type: new DataTypes.SMALLINT(),
        allowNull: false,
        defaultValue: 4,
      },
    },
    {
      sequelize: database,
      tableName: "customer_invoice_items",

      underscored: true,

      indexes: [],

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

      defaultScope: {
        order: [["position", "ASC"]],
      },

      scopes: {},
    }
  );

  return CustomerInvoiceItemModel;
};
