/**
 * Catálogo de planes despacho — fuente de verdad para `features` (acopladas
 * a UI/middleware) y defaults estáticos para limits/precios.
 *
 * IMPORTANTE — split desde 2026-04-30:
 *  - **`features`**: viven aquí en código. Modificarlas requiere release.
 *  - **`maxRfcs`, `maxUsers`, `timbresIncluidosMes`, `dbMode`,
 *    `permiteServidorBackup`, `name`**: estos son **defaults** — la fuente
 *    autoritativa vive en la tabla `despacho_plan_prices` (modelo
 *    `DespachoPlanPrice`), editable por admin global. El backend lee la BD
 *    vía `getDespachoPlanLimits()` en `apps/api/src/services/plan-catalogo.service.ts`.
 *  - **`maxCfdisPorContribuyente`**: solo en TS — no se gating en runtime
 *    (los valores de millones son nominales).
 *
 * El frontend público (sidebar/feature-gate) sigue leyendo de aquí para
 * features. La UI admin (`/configuracion/precios-suscripcion`) lee de BD
 * para mostrar valores editables.
 */
export const DESPACHO_PLANS = {
  trial: {
    name: 'Trial',
    maxRfcs: 3,
    maxUsers: 1,
    maxCfdisPorContribuyente: 1_000_000,
    timbresIncluidosMes: 0,
    dbMode: 'MANAGED' as const,
    permiteServidorBackup: false,
    features: [
      'dashboard', 'cfdi_basic', 'iva_isr', 'reportes', 'alertas',
      'calendario', 'conciliacion', 'documentos', 'facturacion',
      'forecasting', 'xml_sat',
    ],
  },
  mi_empresa: {
    name: 'Mi Empresa',
    maxRfcs: 1,
    maxUsers: 3,
    maxCfdisPorContribuyente: 1_000_000,
    timbresIncluidosMes: 50,
    dbMode: 'MANAGED' as const,
    permiteServidorBackup: false,
    features: [
      'dashboard', 'cfdi_basic', 'iva_isr', 'reportes', 'alertas',
      'calendario', 'conciliacion', 'documentos', 'facturacion',
      'forecasting', 'xml_sat',
    ],
  },
  mi_empresa_plus: {
    name: 'Mi Empresa +',
    maxRfcs: 1,
    maxUsers: 3,
    maxCfdisPorContribuyente: 1_000_000,
    timbresIncluidosMes: 50,
    dbMode: 'MANAGED' as const,
    permiteServidorBackup: false,
    features: [
      'dashboard', 'cfdi_basic', 'iva_isr', 'reportes', 'alertas',
      'calendario', 'conciliacion', 'documentos', 'facturacion',
      'forecasting', 'xml_sat', 'api', 'ia_lolita',
    ],
  },
  business_control: {
    name: 'Business Control',
    maxRfcs: 100,
    maxUsers: -1,
    maxCfdisPorContribuyente: 1_000_000,
    timbresIncluidosMes: 0,
    dbMode: 'MANAGED' as const,
    permiteServidorBackup: true,
    features: [
      'dashboard', 'cfdi_basic', 'iva_isr', 'reportes', 'alertas',
      'calendario', 'conciliacion', 'documentos', 'facturacion',
      'forecasting', 'xml_sat', 'api',
    ],
  },
  // Custom — monto mensual variable, definido al provisionar el tenant.
  //   - amount = 0 → sin tarjeta, sin Subscription, sin cobro MP, no expira.
  //   - amount > 0 → Subscription con preapproval MP mensual; el monto se
  //     toma del parámetro al crear el tenant, no de DESPACHO_PLAN_PRICES.
  // Solo asignable por Admin Global. Limits idénticos a Mi Empresa
  // (1 RFC, MANAGED, sin API ni Lolita). Oculto del catálogo user-facing.
  custom: {
    name: 'Custom',
    maxRfcs: 1,
    maxUsers: 3,
    maxCfdisPorContribuyente: 1_000_000,
    timbresIncluidosMes: 50,
    dbMode: 'MANAGED' as const,
    permiteServidorBackup: false,
    features: [
      'dashboard', 'cfdi_basic', 'iva_isr', 'reportes', 'alertas',
      'calendario', 'conciliacion', 'documentos', 'facturacion',
      'forecasting', 'xml_sat',
    ],
  },
  // Identificador interno: business_cloud (no se renombra el enum por
  // backward compat de suscripciones existentes). Nombre display: "Enterprise".
  business_cloud: {
    name: 'Enterprise',
    maxRfcs: 100,
    maxUsers: -1,
    maxCfdisPorContribuyente: 3_000_000,
    timbresIncluidosMes: 0,
    dbMode: 'MANAGED' as const,
    permiteServidorBackup: true,
    features: [
      'dashboard', 'cfdi_basic', 'iva_isr', 'reportes', 'alertas',
      'calendario', 'conciliacion', 'documentos', 'facturacion',
      'forecasting', 'xml_sat', 'api',
    ],
  },
} as const;

