import pool from '../config/database';
import { DocumentVersion, CreateDocumentVersionInput } from './types';
import logger from '../utils/logger';

export class DocumentVersionModel {
  /**
   * Create new document version
   */
  static async create(versionData: CreateDocumentVersionInput): Promise<DocumentVersion> {
    const { document_id, version_number, summary_markdown, summary_pdf_path, feedback } = versionData;
    
    const query = `
      INSERT INTO document_versions (document_id, version_number, summary_markdown, summary_pdf_path, feedback)
      VALUES ($1, $2, $3, $4, $5)
      RETURNING *
    `;
    
    try {
      const result = await pool.query(query, [document_id, version_number, summary_markdown, summary_pdf_path, feedback]);
      logger.info(`Created version ${version_number} for document: ${document_id}`);
      return result.rows[0];
    } catch (error) {
      logger.error('Error creating document version:', error);
      throw error;
    }
  }

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

  /**
   * Get versions by document ID
   */
  static async findByDocumentId(documentId: string): Promise<DocumentVersion[]> {
    const query = `
      SELECT * FROM document_versions 
      WHERE document_id = $1 
      ORDER BY version_number DESC
    `;
    
    try {
      const result = await pool.query(query, [documentId]);
      return result.rows;
    } catch (error) {
      logger.error('Error finding versions by document ID:', error);
      throw error;
    }
  }

  /**
   * Get latest version by document ID
   */
  static async findLatestByDocumentId(documentId: string): Promise<DocumentVersion | null> {
    const query = `
      SELECT * FROM document_versions 
      WHERE document_id = $1 
      ORDER BY version_number DESC 
      LIMIT 1
    `;
    
    try {
      const result = await pool.query(query, [documentId]);
      return result.rows[0] || null;
    } catch (error) {
      logger.error('Error finding latest version by document ID:', error);
      throw error;
    }
  }

  /**
   * Get specific version by document ID and version number
   */
  static async findByDocumentIdAndVersion(documentId: string, versionNumber: number): Promise<DocumentVersion | null> {
    const query = `
      SELECT * FROM document_versions 
      WHERE document_id = $1 AND version_number = $2
    `;
    
    try {
      const result = await pool.query(query, [documentId, versionNumber]);
      return result.rows[0] || null;
    } catch (error) {
      logger.error('Error finding version by document ID and version number:', error);
      throw error;
    }
  }

  /**
   * Get next version number for a document
   */
  static async getNextVersionNumber(documentId: string): Promise<number> {
    const query = `
      SELECT COALESCE(MAX(version_number), 0) + 1 as next_version
      FROM document_versions 
      WHERE document_id = $1
    `;
    
    try {
      const result = await pool.query(query, [documentId]);
      return parseInt(result.rows[0].next_version);
    } catch (error) {
      logger.error('Error getting next version number:', error);
      throw error;
    }
  }

  /**
   * Update version
   */
  static async update(id: string, updates: Partial<DocumentVersion>): Promise<DocumentVersion | null> {
    const allowedFields = ['summary_markdown', 'summary_pdf_path', 'feedback'];
    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_versions 
      SET ${updateFields.join(', ')}
      WHERE id = $${paramCount}
      RETURNING *
    `;

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

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

  /**
   * Delete all versions for a document
   */
  static async deleteByDocumentId(documentId: string): Promise<number> {
    const query = 'DELETE FROM document_versions WHERE document_id = $1 RETURNING id';
    
    try {
      const result = await pool.query(query, [documentId]);
      const deletedCount = result.rows.length;
      if (deletedCount > 0) {
        logger.info(`Deleted ${deletedCount} versions for document: ${documentId}`);
      }
      return deletedCount;
    } catch (error) {
      logger.error('Error deleting versions by document ID:', error);
      throw error;
    }
  }

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

  /**
   * Get version history with document info
   */
  static async getVersionHistory(documentId: string): Promise<(DocumentVersion & { original_file_name: string })[]> {
    const query = `
      SELECT dv.*, d.original_file_name
      FROM document_versions dv
      JOIN documents d ON dv.document_id = d.id
      WHERE dv.document_id = $1
      ORDER BY dv.version_number DESC
    `;
    
    try {
      const result = await pool.query(query, [documentId]);
      return result.rows;
    } catch (error) {
      logger.error('Error getting version history:', error);
      throw error;
    }
  }
} 