import pool from '../config/database';
import { DocumentFeedback, CreateDocumentFeedbackInput } from './types';
import logger from '../utils/logger';

export class DocumentFeedbackModel {
  /**
   * Create new document feedback
   */
  static async create(feedbackData: CreateDocumentFeedbackInput): Promise<DocumentFeedback> {
    const { document_id, user_id, feedback, regeneration_instructions } = feedbackData;
    
    const query = `
      INSERT INTO document_feedback (document_id, user_id, feedback, regeneration_instructions)
      VALUES ($1, $2, $3, $4)
      RETURNING *
    `;
    
    try {
      const result = await pool.query(query, [document_id, user_id, feedback, regeneration_instructions]);
      logger.info(`Created feedback for document: ${document_id} by user: ${user_id}`);
      return result.rows[0];
    } catch (error) {
      logger.error('Error creating document feedback:', error);
      throw error;
    }
  }

  /**
   * Find feedback by ID
   */
  static async findById(id: string): Promise<DocumentFeedback | null> {
    const query = 'SELECT * FROM document_feedback WHERE id = $1';
    
    try {
      const result = await pool.query(query, [id]);
      return result.rows[0] || null;
    } catch (error) {
      logger.error('Error finding feedback by ID:', error);
      throw error;
    }
  }

  /**
   * Get feedback by document ID
   */
  static async findByDocumentId(documentId: string): Promise<DocumentFeedback[]> {
    const query = `
      SELECT df.*, u.name as user_name, u.email as user_email
      FROM document_feedback df
      JOIN users u ON df.user_id = u.id
      WHERE df.document_id = $1
      ORDER BY df.created_at DESC
    `;
    
    try {
      const result = await pool.query(query, [documentId]);
      return result.rows;
    } catch (error) {
      logger.error('Error finding feedback by document ID:', error);
      throw error;
    }
  }

  /**
   * Get feedback by user ID
   */
  static async findByUserId(userId: string, limit = 50, offset = 0): Promise<DocumentFeedback[]> {
    const query = `
      SELECT df.*, d.original_file_name
      FROM document_feedback df
      JOIN documents d ON df.document_id = d.id
      WHERE df.user_id = $1
      ORDER BY df.created_at DESC
      LIMIT $2 OFFSET $3
    `;
    
    try {
      const result = await pool.query(query, [userId, limit, offset]);
      return result.rows;
    } catch (error) {
      logger.error('Error finding feedback by user ID:', error);
      throw error;
    }
  }

  /**
   * Get all feedback (for admin)
   */
  static async findAll(limit = 100, offset = 0): Promise<(DocumentFeedback & { user_name: string, user_email: string, original_file_name: string })[]> {
    const query = `
      SELECT df.*, u.name as user_name, u.email as user_email, d.original_file_name
      FROM document_feedback df
      JOIN users u ON df.user_id = u.id
      JOIN documents d ON df.document_id = d.id
      ORDER BY df.created_at DESC
      LIMIT $1 OFFSET $2
    `;
    
    try {
      const result = await pool.query(query, [limit, offset]);
      return result.rows;
    } catch (error) {
      logger.error('Error finding all feedback:', error);
      throw error;
    }
  }

  /**
   * Update feedback
   */
  static async update(id: string, updates: Partial<DocumentFeedback>): Promise<DocumentFeedback | null> {
    const allowedFields = ['feedback', 'regeneration_instructions'];
    const updateFields: string[] = [];
    const values: any[] = [];
    let paramCount = 1;

    // Build dynamic update query
    for (const [key, value] of Object.entries(updates)) {
      if (allowedFields.includes(key) && value !== undefined) {
        updateFields.push(`${key} = $${paramCount}`);
        values.push(value);
        paramCount++;
      }
    }

    if (updateFields.length === 0) {
      return this.findById(id);
    }

    values.push(id);
    const query = `
      UPDATE document_feedback 
      SET ${updateFields.join(', ')}
      WHERE id = $${paramCount}
      RETURNING *
    `;

    try {
      const result = await pool.query(query, values);
      logger.info(`Updated feedback: ${id}`);
      return result.rows[0] || null;
    } catch (error) {
      logger.error('Error updating feedback:', error);
      throw error;
    }
  }

  /**
   * Delete feedback
   */
  static async delete(id: string): Promise<boolean> {
    const query = 'DELETE FROM document_feedback WHERE id = $1 RETURNING id';
    
    try {
      const result = await pool.query(query, [id]);
      const deleted = result.rows.length > 0;
      if (deleted) {
        logger.info(`Deleted feedback: ${id}`);
      }
      return deleted;
    } catch (error) {
      logger.error('Error deleting feedback:', error);
      throw error;
    }
  }

  /**
   * Count feedback by document
   */
  static async countByDocument(documentId: string): Promise<number> {
    const query = 'SELECT COUNT(*) FROM document_feedback WHERE document_id = $1';
    
    try {
      const result = await pool.query(query, [documentId]);
      return parseInt(result.rows[0].count);
    } catch (error) {
      logger.error('Error counting feedback by document:', error);
      throw error;
    }
  }

  /**
   * Count total feedback
   */
  static async count(): Promise<number> {
    const query = 'SELECT COUNT(*) FROM document_feedback';
    
    try {
      const result = await pool.query(query);
      return parseInt(result.rows[0].count);
    } catch (error) {
      logger.error('Error counting feedback:', error);
      throw error;
    }
  }
} 