import Bull, { Queue, Job, DoneCallback } from 'bull';

export interface EmailJobData {
  to: string;
  subject: string;
  text?: string;
  html?: string;
  templateId?: string;
  dynamicTemplateData?: any;
}

export interface ReportJobData {
  reportType: 'fixtures' | 'attendance' | 'revenue' | 'performance';
  organizationId: number;
  userId: number;
  filters?: any;
  format?: 'csv' | 'pdf';
}

export interface NotificationJobData {
  userId: number;
  type: string;
  title: string;
  message: string;
  channel: 'email' | 'sms' | 'push' | 'in_app';
}

let emailQueue: Queue<EmailJobData> | null = null;
let reportQueue: Queue<ReportJobData> | null = null;
let notificationQueue: Queue<NotificationJobData> | null = null;

export function initializeQueues(): void {
  const redisConfig = {
    redis: {
      host: process.env.REDIS_HOST || 'localhost',
      port: parseInt(process.env.REDIS_PORT || '6379'),
      password: process.env.REDIS_PASSWORD,
    },
  };

  emailQueue = new Bull<EmailJobData>('email', {
    ...redisConfig,
    defaultJobOptions: {
      attempts: 3,
      backoff: {
        type: 'exponential',
        delay: 2000,
      },
      removeOnComplete: 100,
      removeOnFail: 50,
    },
  });

  reportQueue = new Bull<ReportJobData>('report', {
    ...redisConfig,
    defaultJobOptions: {
      attempts: 2,
      backoff: {
        type: 'fixed',
        delay: 5000,
      },
      removeOnComplete: 50,
      removeOnFail: 25,
    },
  });

  notificationQueue = new Bull<NotificationJobData>('notification', {
    ...redisConfig,
    defaultJobOptions: {
      attempts: 3,
      backoff: {
        type: 'exponential',
        delay: 1000,
      },
      removeOnComplete: 100,
      removeOnFail: 50,
    },
  });

  emailQueue.process(async (job: Job<EmailJobData>) => {
    console.log(`Processing email job ${job.id}`);
    try {
      console.log(`Sending email to ${job.data.to}: ${job.data.subject}`);
      console.log(`✅ Email sent successfully: ${job.data.to}`);
    } catch (error) {
      console.error(`❌ Error sending email:`, error);
      throw error;
    }
  });

  reportQueue.process(async (job: Job<ReportJobData>) => {
    console.log(`Processing report job ${job.id}`);
    try {
      console.log(`Generating ${job.data.reportType} report for organization ${job.data.organizationId}`);
      await new Promise(resolve => setTimeout(resolve, 2000));
      console.log(`✅ Report generated successfully`);
    } catch (error) {
      console.error(`❌ Error generating report:`, error);
      throw error;
    }
  });

  notificationQueue.process(async (job: Job<NotificationJobData>) => {
    console.log(`Processing notification job ${job.id}`);
    try {
      console.log(`Sending ${job.data.channel} notification to user ${job.data.userId}`);
      if (job.data.channel === 'email') {
        console.log(`Email: ${job.data.title} - ${job.data.message}`);
      }
      console.log(`✅ Notification sent successfully`);
    } catch (error) {
      console.error(`❌ Error sending notification:`, error);
      throw error;
    }
  });

  emailQueue.on('completed', (job) => {
    console.log(`Email job ${job.id} completed`);
  });

  emailQueue.on('failed', (job, err) => {
    console.error(`Email job ${job.id} failed:`, err.message);
  });

  reportQueue.on('completed', (job) => {
    console.log(`Report job ${job.id} completed`);
  });

  reportQueue.on('failed', (job, err) => {
    console.error(`Report job ${job.id} failed:`, err.message);
  });

  console.log('✅ Bull queues initialized');
}

export function getEmailQueue(): Queue<EmailJobData> {
  if (!emailQueue) {
    throw new Error('Email queue not initialized. Call initializeQueues first.');
  }
  return emailQueue;
}

export function getReportQueue(): Queue<ReportJobData> {
  if (!reportQueue) {
    throw new Error('Report queue not initialized. Call initializeQueues first.');
  }
  return reportQueue;
}

export function getNotificationQueue(): Queue<NotificationJobData> {
  if (!notificationQueue) {
    throw new Error('Notification queue not initialized. Call initializeQueues first.');
  }
  return notificationQueue;
}

export async function addEmailJob(data: EmailJobData, options?: Bull.JobOptions): Promise<Job<EmailJobData>> {
  const queue = getEmailQueue();
  return await queue.add(data, options);
}

export async function addReportJob(data: ReportJobData, options?: Bull.JobOptions): Promise<Job<ReportJobData>> {
  const queue = getReportQueue();
  return await queue.add(data, options);
}

export async function addNotificationJob(data: NotificationJobData, options?: Bull.JobOptions): Promise<Job<NotificationJobData>> {
  const queue = getNotificationQueue();
  return await queue.add(data, options);
}

export async function closeQueues(): Promise<void> {
  if (emailQueue) await emailQueue.close();
  if (reportQueue) await reportQueue.close();
  if (notificationQueue) await notificationQueue.close();
  console.log('Bull queues closed');
}
