import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

export enum FeatureFlag {
  // Core features
  AI_ASSISTANT = 'ai_assistant',
  VOICE_INPUT = 'voice_input',
  PATTERN_RECOGNITION = 'pattern_recognition',
  PREDICTIONS = 'predictions',

  // Premium features
  ADVANCED_ANALYTICS = 'advanced_analytics',
  FAMILY_SHARING = 'family_sharing',
  EXPORT_REPORTS = 'export_reports',
  CUSTOM_MILESTONES = 'custom_milestones',

  // Experimental features
  AI_GPT5 = 'ai_gpt5',
  SLEEP_COACH = 'sleep_coach',
  MEAL_PLANNER = 'meal_planner',
  COMMUNITY_FORUMS = 'community_forums',

  // A/B tests
  NEW_ONBOARDING_FLOW = 'new_onboarding_flow',
  REDESIGNED_DASHBOARD = 'redesigned_dashboard',
  GAMIFICATION = 'gamification',

  // Performance optimizations
  LAZY_LOADING = 'lazy_loading',
  IMAGE_OPTIMIZATION = 'image_optimization',
  CACHING_V2 = 'caching_v2',

  // Mobile-specific
  OFFLINE_MODE = 'offline_mode',
  PUSH_NOTIFICATIONS = 'push_notifications',
  BIOMETRIC_AUTH = 'biometric_auth',
}

export interface FeatureFlagConfig {
  enabled: boolean;
  rolloutPercentage?: number; // 0-100
  allowedUsers?: string[]; // User IDs with explicit access
  allowedFamilies?: string[]; // Family IDs with explicit access
  minAppVersion?: string; // Minimum app version required
  platforms?: ('web' | 'ios' | 'android')[]; // Platform-specific flags
  startDate?: Date; // When to enable
  endDate?: Date; // When to disable
  metadata?: Record<string, any>;
}

@Injectable()
export class FeatureFlagsService {
  private readonly logger = new Logger(FeatureFlagsService.name);
  private flags: Map<FeatureFlag, FeatureFlagConfig> = new Map();

  constructor(private configService: ConfigService) {
    this.initializeFlags();
  }

  /**
   * Initialize feature flags with default configuration
   */
  private initializeFlags(): void {
    // Core features - enabled by default
    this.setFlag(FeatureFlag.AI_ASSISTANT, { enabled: true });
    this.setFlag(FeatureFlag.VOICE_INPUT, { enabled: true });
    this.setFlag(FeatureFlag.PATTERN_RECOGNITION, { enabled: true });
    this.setFlag(FeatureFlag.PREDICTIONS, { enabled: true });

    // Premium features - enabled for premium users only
    this.setFlag(FeatureFlag.ADVANCED_ANALYTICS, {
      enabled: false, // Controlled by subscription
    });
    this.setFlag(FeatureFlag.FAMILY_SHARING, { enabled: true });
    this.setFlag(FeatureFlag.EXPORT_REPORTS, { enabled: false });
    this.setFlag(FeatureFlag.CUSTOM_MILESTONES, { enabled: false });

    // Experimental features - gradual rollout
    this.setFlag(FeatureFlag.AI_GPT5, {
      enabled: true,
      rolloutPercentage: 10, // 10% of users
      metadata: {
        description: 'Testing GPT-5 mini model for AI assistant',
      },
    });

    this.setFlag(FeatureFlag.SLEEP_COACH, {
      enabled: false,
      metadata: {
        description: 'AI-powered sleep coaching feature',
        status: 'development',
      },
    });

    this.setFlag(FeatureFlag.MEAL_PLANNER, {
      enabled: false,
      metadata: {
        description: 'Meal planning and nutrition tracking',
        status: 'planned',
      },
    });

    this.setFlag(FeatureFlag.COMMUNITY_FORUMS, {
      enabled: false,
      metadata: {
        description: 'Parent community and discussion forums',
        status: 'planned',
      },
    });

    // A/B tests
    this.setFlag(FeatureFlag.NEW_ONBOARDING_FLOW, {
      enabled: true,
      rolloutPercentage: 50, // 50/50 split
      metadata: {
        variant: 'A',
        testStartDate: new Date('2025-01-01'),
        testEndDate: new Date('2025-02-01'),
      },
    });

    this.setFlag(FeatureFlag.REDESIGNED_DASHBOARD, {
      enabled: true,
      rolloutPercentage: 25, // 25% gradual rollout
    });

    this.setFlag(FeatureFlag.GAMIFICATION, {
      enabled: false,
      metadata: {
        description: 'Badges, streaks, and achievements',
        status: 'experimental',
      },
    });

    // Performance optimizations
    this.setFlag(FeatureFlag.LAZY_LOADING, {
      enabled: true,
      platforms: ['web', 'ios', 'android'],
    });

    this.setFlag(FeatureFlag.IMAGE_OPTIMIZATION, { enabled: true });
    this.setFlag(FeatureFlag.CACHING_V2, {
      enabled: true,
      rolloutPercentage: 75,
    });

    // Mobile-specific features
    this.setFlag(FeatureFlag.OFFLINE_MODE, {
      enabled: true,
      platforms: ['ios', 'android'],
    });

    this.setFlag(FeatureFlag.PUSH_NOTIFICATIONS, {
      enabled: true,
      platforms: ['ios', 'android'],
    });

    this.setFlag(FeatureFlag.BIOMETRIC_AUTH, {
      enabled: true,
      platforms: ['ios', 'android'],
      minAppVersion: '1.1.0',
    });

    this.logger.log(`Initialized ${this.flags.size} feature flags`);
  }

