/**
 * Centralized Subscription Tier Configuration
 *
 * This file defines all subscription tiers and their features.
 * To add a new tier:
 * 1. Add the tier name to the SubscriptionTier type
 * 2. Add the tier configuration to SUBSCRIPTION_TIERS
 * 3. Update your Stripe product metadata with tier: "tier_name"
 */

export type SubscriptionTier = 'free' | 'personal' | 'family' | 'professional';

export interface TierFeatures {
  qr_codes: number | 'unlimited';
  scans_per_month: number | 'unlimited';
  analytics: 'basic' | 'advanced' | 'premium';
  custom_branding: boolean;
  document_sharing: boolean;
  hipaa_compliance: boolean;
  priority_support: boolean;
  api_access: boolean;
  team_management?: boolean;
  storage_gb?: number;
}

export interface TierConfig {
  name: string;
  tier: SubscriptionTier;
  description: string;
  features: TierFeatures;
  displayFeatures: string[];
  price?: {
    monthly?: number;
    yearly?: number;
  };
}

/**
 * Subscription Tier Definitions
 * Add new tiers here to automatically support them throughout the system
 */
export const SUBSCRIPTION_TIERS: Record<SubscriptionTier, TierConfig> = {
  free: {
    name: 'Free Plan (Starter Tier)',
    tier: 'free',
    description: 'Perfect for getting started with QuickConnect',
    features: {
      qr_codes: 2,
      scans_per_month: 100,
      analytics: 'basic',
      custom_branding: false,
      document_sharing: false,
      hipaa_compliance: false,
      priority_support: false,
      api_access: false,
      storage_gb: 0.25, // 250MB
    },
    displayFeatures: [
      '2 active QR codes',
      'Basic document uploads (250MB storage)',
      'Standard QuickConnect branding',
      'Limited Memory Tag scans',
    ],
  },
  personal: {
    name: 'Personal Plan',
    tier: 'personal',
    description: 'For individuals who need custom QR pages and memory tags',
    features: {
      qr_codes: 10,
      scans_per_month: 'unlimited',
      analytics: 'basic',
      custom_branding: true,
      document_sharing: true,
      hipaa_compliance: false,
      priority_support: false,
      api_access: false,
      storage_gb: 2,
    },
    displayFeatures: [
      '10 QR codes',
      '2GB encrypted storage',
      'Unlimited Memory Tags (with timestamp & map)',
      'Custom QR page (name, photo, details)',
    ],
    price: {
      monthly: 4.99,
      yearly: 49.0,
    },
  },
  family: {
    name: 'Family Plan',
    tier: 'family',
    description: 'For families who want to share QR codes and memories',
    features: {
      qr_codes: 25,
      scans_per_month: 'unlimited',
      analytics: 'advanced',
      custom_branding: true,
      document_sharing: true,
      hipaa_compliance: false,
      priority_support: false,
      api_access: false,
      storage_gb: 10,
    },
    displayFeatures: [
      '20 QR codes',
      '10GB encrypted storage',
      'Unlimited Memory Tags (with timestamp & map)',
      'Custom QR page (name, photo, details)',
      'Family sharing features',
    ],
    price: {
      monthly: 9.99,
      yearly: 99.0,
    },
  },
  professional: {
    name: 'Professional Plan',
    tier: 'professional',
    description: 'For businesses and professionals with advanced needs',
    features: {
      qr_codes: 50,
      scans_per_month: 'unlimited',
      analytics: 'advanced',
      custom_branding: true,
      document_sharing: true,
      hipaa_compliance: true,
      priority_support: false,
      api_access: true,
      storage_gb: 50,
    },
    displayFeatures: [
      '50 QR codes',
      '50GB encrypted storage',
      'HIPAA compliance toggle (for medical users)',
      'Expiring QR links',
      'Scan analytics',
      'Branded QR pages with logos/colors',
    ],
    price: {
      monthly: 19.99,
      yearly: 29.99,
    },
  },
};

/**
 * Get tier configuration by tier name
 */
