import {
  CreationOptional,
  DataTypes,
  InferAttributes,
  InferCreationAttributes,
  Model,
  NonAttribute,
  Op,
  Sequelize,
} from "sequelize";
import { Dealer_Model } from "./dealer.model";
import { QuoteItemCreationAttributes, QuoteItem_Model } from "./quoteItem.model";

export type QuoteCreationAttributes = InferCreationAttributes<
  Quote_Model,
  { omit: "items" | "dealer" | "id_contract" }
> & {
  items: QuoteItemCreationAttributes[];
  dealer_id: string;
};

export class Quote_Model extends Model<
  InferAttributes<Quote_Model, { omit: "items" | "dealer" }>,
  InferCreationAttributes<Quote_Model, { omit: "items" | "dealer" }>
> {
  static associate(connection: Sequelize) {
    const { Quote_Model, QuoteItem_Model, Dealer_Model } = connection.models;

    Quote_Model.hasMany(QuoteItem_Model, {
      as: "items",
      foreignKey: "quote_id",
      onDelete: "CASCADE",
    });

    Quote_Model.belongsTo(Dealer_Model, {
      foreignKey: "dealer_id",
      as: "dealer",
      onDelete: "RESTRICT",
    });
  }

  declare id: string;
  declare status: CreationOptional<string>;
  declare date: CreationOptional<string>;
  declare reference: CreationOptional<string>;
  declare lang_code: CreationOptional<string>;
  declare customer_reference: CreationOptional<string>;
  declare customer_information: CreationOptional<string>;
  declare currency_code: CreationOptional<string>;
  declare payment_method: CreationOptional<string>;
  declare notes: CreationOptional<string>;
  declare validity: CreationOptional<string>;

  declare subtotal_price: CreationOptional<number | null>;

  declare discount: CreationOptional<number | null>;
  declare discount_price: CreationOptional<number | null>;

  declare before_tax_price: CreationOptional<number | null>;

  declare tax: CreationOptional<number | null>;
  declare tax_price: CreationOptional<number | null>;

  declare total_price: CreationOptional<number | null>;

  declare items: NonAttribute<QuoteItem_Model[]>;
  declare dealer: NonAttribute<Dealer_Model>;

  declare id_contract: CreationOptional<string | null>;
  declare date_sent: CreationOptional<string | null>;
}

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

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

      date: {
        type: new DataTypes.DATE(),
        allowNull: false,
      },

      reference: {
        type: new DataTypes.STRING(),
      },

      lang_code: {
        type: DataTypes.STRING(2),
        allowNull: false,
        defaultValue: "es",
      },

      currency_code: {
        type: new DataTypes.STRING(3),
        allowNull: false,
        defaultValue: "EUR",
      },

      customer_reference: {
        type: new DataTypes.STRING(),
      },

      customer_information: {
        type: DataTypes.TEXT,
      },

      payment_method: {
        type: DataTypes.TEXT,
      },

      notes: {
        type: DataTypes.TEXT,
      },

      validity: {
        type: DataTypes.TEXT,
      },

      subtotal_price: {
        type: new DataTypes.BIGINT(),
        allowNull: true,
      },

      discount: {
        type: new DataTypes.SMALLINT(),
        allowNull: true,
      },

      discount_price: {
        type: new DataTypes.BIGINT(),
        allowNull: true,
      },

      before_tax_price: {
        type: new DataTypes.BIGINT(),
        allowNull: true,
      },

      tax: {
        type: new DataTypes.SMALLINT(),
        allowNull: true,
      },

      tax_price: {
        type: new DataTypes.BIGINT(),
        allowNull: true,
      },

      total_price: {
        type: new DataTypes.BIGINT(),
        allowNull: true,
      },

      id_contract: {
        type: DataTypes.BIGINT().UNSIGNED,
        allowNull: true,
      },

      date_sent: {
        type: new DataTypes.DATE(),
        allowNull: true,
      },
    },
    {
      sequelize,
      tableName: "quotes",

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

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

      indexes: [
        { name: "status_idx", fields: ["status"] },
        { name: "reference_idx", fields: ["reference"] },
        { name: "deleted_at_idx", fields: ["deleted_at"] },
        { name: "date_sent_idx", fields: ["date_sent"] },
        { name: "id_contract_idx", fields: ["id_contract"] },
      ],

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

      defaultScope: {
        order: [
          ["reference", "DESC"],
          ["date", "DESC"],
        ],
      },

      scopes: {
        quickSearch(value) {
          return {
            where: {
              [Op.or]: {
                reference: {
                  [Op.like]: `%${value}%`,
                },
                customer_reference: {
                  [Op.like]: `%${value}%`,
                },
                customer_information: {
                  [Op.like]: `%${value}%`,
                },
              },
            },
            order: [
              ["reference", "DESC"],
              ["date", "DESC"],
            ],
          };
        },
      },
    }
  );

  return Quote_Model;
};
