/**
 * @ai-summary Database operations for user preferences
 * @ai-context Repository pattern for user preference CRUD operations
 */

import { Pool } from 'pg';
import { UserPreferences, CreateUserPreferencesRequest, UpdateUserPreferencesRequest } from '../user-preferences.types';

export class UserPreferencesRepository {
  constructor(private db: Pool) {}

  async findByUserId(userId: string): Promise<UserPreferences | null> {
    const query = `
      SELECT id, user_id, unit_system, currency_code, time_zone, dark_mode, created_at, updated_at
      FROM user_preferences
      WHERE user_id = $1
    `;
    
    const result = await this.db.query(query, [userId]);
    return result.rows.length > 0 ? this.mapRow(result.rows[0]) : null;
  }

  async create(data: CreateUserPreferencesRequest): Promise<UserPreferences> {
    const query = `
      INSERT INTO user_preferences (user_id, unit_system, currency_code, time_zone, dark_mode)
      VALUES ($1, $2, $3, $4, $5)
      RETURNING *
    `;

    const values = [
      data.userId,
      data.unitSystem || 'imperial',
      data.currencyCode || 'USD',
      data.timeZone || 'UTC',
      data.darkMode ?? false
    ];

    const result = await this.db.query(query, values);
    return this.mapRow(result.rows[0]);
  }

  async update(userId: string, data: UpdateUserPreferencesRequest): Promise<UserPreferences | null> {
    const fields = [];
    const values = [];
    let paramCount = 1;

    if (data.unitSystem !== undefined) {
      fields.push(`unit_system = $${paramCount++}`);
      values.push(data.unitSystem);
    }
    if (data.currencyCode !== undefined) {
      fields.push(`currency_code = $${paramCount++}`);
      values.push(data.currencyCode);
    }
    if (data.timeZone !== undefined) {
      fields.push(`time_zone = $${paramCount++}`);
      values.push(data.timeZone);
    }
    if (data.darkMode !== undefined) {
      fields.push(`dark_mode = $${paramCount++}`);
      values.push(data.darkMode);
    }

    if (fields.length === 0) {
      return this.findByUserId(userId);
    }

    const query = `
      UPDATE user_preferences
      SET ${fields.join(', ')}, updated_at = CURRENT_TIMESTAMP
      WHERE user_id = $${paramCount}
      RETURNING *
    `;

    values.push(userId);
    const result = await this.db.query(query, values);
    return result.rows.length > 0 ? this.mapRow(result.rows[0]) : null;
  }

  async upsert(data: CreateUserPreferencesRequest): Promise<UserPreferences> {
    const existing = await this.findByUserId(data.userId);
    
    if (existing) {
      const updated = await this.update(data.userId, { unitSystem: data.unitSystem });
      return updated!;
    }
    
    return this.create(data);
  }

  private mapRow(row: any): UserPreferences {
    return {
      id: row.id,
      userId: row.user_id,
      unitSystem: row.unit_system,
      currencyCode: row.currency_code || 'USD',
      timeZone: row.time_zone || 'UTC',
      darkMode: row.dark_mode,
      createdAt: row.created_at,
      updatedAt: row.updated_at,
    };
  }
}
