/**
 * @ai-summary Fastify route handlers for user preferences API
 * @ai-context HTTP request/response handling for unit system and currency preferences
 */

import { FastifyRequest, FastifyReply } from 'fastify';
import { UserPreferencesRepository } from '../../../core/user-preferences/data/user-preferences.repository';
import { UpdateUserPreferencesRequest } from '../../../core/user-preferences/user-preferences.types';
import { pool } from '../../../core/config/database';
import { logger } from '../../../core/logging/logger';

export class UserPreferencesController {
  private repository: UserPreferencesRepository;

  constructor() {
    this.repository = new UserPreferencesRepository(pool);
  }

  async getPreferences(request: FastifyRequest, reply: FastifyReply) {
    try {
      const userId = (request as any).user.sub;
      let preferences = await this.repository.findByUserId(userId);

      // Create default preferences if none exist
      if (!preferences) {
        preferences = await this.repository.create({
          userId,
          unitSystem: 'imperial',
          currencyCode: 'USD',
          timeZone: 'UTC',
        });
      }

      return reply.code(200).send({
        id: preferences.id,
        userId: preferences.userId,
        unitSystem: preferences.unitSystem,
        currencyCode: preferences.currencyCode,
        timeZone: preferences.timeZone,
        darkMode: preferences.darkMode,
        createdAt: preferences.createdAt,
        updatedAt: preferences.updatedAt,
      });
    } catch (error) {
      logger.error('Error getting user preferences', { error, userId: (request as any).user?.sub });
      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Failed to get preferences',
      });
    }
  }

  async updatePreferences(
    request: FastifyRequest<{ Body: UpdateUserPreferencesRequest }>,
    reply: FastifyReply
  ) {
    try {
      const userId = (request as any).user.sub;
      const { unitSystem, currencyCode, timeZone, darkMode } = request.body;

      // Validate unitSystem if provided
      if (unitSystem && !['imperial', 'metric'].includes(unitSystem)) {
        return reply.code(400).send({
          error: 'Bad Request',
          message: 'unitSystem must be either "imperial" or "metric"',
        });
      }

      // Validate currencyCode if provided (basic 3-letter check)
      if (currencyCode && !/^[A-Z]{3}$/.test(currencyCode)) {
        return reply.code(400).send({
          error: 'Bad Request',
          message: 'currencyCode must be a 3-letter ISO currency code',
        });
      }

      // Validate darkMode if provided (must be boolean or null)
      if (darkMode !== undefined && darkMode !== null && typeof darkMode !== 'boolean') {
        return reply.code(400).send({
          error: 'Bad Request',
          message: 'darkMode must be a boolean or null',
        });
      }

      // Check if preferences exist, create if not
      let preferences = await this.repository.findByUserId(userId);
      if (!preferences) {
        preferences = await this.repository.create({
          userId,
          unitSystem: unitSystem || 'imperial',
          currencyCode: currencyCode || 'USD',
          timeZone: timeZone || 'UTC',
          darkMode: darkMode,
        });
      } else {
        const updated = await this.repository.update(userId, {
          unitSystem,
          currencyCode,
          timeZone,
          darkMode,
        });
        if (updated) {
          preferences = updated;
        }
      }

      return reply.code(200).send({
        id: preferences.id,
        userId: preferences.userId,
        unitSystem: preferences.unitSystem,
        currencyCode: preferences.currencyCode,
        timeZone: preferences.timeZone,
        darkMode: preferences.darkMode,
        createdAt: preferences.createdAt,
        updatedAt: preferences.updatedAt,
      });
    } catch (error) {
      logger.error('Error updating user preferences', { error, userId: (request as any).user?.sub });
      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Failed to update preferences',
      });
    }
  }
}
