import { Injectable, Logger, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '../../database/entities/user.entity';

export interface NotificationPreferences {
  pushEnabled?: boolean;
  emailEnabled?: boolean;
  feedingReminders?: boolean;
  sleepReminders?: boolean;
  diaperReminders?: boolean;
  medicationReminders?: boolean;
  milestoneAlerts?: boolean;
  patternAnomalies?: boolean;
}

export interface UserPreferences {
  notifications?: NotificationPreferences;
  emailUpdates?: boolean;
  darkMode?: boolean;
  measurementUnit?: 'metric' | 'imperial';
  timeFormat?: '12h' | '24h';
}

@Injectable()
export class UserPreferencesService {
  private readonly logger = new Logger('UserPreferencesService');

  constructor(
    @InjectRepository(User)
    private userRepository: Repository<User>,
  ) {}

  /**
   * Get user preferences
   */
  async getUserPreferences(userId: string): Promise<UserPreferences> {
    const user = await this.userRepository.findOne({
      where: { id: userId },
      select: ['id', 'preferences'],
    });

    if (!user) {
      throw new NotFoundException('User not found');
    }

    // Return preferences with defaults
    return {
      notifications: {
        pushEnabled: user.preferences?.notifications?.pushEnabled ?? true,
        emailEnabled: user.preferences?.notifications?.emailEnabled ?? true,
        feedingReminders:
          user.preferences?.notifications?.feedingReminders ?? true,
        sleepReminders: user.preferences?.notifications?.sleepReminders ?? true,
        diaperReminders:
          user.preferences?.notifications?.diaperReminders ?? true,
        medicationReminders:
          user.preferences?.notifications?.medicationReminders ?? true,
        milestoneAlerts:
          user.preferences?.notifications?.milestoneAlerts ?? true,
        patternAnomalies:
          user.preferences?.notifications?.patternAnomalies ?? true,
      },
      emailUpdates: user.preferences?.emailUpdates ?? true,
      darkMode: user.preferences?.darkMode ?? false,
      measurementUnit: user.preferences?.measurementUnit ?? 'metric',
      timeFormat: user.preferences?.timeFormat ?? '12h',
    };
  }

  /**
   * Update user preferences
   */
  async updateUserPreferences(
    userId: string,
    preferences: Partial<UserPreferences>,
  ): Promise<UserPreferences> {
    const user = await this.userRepository.findOne({
      where: { id: userId },
    });

    if (!user) {
      throw new NotFoundException('User not found');
    }

    // Merge with existing preferences
    const currentPreferences = user.preferences || {};
    const updatedPreferences = {
      ...currentPreferences,
      ...preferences,
      notifications: {
        ...currentPreferences.notifications,
        ...preferences.notifications,
      },
    };

    // Update user
    await this.userRepository.update(userId, {
      preferences: updatedPreferences as any,
    });

    this.logger.log(`Updated preferences for user ${userId}`);

    return this.getUserPreferences(userId);
  }

  /**
   * Update notification preferences specifically
   */
  async updateNotificationPreferences(
    userId: string,
    notificationPreferences: Partial<NotificationPreferences>,
  ): Promise<UserPreferences> {
    return this.updateUserPreferences(userId, {
      notifications: notificationPreferences,
    });
  }

  /**
   * Enable push notifications
   */
  async enablePushNotifications(userId: string): Promise<void> {
    await this.updateNotificationPreferences(userId, {
      pushEnabled: true,
    });
    this.logger.log(`Enabled push notifications for user ${userId}`);
  }

  /**
   * Disable push notifications
   */
  async disablePushNotifications(userId: string): Promise<void> {
    await this.updateNotificationPreferences(userId, {
      pushEnabled: false,
    });
    this.logger.log(`Disabled push notifications for user ${userId}`);
  }

  /**
   * Check if user has push notifications enabled
   */
  async isPushNotificationsEnabled(userId: string): Promise<boolean> {
    const preferences = await this.getUserPreferences(userId);
    return preferences.notifications?.pushEnabled ?? true;
  }

  /**
   * Check if specific notification type is enabled for user
   */
  async isNotificationTypeEnabled(
    userId: string,
    notificationType: keyof NotificationPreferences,
  ): Promise<boolean> {
    const preferences = await this.getUserPreferences(userId);

    // If push is disabled globally, return false
    if (!preferences.notifications?.pushEnabled) {
      return false;
    }

    // Check specific type
    return preferences.notifications?.[notificationType] ?? true;
  }

  /**
   * Get notification preferences summary
   */
  async getNotificationPreferencesSummary(userId: string): Promise<{
    enabled: boolean;
    enabledTypes: string[];
    disabledTypes: string[];
  }> {
    const preferences = await this.getUserPreferences(userId);
    const notificationPrefs = preferences.notifications || {};

    const types = [
      'feedingReminders',
      'sleepReminders',
      'diaperReminders',
      'medicationReminders',
      'milestoneAlerts',
      'patternAnomalies',
    ];

    const enabledTypes: string[] = [];
    const disabledTypes: string[] = [];

    types.forEach((type) => {
      if (notificationPrefs[type as keyof NotificationPreferences] !== false) {
        enabledTypes.push(type);
      } else {
        disabledTypes.push(type);
      }
    });

    return {
      enabled: notificationPrefs.pushEnabled ?? true,
      enabledTypes,
      disabledTypes,
    };
  }

  /**
   * Reset preferences to defaults
   */
  async resetToDefaults(userId: string): Promise<UserPreferences> {
    const user = await this.userRepository.findOne({
      where: { id: userId },
    });

    if (!user) {
      throw new NotFoundException('User not found');
    }

    const defaultPreferences: UserPreferences = {
      notifications: {
        pushEnabled: true,
        emailEnabled: true,
        feedingReminders: true,
        sleepReminders: true,
        diaperReminders: true,
        medicationReminders: true,
        milestoneAlerts: true,
        patternAnomalies: true,
      },
      emailUpdates: true,
      darkMode: false,
      measurementUnit: 'metric',
      timeFormat: '12h',
    };

    await this.userRepository.update(userId, {
      preferences: defaultPreferences as any,
    });

    this.logger.log(`Reset preferences to defaults for user ${userId}`);

    return defaultPreferences;
  }
}
