/**
 * Subscription Plan Value Object
 *
 * Represents the different subscription plans available for organizations.
 * Each plan has a maximum number of licenses, shipment limits, commission rates,
 * feature flags, and support levels.
 *
 * Plans: BRONZE (free), SILVER (249EUR/mo), GOLD (899EUR/mo), PLATINIUM (custom)
 */

import { PlanFeature, PLAN_FEATURES } from './plan-feature.vo';

export type SubscriptionPlanType = 'BRONZE' | 'SILVER' | 'GOLD' | 'PLATINIUM';

export type SupportLevel = 'none' | 'email' | 'direct' | 'dedicated_kam';
export type StatusBadge = 'none' | 'silver' | 'gold' | 'platinium';

/**
 * Legacy plan name mapping for backward compatibility during migration.
 */
const LEGACY_PLAN_MAPPING: Record<string, SubscriptionPlanType> = {
  FREE: 'BRONZE',
  STARTER: 'SILVER',
  PRO: 'GOLD',
  ENTERPRISE: 'PLATINIUM',
};

interface PlanDetails {
  readonly name: string;
  readonly maxLicenses: number; // -1 means unlimited
  readonly monthlyPriceEur: number;
  readonly yearlyPriceEur: number;
  readonly maxShipmentsPerYear: number; // -1 means unlimited
  readonly commissionRatePercent: number;
  readonly statusBadge: StatusBadge;
  readonly supportLevel: SupportLevel;
  readonly planFeatures: readonly PlanFeature[];
  readonly features: readonly string[]; // Human-readable feature descriptions
}

const PLAN_DETAILS: Record<SubscriptionPlanType, PlanDetails> = {
  BRONZE: {
    name: 'Bronze',
    maxLicenses: 1,
    monthlyPriceEur: 0,
    yearlyPriceEur: 0,
    maxShipmentsPerYear: 12,
    commissionRatePercent: 5,
    statusBadge: 'none',
    supportLevel: 'none',
    planFeatures: PLAN_FEATURES.BRONZE,
    features: ['1 utilisateur', '12 expéditions par an', 'Recherche de tarifs basique'],
  },
  SILVER: {
    name: 'Silver',
    maxLicenses: 5,
    monthlyPriceEur: 249,
    yearlyPriceEur: 2739,
    maxShipmentsPerYear: -1,
    commissionRatePercent: 3,
    statusBadge: 'silver',
    supportLevel: 'email',
    planFeatures: PLAN_FEATURES.SILVER,
    features: [
      "Jusqu'à 5 utilisateurs",
      'Expéditions illimitées',
      'Tableau de bord',
      'Wiki Maritime',
      'Gestion des utilisateurs',
      'Import CSV',
      'Support par email',
    ],
  },
  GOLD: {
    name: 'Gold',
    maxLicenses: 20,
    monthlyPriceEur: 899,
    yearlyPriceEur: 9889,
    maxShipmentsPerYear: -1,
    commissionRatePercent: 2,
    statusBadge: 'gold',
    supportLevel: 'direct',
    planFeatures: PLAN_FEATURES.GOLD,
    features: [
      "Jusqu'à 20 utilisateurs",
      'Expéditions illimitées',
      'Toutes les fonctionnalités Silver',
      'Intégration API',
      'Assistance commerciale directe',
    ],
  },
  PLATINIUM: {
    name: 'Platinium',
    maxLicenses: -1, // unlimited
    monthlyPriceEur: 0, // custom pricing
    yearlyPriceEur: 0, // custom pricing
    maxShipmentsPerYear: -1,
    commissionRatePercent: 1,
    statusBadge: 'platinium',
    supportLevel: 'dedicated_kam',
    planFeatures: PLAN_FEATURES.PLATINIUM,
    features: [
      'Utilisateurs illimités',
      'Toutes les fonctionnalités Gold',
      'Key Account Manager dédié',
      'Interface personnalisable',
      'Contrats tarifaires cadre',
    ],
  },
};

export class SubscriptionPlan {
  private constructor(private readonly plan: SubscriptionPlanType) {}

  static create(plan: SubscriptionPlanType): SubscriptionPlan {
    if (!PLAN_DETAILS[plan]) {
      throw new Error(`Invalid subscription plan: ${plan}`);
    }
    return new SubscriptionPlan(plan);
  }

