/**
 * Monitor: Polling Job
 * BullMQ recurring job that polls pending submissions every 30 minutes
 */

import { Queue, Worker, QueueScheduler } from 'bullmq';
import pino from 'pino';
import type { SubmissionRecord, SubmissionStatus } from '../types';
import { checkBrandStatus, checkCampaignStatus } from './status-checker';
import { sendNotification } from './notifier';
import { remediateFailure } from './remediation-engine';

const logger = pino({ name: 'polling-job' });

const REDIS_CONNECTION = {
  host: process.env.REDIS_HOST || 'localhost',
  port: parseInt(process.env.REDIS_PORT || '6379', 10),
};

// Create queue and scheduler
const statusPollingQueue = new Queue('status-polling', {
  connection: REDIS_CONNECTION,
});

const statusPollingScheduler = new QueueScheduler('status-polling', {
  connection: REDIS_CONNECTION,
});

/**
 * Initialize the polling job
 * Runs every 30 minutes
 */
export async function startPollingJob() {
  // Add repeatable job (every 30 minutes)
  await statusPollingQueue.add(
    'poll-pending-submissions',
    {},
    {
      repeat: {
        every: 30 * 60 * 1000, // 30 minutes in ms
      },
      removeOnComplete: 10,
      removeOnFail: 50,
    }
  );

  logger.info('Status polling job scheduled (every 30 minutes)');
}

/**
 * Worker that processes the polling job
 */
export const statusPollingWorker = new Worker(
  'status-polling',
  async (job) => {
    logger.info('Starting status polling job');

    try {
      // TODO: Query database for all pending submissions
      // const pendingSubmissions = await db.findSubmissions({
      //   status: { $in: ['brand_pending', 'campaign_pending'] }
      // });

      // For now, simulate with mock data
      const pendingSubmissions: SubmissionRecord[] = []; // Replace with actual DB query

      logger.info({ count: pendingSubmissions.length }, 'Found pending submissions');

      for (const submission of pendingSubmissions) {
        try {
          await pollSubmission(submission);
        } catch (error) {
          logger.error({ error, submissionId: submission.id }, 'Error polling submission');
        }
      }

      logger.info('Status polling job completed');
      return { processed: pendingSubmissions.length };
    } catch (error) {
      logger.error({ error }, 'Error in polling job');
      throw error;
    }
  },
  {
    connection: REDIS_CONNECTION,
    concurrency: 5, // Process up to 5 submissions in parallel
  }
);

/**
 * Poll a single submission
 */
async function pollSubmission(submission: SubmissionRecord): Promise<void> {
  const { id, status, sidChain, input } = submission;

  logger.debug({ submissionId: id, status }, 'Polling submission');

  let newStatus: SubmissionStatus | undefined;
  let failureReason: string | undefined;

  // Check brand status if pending
  if (status === 'brand_pending' && sidChain.brandRegistrationSid) {
    try {
      const brandResult = await checkBrandStatus(sidChain.brandRegistrationSid);
      
      if (brandResult.status !== status) {
        logger.info({
          submissionId: id,
          oldStatus: status,
          newStatus: brandResult.status,
          failureReason: brandResult.failureReason,
        }, 'Brand status changed');

        newStatus = brandResult.status;
        failureReason = brandResult.failureReason;

        // Send notification
        await sendNotification({
          submissionId: id,
          businessName: input.business.businessName,
          status: newStatus,
          message: newStatus === 'brand_approved'
            ? 'Brand registration approved!'
            : newStatus === 'brand_failed'
            ? `Brand registration failed: ${failureReason}`
            : `Brand status updated to ${brandResult.rawStatus}`,
          details: failureReason,
          timestamp: new Date(),
        }, input.notifyWebhook);

        // If failed, trigger remediation
        if (newStatus === 'brand_failed') {
          await remediateFailure(submission, 'brand', failureReason || 'Unknown failure');
        }

        // TODO: Update database
        // await db.updateSubmission(id, {
        //   status: newStatus,
        //   failureReason,
        //   updatedAt: new Date(),
        //   brandResolvedAt: newStatus === 'brand_approved' || newStatus === 'brand_failed' ? new Date() : undefined,
        // });
      }
    } catch (error) {
      logger.error({ error, submissionId: id }, 'Error checking brand status');
    }
  }

  // Check campaign status if pending
  if (status === 'campaign_pending' && sidChain.campaignSid) {
    try {
      const campaignResult = await checkCampaignStatus(sidChain.campaignSid);
      
      if (campaignResult.status !== status) {
        logger.info({
          submissionId: id,
          oldStatus: status,
          newStatus: campaignResult.status,
          failureReason: campaignResult.failureReason,
        }, 'Campaign status changed');

        newStatus = campaignResult.status;
        failureReason = campaignResult.failureReason;

        const finalStatus = newStatus === 'campaign_approved' ? 'completed' : newStatus;

        // Send notification
        await sendNotification({
          submissionId: id,
          businessName: input.business.businessName,
          status: finalStatus,
          message: newStatus === 'campaign_approved'
            ? '🎉 Campaign approved! Your A2P registration is complete and live.'
            : newStatus === 'campaign_failed'
            ? `Campaign failed: ${failureReason}`
            : `Campaign status updated to ${campaignResult.rawStatus}`,
          details: failureReason,
          timestamp: new Date(),
        }, input.notifyWebhook);

        // If failed, trigger remediation
        if (newStatus === 'campaign_failed') {
          await remediateFailure(submission, 'campaign', failureReason || 'Unknown failure');
        }

        // TODO: Update database
        // await db.updateSubmission(id, {
        //   status: finalStatus,
        //   failureReason,
        //   updatedAt: new Date(),
        //   campaignResolvedAt: newStatus === 'campaign_approved' || newStatus === 'campaign_failed' ? new Date() : undefined,
        //   completedAt: newStatus === 'campaign_approved' ? new Date() : undefined,
        // });
      }
    } catch (error) {
      logger.error({ error, submissionId: id }, 'Error checking campaign status');
    }
  }
}

/**
 * Stop the polling job
 */
export async function stopPollingJob() {
  await statusPollingWorker.close();
  await statusPollingQueue.close();
  await statusPollingScheduler.close();
  logger.info('Status polling job stopped');
}
