import { getSubscriptionPlan, TRIAL_DURATION_DAYS } from './plans.js';
import type {
  OrganisationSubscription,
  SubscriptionPlanId,
  SubscriptionStatus,
  SubscriptionUsage,
} from './types.js';
import type { SubscriptionFeature } from './plans.js';

const ACTIVE_STATUSES: SubscriptionStatus[] = ['trialing', 'active', 'past_due'];

export function isSubscriptionActive(subscription: OrganisationSubscription | undefined): boolean {
  if (!subscription) {
    return false;
  }

  if (!ACTIVE_STATUSES.includes(subscription.status)) {
    return false;
  }

  if (subscription.status === 'trialing' && subscription.trialEndsAt) {
    return new Date(subscription.trialEndsAt).getTime() > Date.now();
  }

  if (subscription.currentPeriodEnd) {
    return new Date(subscription.currentPeriodEnd).getTime() > Date.now();
  }

  return true;
}

export function getEffectivePlanId(
  subscription: OrganisationSubscription | undefined,
): SubscriptionPlanId {
  if (!subscription) {
    return 'trial';
  }

  if (subscription.status === 'trialing' && subscription.trialEndsAt) {
    const trialExpired = new Date(subscription.trialEndsAt).getTime() <= Date.now();
    if (trialExpired) {
      return subscription.planId === 'trial' ? 'trial' : subscription.planId;
    }
  }

  return subscription.planId;
}

export function getPlanLimits(planId: SubscriptionPlanId) {
  const plan = getSubscriptionPlan(planId);
  return {
    seatLimit: plan.seatLimit,
    siteLimit: plan.siteLimit,
    features: plan.features,
  };
}

export function hasSubscriptionFeature(
  subscription: OrganisationSubscription | undefined,
  feature: SubscriptionFeature,
): boolean {
  if (!isSubscriptionActive(subscription)) {
    return false;
  }

  const planId = getEffectivePlanId(subscription);
  const plan = getSubscriptionPlan(planId);
  return plan.features.includes(feature);
}

export function isWithinSeatLimit(usage: Pick<SubscriptionUsage, 'seatsUsed' | 'seatLimit'>): boolean {
  return usage.seatsUsed < usage.seatLimit;
}

export function isWithinSiteLimit(usage: Pick<SubscriptionUsage, 'sitesUsed' | 'siteLimit'>): boolean {
  return usage.sitesUsed < usage.siteLimit;
}

export function getTrialDaysRemaining(subscription: OrganisationSubscription | undefined): number | null {
  if (!subscription?.trialEndsAt || subscription.status !== 'trialing') {
    return null;
  }

  const msRemaining = new Date(subscription.trialEndsAt).getTime() - Date.now();
  return Math.max(0, Math.ceil(msRemaining / (24 * 60 * 60 * 1000)));
}

export function createTrialSubscription(now = new Date()): OrganisationSubscription {
  const trialEndsAt = new Date(now);
  trialEndsAt.setDate(trialEndsAt.getDate() + TRIAL_DURATION_DAYS);

  return {
    planId: 'trial',
    status: 'trialing',
    provider: 'payfast',
    trialEndsAt: trialEndsAt.toISOString(),
    currentPeriodStart: now.toISOString(),
    currentPeriodEnd: trialEndsAt.toISOString(),
  };
}
