import { pool } from '../db.js';

/**
 * Repository для работы с метаданными файлов пользователей
 */
export const userFileRepository = {
  /**
   * Создать запись о файле
   */
  async create({ userId, s3Key, originalFilename, fileSize, contentType, fileType = 'image', folder = 'images_input', generationUuid = null, generationStepId = null, status = 'uploaded', uploadId = null }) {
    const query = `
      INSERT INTO uno_bff.user_files (user_id, s3_key, original_filename, file_size, content_type, file_type, folder, generation_uuid, generation_step_id, status, upload_id)
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
      RETURNING id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, generation_uuid, generation_step_id, status, upload_id, created_at, updated_at
    `;
    const values = [userId, s3Key, originalFilename, fileSize, contentType, fileType, folder, generationUuid, generationStepId, status, uploadId];

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

  /**
   * Обновить файл
   */
  async update(fileId, updates) {
    const allowedFields = ['status', 'upload_id', 'file_size', 'updated_at'];
    const setClauses = [];
    const values = [fileId];
    let paramIndex = 2;

    for (const [key, value] of Object.entries(updates)) {
      if (allowedFields.includes(key)) {
        setClauses.push(`${key} = $${paramIndex}`);
        values.push(value);
        paramIndex++;
      }
    }

    if (setClauses.length === 0) {
      throw new Error('No valid fields to update');
    }

    const query = `
      UPDATE uno_bff.user_files
      SET ${setClauses.join(', ')}
      WHERE id = $1
      RETURNING id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, status, upload_id, created_at, updated_at
    `;

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

  /**
   * Удалить файл по ID
   */
  async delete(fileId) {
    const query = `
      DELETE FROM uno_bff.user_files
      WHERE id = $1
      RETURNING id
    `;

    const result = await pool.query(query, [fileId]);
    return result.rows[0];
  },

  /**
   * Найти файл по ID и проверить владение
   */
  async findByIdAndOwner(fileId, userId) {
    const query = `
      SELECT id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, created_at
      FROM uno_bff.user_files
      WHERE id = $1 AND user_id = $2
    `;

    const result = await pool.query(query, [fileId, userId]);
    return result.rows[0];
  },

  /**
   * Найти файл по S3 ключу и проверить владение
   */
  async findByKeyAndOwner(s3Key, userId) {
    const query = `
      SELECT id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, created_at
      FROM uno_bff.user_files
      WHERE s3_key = $1 AND user_id = $2
    `;

    const result = await pool.query(query, [s3Key, userId]);
    return result.rows[0];
  },

  /**
   * Получить список файлов пользователя
   */
  async findByUser(userId, options = {}) {
    const {
      fileType = 'image',
      folder = 'images_input',
      limit = 50,
      offset = 0,
      orderBy = 'created_at',
      order = 'DESC',
    } = options;

    const validOrderColumns = ['created_at', 'original_filename', 'file_size'];
    const validOrders = ['ASC', 'DESC'];
    const safeOrderBy = validOrderColumns.includes(orderBy) ? orderBy : 'created_at';
    const safeOrder = validOrders.includes(order?.toUpperCase()) ? order.toUpperCase() : 'DESC';

    const query = `
      SELECT id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, created_at
      FROM uno_bff.user_files
      WHERE user_id = $1
        AND ($2::VARCHAR IS NULL OR file_type = $2)
        AND ($3::VARCHAR IS NULL OR folder = $3)
      ORDER BY ${safeOrderBy} ${safeOrder}
      LIMIT $4 OFFSET $5
    `;

    const values = [
      userId,
      fileType || null,
      folder || null,
      limit,
      offset,
    ];

    const result = await pool.query(query, values);
    return result.rows;
  },

  /**
   * Получить общее количество файлов пользователя
   */
  async countByUser(userId, options = {}) {
    const { fileType = 'image', folder = 'images_input' } = options;

    const query = `
      SELECT COUNT(*) as total
      FROM uno_bff.user_files
      WHERE user_id = $1
        AND ($2::VARCHAR IS NULL OR file_type = $2)
        AND ($3::VARCHAR IS NULL OR folder = $3)
    `;

    const values = [userId, fileType || null, folder || null];
    const result = await pool.query(query, values);
    return parseInt(result.rows[0].total, 10);
  },

  /**
   * Удалить запись о файле (по ID и владельцу)
   */
  async deleteByIdAndOwner(fileId, userId) {
    const query = `
      DELETE FROM uno_bff.user_files
      WHERE id = $1 AND user_id = $2
      RETURNING s3_key
    `;

    const result = await pool.query(query, [fileId, userId]);
    return result.rows[0];
  },

  /**
   * Удалить запись о файле по S3 ключу
   */
  async deleteByKeyAndOwner(s3Key, userId) {
    const query = `
      DELETE FROM uno_bff.user_files
      WHERE s3_key = $1 AND user_id = $2
      RETURNING s3_key
    `;

    const result = await pool.query(query, [s3Key, userId]);
    return result.rows[0];
  },

  /**
   * Получить файлы генерации
   */
  async findByGeneration(generationUuid, userId) {
    const query = `
      SELECT id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, generation_uuid, generation_step_id, created_at
      FROM uno_bff.user_files
      WHERE generation_uuid = $1 AND user_id = $2
      ORDER BY created_at ASC
    `;

    const result = await pool.query(query, [generationUuid, userId]);
    return result.rows;
  },

  /**
   * Получить файлы шага генерации
   */
  async findByGenerationStep(generationUuid, stepId, userId) {
    const query = `
      SELECT f.id, f.user_id, f.s3_key, f.original_filename, f.file_size, f.content_type, f.file_type, f.folder, f.generation_uuid, f.generation_step_id, f.created_at
      FROM uno_bff.user_files f
      INNER JOIN uno_bff.generation_steps gs ON f.generation_step_id = gs.id
      WHERE f.generation_uuid = $1 AND gs.step_id = $2 AND f.user_id = $3
      ORDER BY f.created_at ASC
    `;

    const result = await pool.query(query, [generationUuid, stepId, userId]);
    return result.rows;
  },
};
