import { v4 as uuidv4 } from 'uuid';
import bcrypt from 'bcryptjs';
import { UserModel } from './UserModel';
import { DocumentModel } from './DocumentModel';
import { ProcessingJobModel } from './ProcessingJobModel';
import logger from '../utils/logger';
import { config } from '../config/env';
import { getSupabaseServiceClient } from '../config/supabase';

class DatabaseSeeder {
  async seed(): Promise<void> {
    try {
      logger.info('Starting database seeding...');
      
      await this.seedUsers();
      await this.seedDocuments();
      await this.seedProcessingJobs();
      
      logger.info('Database seeding completed successfully');
    } catch (error) {
      logger.error('Database seeding failed:', error);
      throw error;
    }
  }

  private async seedUsers(): Promise<void> {
    const users = [
      {
        email: 'admin@example.com',
        name: 'Admin User',
        password: 'admin123',
        role: 'admin' as const
      },
      {
        email: 'user1@example.com',
        name: 'John Doe',
        password: 'user123',
        role: 'user' as const
      },
      {
        email: 'user2@example.com',
        name: 'Jane Smith',
        password: 'user123',
        role: 'user' as const
      }
    ];

    for (const userData of users) {
      try {
        const existingUser = await UserModel.findByEmail(userData.email);
        
        if (!existingUser) {
          const hashedPassword = await bcrypt.hash(userData.password, config.security.bcryptRounds);
          
          await UserModel.create({
            ...userData,
            password: hashedPassword
          });
          
          logger.info(`Created user: ${userData.email}`);
        } else {
          logger.info(`User already exists: ${userData.email}`);
        }
      } catch (error) {
        logger.error(`Error creating user ${userData.email}:`, error);
      }
    }
  }

  private async seedDocuments(): Promise<void> {
    try {
      const user = await UserModel.findByEmail('user1@example.com');
      
      if (!user) {
        logger.warn('No user found for seeding documents');
        return;
      }

      const documents = [
        {
          user_id: user.id,
          original_file_name: 'sample_cim_1.pdf',
          file_path: '/uploads/sample_cim_1.pdf',
          file_size: 2048576,
          status: 'completed' as const
        },
        {
          user_id: user.id,
          original_file_name: 'sample_cim_2.pdf',
          file_path: '/uploads/sample_cim_2.pdf',
          file_size: 3145728,
          status: 'processing_llm' as const
        },
        {
          user_id: user.id,
          original_file_name: 'sample_cim_3.pdf',
          file_path: '/uploads/sample_cim_3.pdf',
          file_size: 1048576,
          status: 'uploaded' as const
        }
      ];

      for (const docData of documents) {
        try {
          const existingDocs = await DocumentModel.findByUserId(user.id);
          const exists = existingDocs.some(doc => doc.file_path === docData.file_path);
          
          if (!exists) {
            await DocumentModel.create(docData);
            logger.info(`Created document: ${docData.original_file_name}`);
          } else {
            logger.info(`Document already exists: ${docData.original_file_name}`);
          }
        } catch (error) {
          logger.error(`Error creating document ${docData.original_file_name}:`, error);
        }
      }
    } catch (error) {
      logger.error('Error seeding documents:', error);
    }
  }

  private async seedProcessingJobs(): Promise<void> {
    try {
      const user = await UserModel.findByEmail('user1@example.com');
      if (!user) {
        logger.warn('No user found for seeding processing jobs');
        return;
      }

      const documents = await DocumentModel.findByUserId(user.id);
      
      if (documents.length === 0) {
        logger.warn('No documents found for seeding processing jobs');
        return;
      }

      const document = documents[0];

      if (!document) {
        logger.warn('No document found for seeding processing jobs');
        return;
      }

      const jobs = [
        {
          document_id: document.id,
          type: 'text_extraction' as const,
          status: 'completed' as const,
          progress: 100
        },
        {
          document_id: document.id,
          type: 'llm_processing' as const,
          status: 'processing' as const,
          progress: 75
        },
        {
          document_id: document.id,
          type: 'pdf_generation' as const,
          status: 'pending' as const,
          progress: 0
        }
      ];

      for (const jobData of jobs) {
        try {
          const existingJobs = await ProcessingJobModel.findByDocumentId(document.id);
          const exists = existingJobs.some(job => job.type === jobData.type);
          
          if (!exists) {
            const job = await ProcessingJobModel.create({
              document_id: jobData.document_id,
              type: jobData.type
            });
            
            await ProcessingJobModel.updateStatus(job.id, jobData.status);
            await ProcessingJobModel.updateProgress(job.id, jobData.progress);
            
            logger.info(`Created processing job: ${jobData.type}`);
          } else {
            logger.info(`Processing job already exists: ${jobData.type}`);
          }
        } catch (error) {
          logger.error(`Error creating processing job ${jobData.type}:`, error);
        }
      }
    } catch (error) {
      logger.error('Error seeding processing jobs:', error);
    }
  }

  async clear(): Promise<void> {
    try {
      logger.info('Clearing seeded data...');
      
      const supabase = getSupabaseServiceClient();
      await supabase.from('processing_jobs').delete().neq('id', uuidv4());
      await supabase.from('document_versions').delete().neq('id', uuidv4());
      await supabase.from('document_feedback').delete().neq('id', uuidv4());
      await supabase.from('documents').delete().neq('id', uuidv4());
      await supabase.from('users').delete().in('email', ['admin@example.com', 'user1@example.com', 'user2@example.com']);
      
      logger.info('Seeded data cleared successfully');
    } catch (error) {
      logger.error('Error clearing seeded data:', error);
      throw error;
    }
  }
}

export default DatabaseSeeder;