/**
 * Feature Flag Management System
 * Centralized feature flag handling with type safety and runtime updates
 */

import type { z } from 'zod';

/**
 * Type for feature flag values
 */
export type FeatureFlagValue = boolean | string | number;

/**
 * Interface for a feature flag definition
 */
export interface FeatureFlag<T = FeatureFlagValue> {
  key: string;
  defaultValue: T;
  description?: string;
  allowedValues?: T[]; // For enum-like flags
  category?: string;
}

/**
 * Feature flag registry - stores all defined flags
 */
export interface FeatureFlagRegistry {
  [key: string]: FeatureFlag;
}

/**
 * Feature flag resolver - handles flag resolution logic
 */
export class FeatureFlagResolver {
  private flags: FeatureFlagRegistry;
  private resolvedCache: Map<string, FeatureFlagValue> = new Map();

  constructor(flags: FeatureFlagRegistry) {
    this.flags = flags;
  }

  /**
   * Resolve a feature flag value
   * Priority: Environment > Cache > Default
   */
  resolve<T>(key: string, defaultValue: T): T {
    // Check cache first
    if (this.resolvedCache.has(key)) {
      return this.resolvedCache.get(key)! as T;
    }

    // Check environment variable (allows runtime updates)
    const envValue = process.env[`FLAG_${key.toUpperCase()}`];
    if (envValue !== undefined) {
      // Try to parse as JSON first, then as boolean, then as string
      let parsed: FeatureFlagValue;
      try {
        parsed = JSON.parse(envValue);
      } catch {
        parsed = envValue.toLowerCase() === 'true' ? true : 
                   envValue.toLowerCase() === 'false' ? false : 
                   envValue;
      }

      // Validate against allowed values if defined
      const flag = this.flags[key];
      if (flag && flag.allowedValues && !flag.allowedValues.includes(parsed)) {
        console.warn(`Invalid value for flag ${key}: ${parsed}. Using default.`);
        parsed = defaultValue as FeatureFlagValue;
      }

      this.resolvedCache.set(key, parsed);
      return parsed as T;
    }

    // Use cached value if available
    if (this.resolvedCache.has(key)) {
      return this.resolvedCache.get(key)! as T;
    }

    // Return default
    this.resolvedCache.set(key, defaultValue as FeatureFlagValue);
    return defaultValue as T;
  }

  /**
   * Check if a flag is enabled (boolean check)
   */
  isEnabled<T>(key: string, defaultValue: T): T {
    return this.resolve(key, defaultValue) as T;
  }

  /**
   * Get flag definition
   */
  getDefinition(key: string): FeatureFlag | undefined {
    return this.flags[key];
  }

  /**
   * List all registered flags
   */
  getAllFlags(): FeatureFlagRegistry {
    return { ...this.flags };
  }

  /**
   * Clear the resolution cache (useful for testing)
   */
  clearCache(): void {
    this.resolvedCache.clear();
  }
}

/**
 * Feature flag configuration with pre-defined flags
 */
export const featureFlags: FeatureFlagRegistry = {
  // SpamShield Feature Flags
  'spamshield.enable.number.reputation': {
    key: 'spamshield_enable_number_reputation',
    defaultValue: true,
    description: 'Enable number reputation checking (Hiya API integration)',
    category: 'spamshield',
  },
  'spamshield.enable.content.classification': {
    key: 'spamshield_enable_content_classification',
    defaultValue: true,
    description: 'Enable SMS content classification (BERT model)',
    category: 'spamshield',
  },
  'spamshield.enable.behavioral.analysis': {
    key: 'spamshield_enable_behavioral_analysis',
    defaultValue: true,
    description: 'Enable call behavioral analysis',
    category: 'spamshield',
  },
  'spamshield.enable.community.intelligence': {
    key: 'spamshield_enable_community_intelligence',
    defaultValue: true,
    description: 'Enable community intelligence sharing',
    category: 'spamshield',
  },
  'spamshield.enable.real.time.blocking': {
    key: 'spamshield_enable_real_time_blocking',
    defaultValue: true,
    description: 'Enable real-time spam blocking',
    category: 'spamshield',
  },
  'spamshield.enable.multiple.sources': {
    key: 'spamshield_enable_multiple_sources',
    defaultValue: false,
    description: 'Enable multiple reputation source aggregation (Truecaller, etc.)',
    category: 'spamshield',
  },
  'spamshield.enable.ml.classifier': {
    key: 'spamshield_enable_ml_classifier',
    defaultValue: false,
    description: 'Enable ML-based spam classification',
    category: 'spamshield',
  },

  // VoicePrint Feature Flags
  'voiceprint.enable.ml.service': {
    key: 'voiceprint_enable_ml_service',
    defaultValue: false,
    description: 'Enable ML service integration for voice analysis',
    category: 'voiceprint',
  },
  'voiceprint.enable.faiss.index': {
    key: 'voiceprint_enable_faiss_index',
    defaultValue: true,
    description: 'Enable FAISS index for voice matching',
    category: 'voiceprint',
  },
  'voiceprint.enable.batch.analysis': {
    key: 'voiceprint_enable_batch_analysis',
    defaultValue: true,
    description: 'Enable batch voice analysis',
    category: 'voiceprint',
  },
  'voiceprint.enable.realtime.analysis': {
    key: 'voiceprint_enable_realtime_analysis',
    defaultValue: false,
    description: 'Enable real-time voice analysis',
    category: 'voiceprint',
  },
  'voiceprint.enable.mock.model': {
    key: 'voiceprint_enable_mock_model',
    defaultValue: true,
    description: 'Enable mock model for development',
    category: 'voiceprint',
  },

  // General Platform Flags
  'platform.enable.audit.logs': {
    key: 'platform_enable_audit_logs',
    defaultValue: true,
    description: 'Enable comprehensive audit logging',
    category: 'platform',
  },
  'platform.enable.kpi.tracking': {
    key: 'platform_enable_kpi_tracking',
    defaultValue: true,
    description: 'Enable KPI snapshot tracking',
    category: 'platform',
  },
};

/**
 * Create a resolver instance with the default flags
 */
export const featureFlagResolver = new FeatureFlagResolver(featureFlags);

/**
 * Convenience function for quick flag checks
 */
export function isFeatureEnabled<T>(key: string, defaultValue: T): T {
  return featureFlagResolver.isEnabled(key, defaultValue);
}

/**
 * Check if a flag is enabled with type safety
 */
export function checkFlag<T>(key: string, defaultValue: T): T {
  return featureFlagResolver.resolve(key, defaultValue);
}
