/**
 * Sale Model
 * Represents sales transactions (POS or Invoice)
 */

module.exports = (sequelize, DataTypes) => {
  // Define Sale model
  const Sale = sequelize.define('Sale', {
    // Primary key
    id: {
      type: DataTypes.BIGINT, // Use BIGINT for large scale
      primaryKey: true, // Set as primary key
      autoIncrement: true, // Auto-increment ID
    },
    // Invoice number (unique identifier for the sale)
    invoice_no: {
      type: DataTypes.STRING(100), // Invoice number with max length
      allowNull: true, // Invoice number is optional (can be generated)
      unique: true, // Invoice number must be unique if provided
      validate: {
        len: [0, 100], // Maximum length validation
      },
    },
    // Foreign key to Customer (optional - null for walk-in customers)
    customer_id: {
      type: DataTypes.BIGINT, // Match Customer ID type
      allowNull: true, // Customer ID is optional (allows sales without customers)
      references: {
        model: 'customers', // Reference to customers table
        key: 'id', // Reference to id column
      },
      onUpdate: 'CASCADE', // Cascade update on customer update
    },
    // Sale type (POS for walk-in or Invoice for B2B)
    sale_type: {
      type: DataTypes.ENUM('POS', 'INVOICE'), // Enum for sale type
      allowNull: false, // Sale type is required
      defaultValue: 'POS', // Default to POS (walk-in sale)
      validate: {
        isIn: [['POS', 'INVOICE']], // Validate enum values
      },
    },
    // Foreign key to User (cashier who created the sale)
    user_id: {
      type: DataTypes.BIGINT, // Match User ID type
      allowNull: true, // User ID is optional (for backward compatibility)
      references: {
        model: 'users', // Reference to users table
        key: 'id', // Reference to id column
      },
      onUpdate: 'CASCADE', // Cascade update on user update
    },
    // Sale status
    status: {
      type: DataTypes.ENUM('DRAFT', 'PAID', 'CANCELLED'), // Enum for sale status
      defaultValue: 'DRAFT', // Default status is DRAFT
      allowNull: false, // Status is required
      validate: {
        isIn: [['DRAFT', 'PAID', 'CANCELLED']], // Validate enum values
      },
    },
    // Fulfillment type (how items are being fulfilled)
    fulfillment_type: {
      type: DataTypes.ENUM('POS_SALE', 'ORDER', 'PREORDER', 'LAYAWAY', 'SPLIT_FULFILLMENT'), // Enum for fulfillment type
      defaultValue: 'POS_SALE', // Default to immediate POS sale
      allowNull: false, // Fulfillment type is required
      validate: {
        isIn: [['POS_SALE', 'ORDER', 'PREORDER', 'LAYAWAY', 'SPLIT_FULFILLMENT']], // Validate enum values
      },
    },
    // Subtotal before discount
    subtotal: {
      type: DataTypes.DECIMAL(12, 2), // Decimal with 12 digits, 2 decimal places
      allowNull: false, // Subtotal is required
      defaultValue: 0, // Default subtotal is 0
      validate: {
        min: 0, // Subtotal cannot be negative
      },
    },
    // Total amount (subtotal - discount_amount)
    total: {
      type: DataTypes.DECIMAL(12, 2), // Decimal with 12 digits, 2 decimal places
      allowNull: false, // Total is required
      defaultValue: 0, // Default total is 0
      validate: {
        min: 0, // Total cannot be negative
      },
    },
    // Foreign key to Discount (optional - discount applied to sale)
    discount_id: {
      type: DataTypes.BIGINT, // Match Discount ID type
      allowNull: true, // Discount ID is optional (sales can be without discounts)
      references: {
        model: 'discounts', // Reference to discounts table
        key: 'id', // Reference to id column
      },
      onUpdate: 'CASCADE', // Cascade update on discount update
    },
    // Discount amount applied to this sale
    discount_amount: {
      type: DataTypes.DECIMAL(12, 2), // Decimal with 12 digits, 2 decimal places
      allowNull: false, // Discount amount is required
      defaultValue: 0, // Default discount amount is 0
      validate: {
        min: 0, // Discount amount cannot be negative
      },
    },
    // Dispatch status (whether items have been dispatched from inventory)
    dispatched: {
      type: DataTypes.BOOLEAN, // Boolean for dispatch status
      allowNull: false, // Dispatch status is required
      defaultValue: false, // Default to not dispatched
    },
    // Dispatch timestamp (when items were dispatched)
    dispatched_at: {
      type: DataTypes.DATE, // Date/time for dispatch
      allowNull: true, // Dispatch timestamp is optional (null if not dispatched)
    },
    // Foreign key to User who dispatched the sale (optional)
    dispatched_by: {
      type: DataTypes.BIGINT, // Match User ID type
      allowNull: true, // Dispatcher ID is optional
      references: {
        model: 'users', // Reference to users table
        key: 'id', // Reference to id column
      },
      onUpdate: 'CASCADE', // Cascade update on user update
    },
  }, {
    // Model options
    tableName: 'sales', // Explicit table name
    underscored: true, // Use snake_case for database columns
    timestamps: true, // Enable createdAt and updatedAt timestamps
    createdAt: 'created_at', // Map createdAt to created_at column
    updatedAt: 'updated_at', // Map updatedAt to updated_at column
    indexes: [
      // Unique index on invoice_no (already enforced by unique constraint)
      {
        unique: true, // Unique index
        fields: ['invoice_no'], // Index on invoice_no field
        where: {
          invoice_no: {
            [sequelize.Sequelize.Op.ne]: null, // Only index non-null invoice numbers
          },
        },
      },
      // Index on customer_id for faster lookups
      {
        fields: ['customer_id'], // Index on customer_id field
      },
      // Index on sale_type for filtering
      {
        fields: ['sale_type'], // Index on sale_type field
      },
      // Index on status for filtering
      {
        fields: ['status'], // Index on status field
      },
      // Index on fulfillment_type for filtering
      {
        fields: ['fulfillment_type'], // Index on fulfillment_type field
      },
      // Index on created_at for date-based queries
      {
        fields: ['created_at'], // Index on created_at field
      },
      // Index on user_id for filtering by cashier
      {
        fields: ['user_id'], // Index on user_id field
      },
      // Index on discount_id for filtering by discount
      {
        fields: ['discount_id'], // Index on discount_id field
      },
      // Index on dispatched for filtering
      {
        fields: ['dispatched'], // Index on dispatched field
      },
    ],
  });

  // Define model associations
  Sale.associate = (models) => {
    // Sale belongs to Customer (many-to-one relationship, optional)
    Sale.belongsTo(models.Customer, {
      foreignKey: 'customer_id', // Foreign key in Sale table
      as: 'customer', // Alias for association
    });
    
    // Sale has many SaleItems (one-to-many relationship)
    Sale.hasMany(models.SaleItem, {
      foreignKey: 'sale_id', // Foreign key in SaleItems table
      as: 'items', // Alias for association
      onDelete: 'CASCADE', // Cascade delete items when sale is deleted
    });
    
    // Sale has many Payments (one-to-many relationship)
    Sale.hasMany(models.Payment, {
      foreignKey: 'sale_id', // Foreign key in Payments table
      as: 'payments', // Alias for association
    });
    
    // Sale has many FiscalReceipts (one-to-many relationship)
    Sale.hasMany(models.FiscalReceipt, {
      foreignKey: 'sale_id', // Foreign key in FiscalReceipts table
      as: 'fiscalReceipts', // Alias for association
    });
    
    // Sale has many Returns (one-to-many relationship)
    Sale.hasMany(models.Return, {
      foreignKey: 'sale_id', // Foreign key in Returns table
      as: 'returns', // Alias for association
    });
    
    // Sale belongs to User (many-to-one relationship - cashier who created the sale)
    Sale.belongsTo(models.User, {
      foreignKey: 'user_id', // Foreign key in Sale table
      as: 'user', // Alias for association
    });
    
    // Sale belongs to Discount (many-to-one relationship, optional)
    Sale.belongsTo(models.Discount, {
      foreignKey: 'discount_id', // Foreign key in Sale table
      as: 'discount', // Alias for association
    });
    
    // Sale belongs to User (dispatcher) - many-to-one relationship, optional
    Sale.belongsTo(models.User, {
      foreignKey: 'dispatched_by', // Foreign key in Sale table
      as: 'dispatcher', // Alias for association
    });
  };

  // Return Sale model
  return Sale;
};