  /**
   * Set a feature flag configuration
   */
  setFlag(flag: FeatureFlag, config: FeatureFlagConfig): void {
    this.flags.set(flag, config);
  }

  /**
   * Check if a feature is enabled for a specific user
   */
  isEnabled(
    flag: FeatureFlag,
    context?: {
      userId?: string;
      familyId?: string;
      platform?: 'web' | 'ios' | 'android';
      appVersion?: string;
      isPremium?: boolean;
    },
  ): boolean {
    const config = this.flags.get(flag);

    if (!config) {
      this.logger.warn(`Feature flag not found: ${flag}`);
      return false;
    }

    // Check if globally disabled
    if (!config.enabled) {
      return false;
    }

    // Check platform compatibility
    if (
      config.platforms &&
      context?.platform &&
      !config.platforms.includes(context.platform)
    ) {
      return false;
    }

    // Check app version requirement
    if (config.minAppVersion && context?.appVersion) {
      if (
        !this.isVersionGreaterOrEqual(context.appVersion, config.minAppVersion)
      ) {
        return false;
      }
    }

    // Check date range
    const now = new Date();
    if (config.startDate && now < config.startDate) {
      return false;
    }
    if (config.endDate && now > config.endDate) {
      return false;
    }

    // Check explicit user/family allowlist
    if (config.allowedUsers && context?.userId) {
      return config.allowedUsers.includes(context.userId);
    }

    if (config.allowedFamilies && context?.familyId) {
      return config.allowedFamilies.includes(context.familyId);
    }

    // Check premium features
    if (
      [
        FeatureFlag.ADVANCED_ANALYTICS,
        FeatureFlag.EXPORT_REPORTS,
        FeatureFlag.CUSTOM_MILESTONES,
      ].includes(flag)
    ) {
      return context?.isPremium || false;
    }

    // Check rollout percentage
    if (config.rolloutPercentage !== undefined && context?.userId) {
      const userHash = this.hashUserId(context.userId);
      const threshold = (config.rolloutPercentage / 100) * 0xffffffff;
      return userHash <= threshold;
    }

    return config.enabled;
  }

  /**
   * Get all enabled flags for a user
   */
  getEnabledFlags(context?: {
    userId?: string;
    familyId?: string;
    platform?: 'web' | 'ios' | 'android';
    appVersion?: string;
    isPremium?: boolean;
  }): FeatureFlag[] {
    const enabledFlags: FeatureFlag[] = [];

    for (const flag of Object.values(FeatureFlag)) {
      if (this.isEnabled(flag, context)) {
        enabledFlags.push(flag);
      }
    }

    return enabledFlags;
  }

  /**
   * Get flag configuration
   */
  getFlagConfig(flag: FeatureFlag): FeatureFlagConfig | undefined {
    return this.flags.get(flag);
  }

  /**
   * Get all flags with their configurations (admin only)
   */
  getAllFlags(): Array<{ flag: FeatureFlag; config: FeatureFlagConfig }> {
    return Array.from(this.flags.entries()).map(([flag, config]) => ({
      flag,
      config,
    }));
  }

  /**
   * Override flag for testing
   */
  overrideFlag(flag: FeatureFlag, enabled: boolean, userId?: string): void {
    const config = this.flags.get(flag);
    if (!config) {
      this.logger.warn(`Cannot override non-existent flag: ${flag}`);
      return;
    }

    if (userId) {
      // Add user to allowlist
      if (!config.allowedUsers) {
        config.allowedUsers = [];
      }
      if (!config.allowedUsers.includes(userId)) {
        config.allowedUsers.push(userId);
      }
    } else {
      // Global override
      config.enabled = enabled;
    }

    this.logger.debug(
      `Feature flag ${flag} overridden: ${enabled}${userId ? ` for user ${userId}` : ' globally'}`,
    );
  }

  /**
   * Get variant for A/B test
   */
  getVariant(
    flag: FeatureFlag,
    userId: string,
    variants: string[] = ['A', 'B'],
  ): string {
    if (!this.isEnabled(flag, { userId })) {
      return 'control';
    }

    const userHash = this.hashUserId(userId);
    const variantIndex = userHash % variants.length;
    return variants[variantIndex];
  }

  /**
   * Hash user ID for consistent rollout
   */
  private hashUserId(userId: string): number {
    let hash = 0;
    for (let i = 0; i < userId.length; i++) {
      const char = userId.charCodeAt(i);
      hash = (hash << 5) - hash + char;
      hash = hash & hash; // Convert to 32bit integer
    }
    return Math.abs(hash);
  }

  /**
   * Compare semantic versions
   */
  private isVersionGreaterOrEqual(
    version: string,
    minVersion: string,
  ): boolean {
    const v1Parts = version.split('.').map(Number);
    const v2Parts = minVersion.split('.').map(Number);

    for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
      const v1 = v1Parts[i] || 0;
      const v2 = v2Parts[i] || 0;

      if (v1 > v2) return true;
      if (v1 < v2) return false;
    }

    return true; // Equal
  }

  /**
   * Load flags from external source (e.g., LaunchDarkly, ConfigCat)
   */
  async loadFromExternal(provider: string): Promise<void> {
    this.logger.debug(`Loading flags from ${provider} (not implemented)`);
    // Implementation would integrate with external feature flag service
  }
}
