import { UserModel } from '../UserModel';
import { DocumentModel } from '../DocumentModel';
import { DocumentFeedbackModel } from '../DocumentFeedbackModel';
import { DocumentVersionModel } from '../DocumentVersionModel';
import { ProcessingJobModel } from '../ProcessingJobModel';

// Mock the database pool
jest.mock('../../config/database', () => ({
  query: jest.fn()
}));

// Mock the logger
jest.mock('../../utils/logger', () => ({
  info: jest.fn(),
  error: jest.fn(),
  warn: jest.fn()
}));

describe('Database Models Integration', () => {
  let mockPool: any;

  beforeEach(() => {
    jest.clearAllMocks();
    mockPool = require('../../config/database');
  });

  describe('User and Document Relationship', () => {
    it('should handle user-document relationship correctly', async () => {
      const mockUser = {
        id: '123e4567-e89b-12d3-a456-426614174000',
        email: 'test@example.com',
        name: 'Test User',
        password_hash: 'hashed_password',
        role: 'user',
        created_at: new Date(),
        updated_at: new Date(),
        is_active: true
      };

      const mockDocument = {
        id: '123e4567-e89b-12d3-a456-426614174001',
        user_id: mockUser.id,
        original_file_name: 'test.pdf',
        file_path: '/uploads/test.pdf',
        file_size: 1024000,
        uploaded_at: new Date(),
        status: 'uploaded',
        created_at: new Date(),
        updated_at: new Date()
      };

      // Mock user creation
      mockPool.query.mockResolvedValueOnce({ rows: [mockUser] });
      
      // Mock document creation
      mockPool.query.mockResolvedValueOnce({ rows: [mockDocument] });
      
      // Mock finding documents by user
      mockPool.query.mockResolvedValueOnce({ rows: [mockDocument] });

      // Test the workflow
      const user = await UserModel.create({
        email: 'test@example.com',
        name: 'Test User',
        password: 'password123'
      });

      const document = await DocumentModel.create({
        user_id: user.id,
        original_file_name: 'test.pdf',
        file_path: '/uploads/test.pdf',
        file_size: 1024000
      });

      const userDocuments = await DocumentModel.findByUserId(user.id);

      expect(user.id).toBe(mockUser.id);
      expect(document.user_id).toBe(user.id);
      expect(userDocuments).toHaveLength(1);
      expect(userDocuments[0]?.id).toBe(document.id);
    });
  });

  describe('Document Processing Workflow', () => {
    it('should handle complete document processing workflow', async () => {
      const mockUser = {
        id: '123e4567-e89b-12d3-a456-426614174000',
        email: 'test@example.com',
        name: 'Test User',
        password_hash: 'hashed_password',
        role: 'user',
        created_at: new Date(),
        updated_at: new Date(),
        is_active: true
      };

      const mockDocument = {
        id: '123e4567-e89b-12d3-a456-426614174001',
        user_id: mockUser.id,
        original_file_name: 'test.pdf',
        file_path: '/uploads/test.pdf',
        file_size: 1024000,
        uploaded_at: new Date(),
        status: 'uploaded',
        created_at: new Date(),
        updated_at: new Date()
      };

      const mockProcessingJob = {
        id: '123e4567-e89b-12d3-a456-426614174002',
        document_id: mockDocument.id,
        type: 'text_extraction',
        status: 'pending',
        progress: 0,
        created_at: new Date()
      };

      // Mock the workflow
      mockPool.query.mockResolvedValueOnce({ rows: [mockUser] }); // Create user
      mockPool.query.mockResolvedValueOnce({ rows: [mockDocument] }); // Create document
      mockPool.query.mockResolvedValueOnce({ rows: [mockProcessingJob] }); // Create job
      mockPool.query.mockResolvedValueOnce({ rows: [{ ...mockDocument, status: 'extracting_text' }] }); // Update status
      mockPool.query.mockResolvedValueOnce({ rows: [{ ...mockDocument, extracted_text: 'Extracted text' }] }); // Update text
      mockPool.query.mockResolvedValueOnce({ rows: [{ ...mockDocument, status: 'completed' }] }); // Complete

      // Execute workflow
      const user = await UserModel.create({
        email: 'test@example.com',
        name: 'Test User',
        password: 'password123'
      });

      const document = await DocumentModel.create({
        user_id: user.id,
        original_file_name: 'test.pdf',
        file_path: '/uploads/test.pdf',
        file_size: 1024000
      });

      const job = await ProcessingJobModel.create({
        document_id: document.id,
        type: 'text_extraction'
      });

      await DocumentModel.updateStatus(document.id, 'extracting_text');
      await DocumentModel.updateExtractedText(document.id, 'Extracted text');
      await DocumentModel.updateStatus(document.id, 'completed');

      expect(job.document_id).toBe(document.id);
      expect(job.type).toBe('text_extraction');
    });
  });

  describe('Document Feedback and Versioning', () => {
    it('should handle feedback and versioning workflow', async () => {
      const mockUser = {
        id: '123e4567-e89b-12d3-a456-426614174000',
        email: 'test@example.com',
        name: 'Test User',
        password_hash: 'hashed_password',
        role: 'user',
        created_at: new Date(),
        updated_at: new Date(),
        is_active: true
      };

      const mockDocument = {
        id: '123e4567-e89b-12d3-a456-426614174001',
        user_id: mockUser.id,
        original_file_name: 'test.pdf',
        file_path: '/uploads/test.pdf',
        file_size: 1024000,
        uploaded_at: new Date(),
        status: 'completed',
        created_at: new Date(),
        updated_at: new Date()
      };

      const mockFeedback = {
        id: '123e4567-e89b-12d3-a456-426614174003',
        document_id: mockDocument.id,
        user_id: mockUser.id,
        feedback: 'Please make the summary more concise',
        regeneration_instructions: 'Focus on key points only',
        created_at: new Date()
      };

      const mockVersion = {
        id: '123e4567-e89b-12d3-a456-426614174004',
        document_id: mockDocument.id,
        version_number: 2,
        summary_markdown: '# Updated Summary\n\nMore concise version',
        summary_pdf_path: '/summaries/test_v2.pdf',
        feedback: 'Please make the summary more concise',
        created_at: new Date()
      };

      // Mock the workflow
      mockPool.query.mockResolvedValueOnce({ rows: [mockUser] }); // Create user
      mockPool.query.mockResolvedValueOnce({ rows: [mockDocument] }); // Create document
      mockPool.query.mockResolvedValueOnce({ rows: [mockFeedback] }); // Create feedback
      mockPool.query.mockResolvedValueOnce({ rows: [mockVersion] }); // Create version

      // Execute workflow
      const user = await UserModel.create({
        email: 'test@example.com',
        name: 'Test User',
        password: 'password123'
      });

      const document = await DocumentModel.create({
        user_id: user.id,
        original_file_name: 'test.pdf',
        file_path: '/uploads/test.pdf',
        file_size: 1024000
      });

      const feedback = await DocumentFeedbackModel.create({
        document_id: document.id,
        user_id: user.id,
        feedback: 'Please make the summary more concise',
        regeneration_instructions: 'Focus on key points only'
      });

      const version = await DocumentVersionModel.create({
        document_id: document.id,
        version_number: 2,
        summary_markdown: '# Updated Summary\n\nMore concise version',
        summary_pdf_path: '/summaries/test_v2.pdf',
        feedback: 'Please make the summary more concise'
      });

      expect(feedback.document_id).toBe(document.id);
      expect(feedback.user_id).toBe(user.id);
      expect(version.document_id).toBe(document.id);
      expect(version.version_number).toBe(2);
    });
  });

  describe('Model Relationships', () => {
    it('should maintain referential integrity', async () => {
      const mockUser = {
        id: '123e4567-e89b-12d3-a456-426614174000',
        email: 'test@example.com',
        name: 'Test User',
        password_hash: 'hashed_password',
        role: 'user',
        created_at: new Date(),
        updated_at: new Date(),
        is_active: true
      };

      const mockDocument = {
        id: '123e4567-e89b-12d3-a456-426614174001',
        user_id: mockUser.id,
        original_file_name: 'test.pdf',
        file_path: '/uploads/test.pdf',
        file_size: 1024000,
        uploaded_at: new Date(),
        status: 'uploaded',
        created_at: new Date(),
        updated_at: new Date()
      };

      // Mock queries
      mockPool.query.mockResolvedValueOnce({ rows: [mockUser] }); // Create user
      mockPool.query.mockResolvedValueOnce({ rows: [mockDocument] }); // Create document
      mockPool.query.mockResolvedValueOnce({ rows: [mockUser] }); // Find user
      mockPool.query.mockResolvedValueOnce({ rows: [mockDocument] }); // Find document

      // Test relationships
      const user = await UserModel.create({
        email: 'test@example.com',
        name: 'Test User',
        password: 'password123'
      });

      const document = await DocumentModel.create({
        user_id: user.id,
        original_file_name: 'test.pdf',
        file_path: '/uploads/test.pdf',
        file_size: 1024000
      });

      const foundUser = await UserModel.findById(user.id);
      const foundDocument = await DocumentModel.findById(document.id);

      expect(foundUser?.id).toBe(user.id);
      expect(foundDocument?.id).toBe(document.id);
      expect(foundDocument?.user_id).toBe(user.id);
    });
  });
}); 