/**
 * @ai-summary Business logic for user onboarding workflow
 * @ai-context Coordinates user preferences and profile updates during onboarding
 */

import { UserPreferencesRepository } from '../../../core/user-preferences/data/user-preferences.repository';
import { UserProfileRepository } from '../../user-profile/data/user-profile.repository';
import { logger } from '../../../core/logging/logger';
import {
  OnboardingPreferences,
  OnboardingStatus,
  SavePreferencesRequest,
} from './onboarding.types';

export class OnboardingService {
  constructor(
    private userPreferencesRepo: UserPreferencesRepository,
    private userProfileRepo: UserProfileRepository
  ) {}

  /**
   * Save user preferences during onboarding
   */
  async savePreferences(
    auth0Sub: string,
    request: SavePreferencesRequest
  ): Promise<OnboardingPreferences> {
    try {
      // Validate required fields (should be guaranteed by Zod validation)
      if (!request.unitSystem || !request.currencyCode || !request.timeZone) {
        throw new Error('Missing required fields: unitSystem, currencyCode, timeZone');
      }

      logger.info('Saving onboarding preferences', {
        userId: auth0Sub.substring(0, 8) + '...',
        unitSystem: request.unitSystem,
        currencyCode: request.currencyCode,
        timeZone: request.timeZone,
      });

      // Get user profile to get internal user ID
      const profile = await this.userProfileRepo.getByAuth0Sub(auth0Sub);
      if (!profile) {
        throw new Error('User profile not found');
      }

      // Check if preferences already exist
      const existingPrefs = await this.userPreferencesRepo.findByUserId(profile.id);

      let savedPrefs;
      if (existingPrefs) {
        // Update existing preferences
        savedPrefs = await this.userPreferencesRepo.update(profile.id, {
          unitSystem: request.unitSystem,
          currencyCode: request.currencyCode,
          timeZone: request.timeZone,
        });
      } else {
        // Create new preferences
        savedPrefs = await this.userPreferencesRepo.create({
          userId: profile.id,
          unitSystem: request.unitSystem,
          currencyCode: request.currencyCode,
          timeZone: request.timeZone,
        });
      }

      if (!savedPrefs) {
        throw new Error('Failed to save user preferences');
      }

      logger.info('Onboarding preferences saved successfully', {
        userId: auth0Sub.substring(0, 8) + '...',
        preferencesId: savedPrefs.id,
      });

      return {
        unitSystem: savedPrefs.unitSystem,
        currencyCode: savedPrefs.currencyCode,
        timeZone: savedPrefs.timeZone,
      };
    } catch (error) {
      logger.error('Error saving onboarding preferences', {
        error,
        userId: auth0Sub.substring(0, 8) + '...',
      });
      throw error;
    }
  }

  /**
   * Mark onboarding as complete
   */
  async completeOnboarding(auth0Sub: string): Promise<Date> {
    try {
      logger.info('Completing onboarding', {
        userId: auth0Sub.substring(0, 8) + '...',
      });

      const profile = await this.userProfileRepo.markOnboardingComplete(auth0Sub);

      logger.info('Onboarding completed successfully', {
        userId: auth0Sub.substring(0, 8) + '...',
        completedAt: profile.onboardingCompletedAt,
      });

      return profile.onboardingCompletedAt!;
    } catch (error) {
      logger.error('Error completing onboarding', {
        error,
        userId: auth0Sub.substring(0, 8) + '...',
      });
      throw error;
    }
  }

  /**
   * Get current onboarding status
   */
  async getOnboardingStatus(auth0Sub: string): Promise<OnboardingStatus> {
    try {
      logger.info('Getting onboarding status', {
        userId: auth0Sub.substring(0, 8) + '...',
      });

      // Get user profile
      const profile = await this.userProfileRepo.getByAuth0Sub(auth0Sub);
      if (!profile) {
        throw new Error('User profile not found');
      }

      // Check if preferences exist
      const preferences = await this.userPreferencesRepo.findByUserId(profile.id);

      const status: OnboardingStatus = {
        preferencesSet: !!preferences,
        onboardingCompleted: !!profile.onboardingCompletedAt,
        onboardingCompletedAt: profile.onboardingCompletedAt,
      };

      logger.info('Retrieved onboarding status', {
        userId: auth0Sub.substring(0, 8) + '...',
        status,
      });

      return status;
    } catch (error) {
      logger.error('Error getting onboarding status', {
        error,
        userId: auth0Sub.substring(0, 8) + '...',
      });
      throw error;
    }
  }
}
