/* eslint-disable @typescript-eslint/lines-between-class-members */
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from 'sequelize';

import { createIdGenerator } from '../../libs/util';
import type { EventType } from './types';

const nextId = createIdGenerator('evt', 24);

// eslint-disable-next-line prettier/prettier
export class Event extends Model<InferAttributes<Event>, InferCreationAttributes<Event>> {
  declare id: CreationOptional<string>;

  declare livemode: boolean;

  declare type: EventType;
  declare api_version: string;

  declare data: Record<string, any>;

  // the object that this event belongs to
  declare object_type: string;
  declare object_id: string;

  declare request: {
    id: string;
    idempotency_key: string;
    requested_by?: string;
  };

  // Number of webhooks that have yet to be successfully delivered
  declare pending_webhooks: number;

  declare metadata: Record<string, any>;

  declare created_at: CreationOptional<Date>;
  declare updated_at: CreationOptional<Date>;

  public static readonly GENESIS_ATTRIBUTES = {
    id: {
      type: DataTypes.STRING(30),
      primaryKey: true,
      allowNull: false,
      defaultValue: nextId,
    },
    livemode: {
      type: DataTypes.BOOLEAN,
      allowNull: false,
    },
    type: {
      type: DataTypes.STRING(64),
      allowNull: false,
    },
    api_version: {
      type: DataTypes.STRING(16),
      allowNull: false,
    },
    object_type: {
      type: DataTypes.STRING(32),
      allowNull: false,
    },
    object_id: {
      type: DataTypes.STRING(32),
      allowNull: false,
    },
    data: {
      type: DataTypes.JSON,
      allowNull: false,
    },
    request: {
      type: DataTypes.JSON,
      allowNull: false,
    },
    pending_webhooks: {
      type: DataTypes.NUMBER,
      allowNull: false,
    },
    metadata: {
      type: DataTypes.JSON,
      allowNull: true,
    },
    created_at: {
      type: DataTypes.DATE,
      defaultValue: DataTypes.NOW,
      allowNull: false,
    },
    updated_at: {
      type: DataTypes.DATE,
      defaultValue: DataTypes.NOW,
      allowNull: false,
    },
  };

  public static initialize(sequelize: any) {
    this.init(Event.GENESIS_ATTRIBUTES, {
      sequelize,
      modelName: 'Event',
      tableName: 'events',
      createdAt: 'created_at',
      updatedAt: 'updated_at',
    });
  }

  public static associate(models: any) {
    this.hasMany(models.WebhookAttempt, {
      sourceKey: 'id',
      foreignKey: 'event_id',
      as: 'webhookAttempts',
    });
  }
}

export type TEvent = InferAttributes<Event>;