export function getTierConfig(tier: SubscriptionTier): TierConfig {
  return SUBSCRIPTION_TIERS[tier] || SUBSCRIPTION_TIERS.free;
}

/**
 * Check if a tier has access to a specific feature
 */
export function hasFeatureAccess(
  tier: SubscriptionTier,
  feature: keyof TierFeatures
): boolean {
  const config = getTierConfig(tier);
  const featureValue = config.features[feature];

  if (typeof featureValue === 'boolean') {
    return featureValue;
  }

  return featureValue !== undefined && featureValue !== 0;
}

/**
 * Get all available tiers
 */
export function getAllTiers(): TierConfig[] {
  return Object.values(SUBSCRIPTION_TIERS);
}

/**
 * Validate if a tier name is valid
 */
export function isValidTier(tier: string): tier is SubscriptionTier {
  return tier in SUBSCRIPTION_TIERS;
}

/**
 * Determine tier from Stripe product
 * Checks metadata first, then falls back to product name matching
 */
export function determineTierFromProduct(
  productMetadata: Record<string, string> | undefined,
  productName: string
): SubscriptionTier {
  // Check metadata first
  if (productMetadata?.tier && isValidTier(productMetadata.tier)) {
    return productMetadata.tier as SubscriptionTier;
  }

  // Fallback to name matching
  const nameLower = productName.toLowerCase();

  if (nameLower.includes('family')) {
    return 'family';
  }

  if (nameLower.includes('professional') || nameLower.includes('pro')) {
    return 'professional';
  }

  if (nameLower.includes('personal') || nameLower.includes('basic')) {
    return 'personal';
  }

  // Default to personal for paid products
  return 'personal';
}

// ========== STORAGE LIMIT MANAGEMENT ===========

/**
 * Storage validation result interface
 */
export interface StorageValidationResult {
  isValid: boolean;
  currentUsageMB: number;
  limitMB: number;
  remainingMB: number;
  isExceeded: boolean;
  tier: SubscriptionTier;
  error?: 'storage_exceeded' | 'invalid_tier' | 'invalid_usage';
}

/**
 * Storage authorization result for CASL integration
 */
export interface StorageAuthorizationResult {
  canUpload: boolean;
  storageStatus: 'available' | 'storage_exceeded' | 'invalid_tier';
  validation: StorageValidationResult;
  errorMessage?: string;
}

/**
 * Get storage limit for a subscription tier in megabytes (MB)
 * @param tier - The subscription tier to check
 * @returns Storage limit in MB, or 0 if tier is invalid or has no storage
 */
export function getStorageLimitMB(tier: SubscriptionTier): number {
  const config = getTierConfig(tier);
  const limitGB = config.features.storage_gb || 0;

  // Convert GB to MB (1 GB = 1024 MB)
  return limitGB * 1024;
}

/**
 * Convert bytes to megabytes
 * @param bytes - Storage size in bytes
 * @returns Storage size in MB (rounded to 2 decimal places)
 */
export function bytesToMB(bytes: number): number {
  if (bytes < 0) {
    return 0;
  }
  // Convert bytes to MB: bytes / (1024 * 1024)
  return Math.round((bytes / (1024 * 1024)) * 100) / 100;
}

/**
 * Convert megabytes to bytes
 * @param mb - Storage size in MB
 * @returns Storage size in bytes
 */
export function mbToBytes(mb: number): number {
  if (mb < 0) {
    return 0;
  }
  // Convert MB to bytes: MB * 1024 * 1024
  return Math.round(mb * 1024 * 1024);
}

/**
 * Validate storage usage against tier limits
 * Handles edge cases: zero/negative values, undefined tiers, exact limit matches, floating-point precision
 * @param tier - Subscription tier to validate against
 * @param currentUsageBytes - Current storage usage in bytes
 * @param additionalUsageBytes - Additional storage to be used (optional, defaults to 0)
 * @returns StorageValidationResult with validation status and details
 */
