// Estado derivado de una suscripción — usado por backend (middleware) y frontend
// (sidebar, banner) para coincidir en una sola lógica de "qué puede hacer este tenant".

export type SubscriptionStatus =
  | 'trial'
  | 'trial_converted'
  | 'trial_expired'
  | 'pending'
  | 'authorized'
  | 'paused'
  | 'cancelled';

export interface SubscriptionLike {
  status: string | null;
  currentPeriodEnd?: string | Date | null;
}

export interface SubscriptionState {
  status: SubscriptionStatus | null;
  daysUntilEnd: number | null;
  isExpired: boolean;
  isTrial: boolean;
  isTrialExpired: boolean;
  isActive: boolean;
  isCancelledInPeriod: boolean;
  isCancelledExpired: boolean;
  isPending: boolean;
  /** Bloqueante: el tenant no puede escribir y debe renovar para continuar. */
  needsRenewal: boolean;
  /** Aviso pre-vencimiento (≤7 días). Se cumple incluso en `authorized` activo. */
  isWarning: boolean;
}

const DAY_MS = 24 * 60 * 60 * 1000;

function diffDays(end: Date, now: Date): number {
  return Math.ceil((end.getTime() - now.getTime()) / DAY_MS);
}

export function getSubscriptionState(
  subscription: SubscriptionLike | null | undefined,
  now: Date = new Date(),
): SubscriptionState {
  if (!subscription) {
    return {
      status: null,
      daysUntilEnd: null,
      isExpired: true,
      isTrial: false,
      isTrialExpired: false,
      isActive: false,
      isCancelledInPeriod: false,
      isCancelledExpired: false,
      isPending: false,
      needsRenewal: true,
      isWarning: false,
    };
  }

  const status = subscription.status as SubscriptionStatus | null;
  const end = subscription.currentPeriodEnd
    ? new Date(subscription.currentPeriodEnd)
    : null;
  const daysUntilEnd = end ? diffDays(end, now) : null;
  const isExpired = end ? end.getTime() <= now.getTime() : true;

  // El frontend ya derivaba estos flags duplicados en /configuracion/suscripcion
  // — los centralizamos aquí para que el middleware backend use la misma lógica.
  const isTrial = status === 'trial' && !isExpired;
  const isTrialExpired = status === 'trial_expired' || (status === 'trial' && isExpired);
  const isActive = status === 'authorized' && !isExpired;
  const isCancelledInPeriod = status === 'cancelled' && !isExpired;
  const isCancelledExpired = status === 'cancelled' && isExpired;
  const isPending = status === 'pending';

  // Tenant bloqueado para escritura. `pending` también permite (esperando 1er cobro).
  // `paused` (status MP) cuenta como bloqueante.
  const needsRenewal = !(isActive || isPending || isTrial || isCancelledInPeriod);

  // Aviso azul/amber: dentro de los 7 días previos al fin de período. Aplica tanto
  // a trial como a suscripción activa.
  const isWarning =
    !needsRenewal &&
    daysUntilEnd !== null &&
    daysUntilEnd > 0 &&
    daysUntilEnd <= 7;

  return {
    status,
    daysUntilEnd,
    isExpired,
    isTrial,
    isTrialExpired,
    isActive,
    isCancelledInPeriod,
    isCancelledExpired,
    isPending,
    needsRenewal,
    isWarning,
  };
}
