/**
 * Payment Model
 * Represents payments for sales (supports multiple payments per sale)
 */

module.exports = (sequelize, DataTypes) => {
  // Define Payment model
  const Payment = sequelize.define('Payment', {
    // Primary key
    id: {
      type: DataTypes.BIGINT, // Use BIGINT for large scale
      primaryKey: true, // Set as primary key
      autoIncrement: true, // Auto-increment ID
    },
    // Foreign key to Sale
    sale_id: {
      type: DataTypes.BIGINT, // Match Sale ID type
      allowNull: false, // Sale ID is required
      references: {
        model: 'sales', // Reference to sales table
        key: 'id', // Reference to id column
      },
      onUpdate: 'CASCADE', // Cascade update on sale update
    },
    // Payment provider (Cash, Card, M-Pesa)
    provider: {
      type: DataTypes.ENUM('CASH', 'CARD', 'MPESA'), // Enum for payment provider
      allowNull: false, // Provider is required
      validate: {
        isIn: [['CASH', 'CARD', 'MPESA']], // Validate enum values
      },
    },
    // Payment reference (for Paystack/card payments)
    reference: {
      type: DataTypes.STRING(150), // Payment reference with max length
      allowNull: true, // Reference is optional (cash payments may not have reference)
      validate: {
        len: [0, 150], // Maximum length validation
      },
    },
    // Payment amount
    amount: {
      type: DataTypes.DECIMAL(12, 2), // Decimal with 12 digits, 2 decimal places
      allowNull: false, // Amount is required
      validate: {
        min: 0, // Amount cannot be negative
      },
    },
    // Payment status (updated to support split payments and M-Pesa)
    status: {
      type: DataTypes.ENUM('PENDING', 'SUCCESS', 'FAILED', 'CONFIRMED', 'RETRYING'), // Enum for payment status
      defaultValue: 'PENDING', // Default status is PENDING
      allowNull: false, // Status is required
      validate: {
        isIn: [['PENDING', 'SUCCESS', 'FAILED', 'CONFIRMED', 'RETRYING']], // Validate enum values
      },
    },
    // Tender sequence number (1 or 2 for split payments)
    tender_number: {
      type: DataTypes.INTEGER, // Integer for tender sequence
      allowNull: false, // Tender number is required
      defaultValue: 1, // Default to 1 (single payment)
      validate: {
        min: 1, // Must be at least 1
        max: 2, // Maximum 2 tenders per sale
      },
    },
    // M-Pesa phone number (for STK Push)
    mpesa_phone_number: {
      type: DataTypes.STRING(20), // Phone number with max length
      allowNull: true, // Optional (only for M-Pesa payments)
      validate: {
        len: [0, 20], // Maximum length validation
      },
    },
    // M-Pesa transaction code (from callback)
    mpesa_transaction_code: {
      type: DataTypes.STRING(50), // Transaction code with max length
      allowNull: true, // Optional (only for M-Pesa payments)
      validate: {
        len: [0, 50], // Maximum length validation
      },
    },
    // Card transaction reference (manual entry)
    card_reference: {
      type: DataTypes.STRING(100), // Card reference with max length
      allowNull: true, // Optional (only for card payments)
      validate: {
        len: [0, 100], // Maximum length validation
      },
    },
    // Date and time when payment was completed
    paid_at: {
      type: DataTypes.DATE, // Date and time
      allowNull: true, // Paid date is optional (only set when payment succeeds)
    },
  }, {
    // Model options
    tableName: 'payments', // 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: false, // No updatedAt for payments (immutable after creation)
    indexes: [
      // Index on sale_id for faster lookups
      {
        fields: ['sale_id'], // Index on sale_id field
      },
      // Index on provider for filtering
      {
        fields: ['provider'], // Index on provider field
      },
      // Index on status for filtering
      {
        fields: ['status'], // Index on status field
      },
      // Index on reference for lookup (unique where not null)
      {
        fields: ['reference'], // Index on reference field
      },
      // Index on paid_at for date-based queries
      {
        fields: ['paid_at'], // Index on paid_at field
      },
      // Index on tender_number for split payment queries
      {
        fields: ['sale_id', 'tender_number'], // Composite index for tender lookups
      },
      // Index on mpesa_transaction_code for M-Pesa lookups
      {
        fields: ['mpesa_transaction_code'], // Index on M-Pesa transaction code
      },
    ],
  });

  // Define model associations
  Payment.associate = (models) => {
    // Payment belongs to Sale (many-to-one relationship)
    Payment.belongsTo(models.Sale, {
      foreignKey: 'sale_id', // Foreign key in Payment table
      as: 'sale', // Alias for association
    });
  };

  // Return Payment model
  return Payment;
};