export function validateStorageUsage(
  tier: SubscriptionTier,
  currentUsageBytes: number,
  additionalUsageBytes: number = 0
): StorageValidationResult {
  // Handle invalid tier
  if (!isValidTier(tier)) {
    return {
      isValid: false,
      currentUsageMB: bytesToMB(currentUsageBytes),
      limitMB: 0,
      remainingMB: 0,
      isExceeded: true,
      tier: 'free', // Default fallback
      error: 'invalid_tier',
    };
  }

  // Handle negative or invalid usage values
  if (currentUsageBytes < 0) {
    currentUsageBytes = 0;
  }
  if (additionalUsageBytes < 0) {
    additionalUsageBytes = 0;
  }

  // Get tier limit in MB
  const limitMB = getStorageLimitMB(tier);
  const limitBytes = mbToBytes(limitMB);

  // Convert current usage to MB (with precision handling)
  const currentUsageMB = bytesToMB(currentUsageBytes);
  const additionalUsageMB = bytesToMB(additionalUsageBytes);
  const totalUsageMB = currentUsageMB + additionalUsageMB;

  // Calculate total usage in bytes for precise comparison
  // Use a small epsilon (0.01 MB = ~10KB) to handle floating-point precision issues
  const epsilonBytes = mbToBytes(0.01);
  const totalUsageBytes = currentUsageBytes + additionalUsageBytes;

  // Check if storage is exceeded (allowing for small floating-point differences)
  // Storage is considered exceeded if total usage exceeds limit by more than epsilon
  const isExceeded = totalUsageBytes > limitBytes + epsilonBytes;

  // Storage is valid if not exceeded (exact limit is allowed)
  const isValid = !isExceeded;

  // Calculate remaining storage
  const remainingBytes = Math.max(0, limitBytes - currentUsageBytes);
  const remainingMB = bytesToMB(remainingBytes);

  return {
    isValid,
    currentUsageMB,
    limitMB,
    remainingMB,
    isExceeded,
    tier,
    error: isExceeded ? 'storage_exceeded' : undefined,
  };
}

/**
 * Get storage authorization for CASL integration
 * Returns authorization result that can be used to block uploads when storage is exceeded
 * @param tier - Subscription tier to check
 * @param currentUsageBytes - Current storage usage in bytes
 * @param uploadSizeBytes - Size of the file to be uploaded in bytes
 * @returns StorageAuthorizationResult with CASL-compatible authorization status
 */
export function getStorageAuthorization(
  tier: SubscriptionTier,
  currentUsageBytes: number,
  uploadSizeBytes: number = 0
): StorageAuthorizationResult {
  // Validate storage usage
  const validation = validateStorageUsage(tier, currentUsageBytes, uploadSizeBytes);

  // Determine if upload is allowed
  const canUpload = validation.isValid && !validation.isExceeded;

  // Determine storage status for CASL
  let storageStatus: 'available' | 'storage_exceeded' | 'invalid_tier';
  let errorMessage: string | undefined;

  if (validation.error === 'invalid_tier') {
    storageStatus = 'invalid_tier';
    errorMessage = `Invalid subscription tier: ${tier}`;
  } else if (validation.isExceeded) {
    storageStatus = 'storage_exceeded';
    const limitGB = (validation.limitMB / 1024).toFixed(2);
    const currentGB = (validation.currentUsageMB / 1024).toFixed(2);
    errorMessage = `Storage limit exceeded. Current usage: ${currentGB} GB / ${limitGB} GB. Please upgrade your subscription or delete some files.`;
  } else {
    storageStatus = 'available';
  }

  return {
    canUpload,
    storageStatus,
    validation,
    errorMessage,
  };
}

/**
 * Check if storage limit is exceeded for a given tier and usage
 * Simplified function for quick checks
 * @param tier - Subscription tier to check
 * @param currentUsageBytes - Current storage usage in bytes
 * @param additionalUsageBytes - Additional storage to be used (optional)
 * @returns true if storage limit is exceeded, false otherwise
 */
export function isStorageExceeded(
  tier: SubscriptionTier,
  currentUsageBytes: number,
  additionalUsageBytes: number = 0
): boolean {
  const validation = validateStorageUsage(tier, currentUsageBytes, additionalUsageBytes);
  return validation.isExceeded;
}
