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

import { createIdGenerator } from '../../libs/util';

export const nextEntitlementGrantId = createIdGenerator('eg', 24);

// One Subscription (or other source) grants an Entitlement to a Customer.
// Multiple grants for the same (customer, entitlement) can coexist across channels;
// the "currently effective" grant is determined by status + active_until.
// eslint-disable-next-line prettier/prettier
export class EntitlementGrant extends Model<InferAttributes<EntitlementGrant>, InferCreationAttributes<EntitlementGrant>> {
  declare id: CreationOptional<string>;
  declare livemode: boolean;

  declare entitlement_id: string;
  declare customer_id: string;

  declare source_subscription_id?: string;
  declare source_channel: LiteralUnion<
    'stripe' | 'arcblock' | 'ethereum' | 'base' | 'app_store' | 'google_play',
    string
  >;

  declare active_from: number;
  declare active_until: number;

  declare status: LiteralUnion<'active' | 'canceled' | 'expired' | 'voided', string>;

  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: nextEntitlementGrantId,
    },
    livemode: {
      type: DataTypes.BOOLEAN,
      allowNull: false,
    },
    entitlement_id: {
      type: DataTypes.STRING(30),
      allowNull: false,
    },
    customer_id: {
      type: DataTypes.STRING(18),
      allowNull: false,
    },
    source_subscription_id: {
      type: DataTypes.STRING(30),
      allowNull: true,
    },
    source_channel: {
      type: DataTypes.STRING(20),
      allowNull: false,
    },
    active_from: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
    active_until: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
    status: {
      type: DataTypes.STRING(20),
      allowNull: false,
      defaultValue: 'active',
    },
    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(EntitlementGrant.GENESIS_ATTRIBUTES, {
      sequelize,
      modelName: 'EntitlementGrant',
      tableName: 'entitlement_grants',
      createdAt: 'created_at',
      updatedAt: 'updated_at',
    });
  }

  public static associate(models: any) {
    this.belongsTo(models.Entitlement, {
      foreignKey: 'entitlement_id',
      as: 'entitlement',
    });
    this.belongsTo(models.Customer, {
      foreignKey: 'customer_id',
      as: 'customer',
    });
    this.belongsTo(models.Subscription, {
      foreignKey: 'source_subscription_id',
      as: 'subscription',
    });
  }
}

export type TEntitlementGrant = InferAttributes<EntitlementGrant>;