export type DespachoPlan = keyof typeof DESPACHO_PLANS;

/**
 * Precios MXN (IVA incluido) para planes despacho pagables.
 *
 * - `monthly`: precio mensual. Solo aplica a planes con `permiteMonthly=true`
 *   (Mi Empresa, Mi Empresa+). Para Business Control y Enterprise es null.
 * - `firstYear` / `renewal`: precios anuales. `firstYear` es lo que se cobra
 *   al contratar; `renewal` lo que MP cobra automáticamente en renovaciones.
 *   Cuando ambos son iguales no hay dualidad.
 *
 * Política de descuento (D1, 2026-04-26): Mi Empresa y Mi Empresa+ tienen
 * descuento del ~17% al pagar el año adelantado — el cobro anual es
 * equivalente a 10 meses (en lugar de 12).
 *
 *   mi_empresa:       $580/mes  → $5,800/año (10 meses)
 *   mi_empresa_plus:  $900/mes  → $9,000/año (10 meses)
 */
export const DESPACHO_PLAN_PRICES = {
  mi_empresa: {
    monthly: 580,
    firstYear: 5_800,
    renewal: 5_800,
    permiteMonthly: true,
  },
  mi_empresa_plus: {
    monthly: 900,
    firstYear: 9_000,
    renewal: 9_000,
    permiteMonthly: true,
  },
  business_control: {
    monthly: null,
    firstYear: 25_850,
    renewal: 25_850,
    permiteMonthly: false,
  },
  business_cloud: { // display: Enterprise
    monthly: null,
    firstYear: 43_000,
    renewal: 43_000,
    permiteMonthly: false,
  },
} as const;

export type DespachoPaidPlan = keyof typeof DESPACHO_PLAN_PRICES;
export type DespachoPricePhase = 'firstYear' | 'renewal';
export type DespachoFrequency = 'monthly' | 'annual';

/**
 * Resuelve el precio MXN para un (plan, frequency, phase). Para monthly
 * la fase se ignora (no hay dualidad mensual). Para annual aplica
 * firstYear o renewal según corresponda. Throws si el plan no permite
 * la frecuencia solicitada.
 */
export function getPrecioDespacho(
  plan: DespachoPaidPlan,
  frequency: DespachoFrequency,
  phase: DespachoPricePhase = 'renewal',
): number {
  const cfg = DESPACHO_PLAN_PRICES[plan];
  if (frequency === 'monthly') {
    if (!cfg.permiteMonthly || cfg.monthly == null) {
      throw new Error(`El plan ${plan} no permite frecuencia mensual`);
    }
    return cfg.monthly;
  }
  return cfg[phase];
}

/** True si el plan acepta frecuencia mensual (Mi Empresa y Mi Empresa+). */
export function permiteFrecuenciaMensual(plan: string): boolean {
  if (plan in DESPACHO_PLAN_PRICES) {
    return DESPACHO_PLAN_PRICES[plan as DespachoPaidPlan].permiteMonthly;
  }
  return false;
}

/**
 * Costo mensual MXN por contribuyente extra que excede `maxRfcs` del
 * plan. Solo aplica a business_control y business_cloud (Enterprise).
 * Mi Empresa tiene límite duro de 1 RFC; no permite extras.
 */
export const DESPACHO_OVERAGE_PRICE_MENSUAL = 45;

/** True si el plan cobra distinto en el primer año vs renovaciones (anual). */
export function despachoPlanTieneDualidad(plan: DespachoPaidPlan): boolean {
  const p = DESPACHO_PLAN_PRICES[plan];
  return p.firstYear !== p.renewal;
}

export function getDespachoPlanLimits(plan: DespachoPlan) {
  return DESPACHO_PLANS[plan];
}

export function hasDespachoFeature(plan: DespachoPlan, feature: string): boolean {
  return (DESPACHO_PLANS[plan]?.features as readonly string[])?.includes(feature) ?? false;
}

/**
 * DEPRECATED: Todos los tenants son despachos. Esta función se mantiene
 * por compatibilidad con código existente pero siempre devuelve true.
 */
export function isDespachoTenant(_tenantRfc: string | null | undefined): boolean {
  return true;
}

/** True si el plan es uno pagable de despacho con precio fijo en catálogo
 * (excluye trial y custom). Custom se cobra por monto variable definido al
 * provisionar — usar `isCustomPlan` + chequeo de `Subscription.amount > 0`. */
export function isDespachoPaidPlan(plan: string): plan is DespachoPaidPlan {
  return plan === 'business_control' || plan === 'business_cloud'
      || plan === 'mi_empresa' || plan === 'mi_empresa_plus';
}

/** True si el plan es Custom (monto variable, definido al provisionar). */
export function isCustomPlan(plan: string): boolean {
  return plan === 'custom';
}

/** Planes que permiten cobrar overage por contribuyente extra. */
export function permiteOverage(plan: string): boolean {
  return plan === 'business_control' || plan === 'business_cloud';
}