  /**
   * Create from string with legacy name support.
   * Accepts both old (FREE/STARTER/PRO/ENTERPRISE) and new (BRONZE/SILVER/GOLD/PLATINIUM) names.
   */
  static fromString(value: string): SubscriptionPlan {
    const upperValue = value.toUpperCase();

    // Check legacy mapping first
    const mapped = LEGACY_PLAN_MAPPING[upperValue];
    if (mapped) {
      return new SubscriptionPlan(mapped);
    }

    // Try direct match
    if (PLAN_DETAILS[upperValue as SubscriptionPlanType]) {
      return new SubscriptionPlan(upperValue as SubscriptionPlanType);
    }

    throw new Error(`Invalid subscription plan: ${value}`);
  }

  // Named factories
  static bronze(): SubscriptionPlan {
    return new SubscriptionPlan('BRONZE');
  }

  static silver(): SubscriptionPlan {
    return new SubscriptionPlan('SILVER');
  }

  static gold(): SubscriptionPlan {
    return new SubscriptionPlan('GOLD');
  }

  static platinium(): SubscriptionPlan {
    return new SubscriptionPlan('PLATINIUM');
  }

  // Legacy aliases
  static free(): SubscriptionPlan {
    return SubscriptionPlan.bronze();
  }

  static starter(): SubscriptionPlan {
    return SubscriptionPlan.silver();
  }

  static pro(): SubscriptionPlan {
    return SubscriptionPlan.gold();
  }

  static enterprise(): SubscriptionPlan {
    return SubscriptionPlan.platinium();
  }

  static getAllPlans(): SubscriptionPlan[] {
    return (['BRONZE', 'SILVER', 'GOLD', 'PLATINIUM'] as SubscriptionPlanType[]).map(
      p => new SubscriptionPlan(p)
    );
  }

  // Getters
  get value(): SubscriptionPlanType {
    return this.plan;
  }

  get name(): string {
    return PLAN_DETAILS[this.plan].name;
  }

  get maxLicenses(): number {
    return PLAN_DETAILS[this.plan].maxLicenses;
  }

  get monthlyPriceEur(): number {
    return PLAN_DETAILS[this.plan].monthlyPriceEur;
  }

  get yearlyPriceEur(): number {
    return PLAN_DETAILS[this.plan].yearlyPriceEur;
  }

  get features(): readonly string[] {
    return PLAN_DETAILS[this.plan].features;
  }

  get maxShipmentsPerYear(): number {
    return PLAN_DETAILS[this.plan].maxShipmentsPerYear;
  }

  get commissionRatePercent(): number {
    return PLAN_DETAILS[this.plan].commissionRatePercent;
  }

  get statusBadge(): StatusBadge {
    return PLAN_DETAILS[this.plan].statusBadge;
  }

  get supportLevel(): SupportLevel {
    return PLAN_DETAILS[this.plan].supportLevel;
  }

  get planFeatures(): readonly PlanFeature[] {
    return PLAN_DETAILS[this.plan].planFeatures;
  }

  hasFeature(feature: PlanFeature): boolean {
    return this.planFeatures.includes(feature);
  }

  isUnlimited(): boolean {
    return this.maxLicenses === -1;
  }

  hasUnlimitedShipments(): boolean {
    return this.maxShipmentsPerYear === -1;
  }

  isPaid(): boolean {
    return this.plan !== 'BRONZE';
  }

  isFree(): boolean {
    return this.plan === 'BRONZE';
  }

  isCustomPricing(): boolean {
    return this.plan === 'PLATINIUM';
  }

  canAccommodateUsers(userCount: number): boolean {
    if (this.isUnlimited()) return true;
    return userCount <= this.maxLicenses;
  }

  canUpgradeTo(targetPlan: SubscriptionPlan): boolean {
    const planOrder: SubscriptionPlanType[] = ['BRONZE', 'SILVER', 'GOLD', 'PLATINIUM'];
    const currentIndex = planOrder.indexOf(this.plan);
    const targetIndex = planOrder.indexOf(targetPlan.value);
    return targetIndex > currentIndex;
  }

  canDowngradeTo(targetPlan: SubscriptionPlan, currentUserCount: number): boolean {
    const planOrder: SubscriptionPlanType[] = ['BRONZE', 'SILVER', 'GOLD', 'PLATINIUM'];
    const currentIndex = planOrder.indexOf(this.plan);
    const targetIndex = planOrder.indexOf(targetPlan.value);

    if (targetIndex >= currentIndex) return false;
    return targetPlan.canAccommodateUsers(currentUserCount);
  }

  equals(other: SubscriptionPlan): boolean {
    return this.plan === other.plan;
  }

  toString(): string {
    return this.plan;
  }
}
