/**
 * Subscription ORM Mapper
 *
 * Maps between Subscription domain entity and SubscriptionOrmEntity
 */

import { Subscription } from '@domain/entities/subscription.entity';
import {
  SubscriptionOrmEntity,
  SubscriptionPlanOrmType,
} from '../entities/subscription.orm-entity';

/** Maps canonical domain plan names back to the values stored in the DB. */
const DOMAIN_TO_ORM_PLAN: Record<string, SubscriptionPlanOrmType> = {
  FREE: 'BRONZE',
  STARTER: 'SILVER',
  PRO: 'GOLD',
  ENTERPRISE: 'PLATINIUM',
  // Pass-through for any value already in ORM format
  BRONZE: 'BRONZE',
  SILVER: 'SILVER',
  GOLD: 'GOLD',
  PLATINIUM: 'PLATINIUM',
};

export class SubscriptionOrmMapper {
  /**
   * Map domain entity to ORM entity
   */
  static toOrm(domain: Subscription): SubscriptionOrmEntity {
    const orm = new SubscriptionOrmEntity();
    const props = domain.toObject();

    orm.id = props.id;
    orm.organizationId = props.organizationId;
    orm.plan = DOMAIN_TO_ORM_PLAN[props.plan] ?? 'BRONZE';
    orm.status = props.status;
    orm.stripeCustomerId = props.stripeCustomerId;
    orm.stripeSubscriptionId = props.stripeSubscriptionId;
    orm.currentPeriodStart = props.currentPeriodStart;
    orm.currentPeriodEnd = props.currentPeriodEnd;
    orm.cancelAtPeriodEnd = props.cancelAtPeriodEnd;
    orm.createdAt = props.createdAt;
    orm.updatedAt = props.updatedAt;

    return orm;
  }

  /**
   * Map ORM entity to domain entity
   */
  static toDomain(orm: SubscriptionOrmEntity): Subscription {
    return Subscription.fromPersistence({
      id: orm.id,
      organizationId: orm.organizationId,
      plan: orm.plan,
      status: orm.status,
      stripeCustomerId: orm.stripeCustomerId,
      stripeSubscriptionId: orm.stripeSubscriptionId,
      currentPeriodStart: orm.currentPeriodStart,
      currentPeriodEnd: orm.currentPeriodEnd,
      cancelAtPeriodEnd: orm.cancelAtPeriodEnd,
      createdAt: orm.createdAt,
      updatedAt: orm.updatedAt,
    });
  }

  /**
   * Map array of ORM entities to domain entities
   */
  static toDomainMany(orms: SubscriptionOrmEntity[]): Subscription[] {
    return orms.map(orm => this.toDomain(orm));
  }
}
