/**
 * Monitor: Webhook Handler
 * Receives Twilio status callback webhooks
 */

import express, { Request, Response } from 'express';
import twilio from 'twilio';
import pino from 'pino';
import type { SubmissionStatus } from '../types';
import { sendNotification } from './notifier';
import { remediateFailure } from './remediation-engine';

const logger = pino({ name: 'webhook-handler' });
const router = express.Router();

// Middleware to validate Twilio webhook signatures
function validateTwilioSignature(req: Request, res: Response, next: Function) {
  const authToken = process.env.TWILIO_AUTH_TOKEN!;
  const twilioSignature = req.headers['x-twilio-signature'] as string;
  
  if (!twilioSignature) {
    logger.warn('Missing Twilio signature');
    return res.status(403).json({ error: 'Missing signature' });
  }

  const url = `${req.protocol}://${req.get('host')}${req.originalUrl}`;
  const params = req.body;

  const validator = twilio.validateRequest(authToken, twilioSignature, url, params);

  if (!validator) {
    logger.warn({ url }, 'Invalid Twilio signature');
    return res.status(403).json({ error: 'Invalid signature' });
  }

  next();
}

/**
 * POST /webhooks/brand-status
 * Handles brand registration status changes
 */
router.post('/brand-status', validateTwilioSignature, async (req: Request, res: Response) => {
  try {
    const {
      BrandRegistrationSid,
      Status,
      FailureReason,
      IdentityStatus,
    } = req.body;

    logger.info({
      brandSid: BrandRegistrationSid,
      status: Status,
      failureReason: FailureReason,
      identityStatus: IdentityStatus,
    }, 'Brand status webhook received');

    // Map Twilio status to our internal status
    let status: SubmissionStatus;
    switch (Status?.toUpperCase()) {
      case 'PENDING':
      case 'IN_REVIEW':
        status = 'brand_pending';
        break;
      case 'APPROVED':
        status = 'brand_approved';
        break;
      case 'FAILED':
      case 'REJECTED':
        status = 'brand_failed';
        break;
      case 'SUSPENDED':
        status = 'manual_review';
        break;
      default:
        logger.warn({ status: Status }, 'Unknown brand status in webhook');
        status = 'brand_pending';
    }

    // TODO: Update submission record in database
    // const submission = await db.findSubmissionByBrandSid(BrandRegistrationSid);
    // if (!submission) {
    //   logger.error({ brandSid: BrandRegistrationSid }, 'Submission not found for brand');
    //   return res.status(404).json({ error: 'Submission not found' });
    // }

    // await db.updateSubmission(submission.id, {
    //   status,
    //   failureReason: FailureReason,
    //   updatedAt: new Date(),
    //   brandResolvedAt: status === 'brand_approved' || status === 'brand_failed' ? new Date() : undefined,
    // });

    // For now, simulate submission record
    const submission = {
      id: 'sim-123',
      input: {
        business: { businessName: 'Example Corp' },
        notifyWebhook: process.env.NOTIFY_WEBHOOK_URL,
      },
      status,
      sidChain: { brandRegistrationSid: BrandRegistrationSid },
      failureReason: FailureReason,
      attemptCount: 1,
      maxAttempts: 3,
      remediationHistory: [],
    };

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

    // If failed, trigger remediation
    if (status === 'brand_failed') {
      logger.info({ submissionId: submission.id }, 'Triggering remediation for failed brand');
      await remediateFailure(submission as any, 'brand', FailureReason || 'Unknown failure');
    }

    res.status(200).json({ received: true });
  } catch (error) {
    logger.error({ error }, 'Error handling brand webhook');
    res.status(500).json({ error: 'Internal error' });
  }
});

/**
 * POST /webhooks/campaign-status
 * Handles campaign status changes
 */
router.post('/campaign-status', validateTwilioSignature, async (req: Request, res: Response) => {
  try {
    const {
      CampaignSid,
      Status,
      FailureReason,
    } = req.body;

    logger.info({
      campaignSid: CampaignSid,
      status: Status,
      failureReason: FailureReason,
    }, 'Campaign status webhook received');

    // Map Twilio status to our internal status
    let status: SubmissionStatus;
    switch (Status?.toUpperCase()) {
      case 'PENDING':
      case 'IN_REVIEW':
        status = 'campaign_pending';
        break;
      case 'VERIFIED':
      case 'APPROVED':
        status = 'campaign_approved';
        break;
      case 'FAILED':
      case 'REJECTED':
        status = 'campaign_failed';
        break;
      case 'SUSPENDED':
        status = 'manual_review';
        break;
      default:
        logger.warn({ status: Status }, 'Unknown campaign status in webhook');
        status = 'campaign_pending';
    }

    // TODO: Update submission record in database
    // const submission = await db.findSubmissionByCampaignSid(CampaignSid);
    // if (!submission) {
    //   logger.error({ campaignSid: CampaignSid }, 'Submission not found for campaign');
    //   return res.status(404).json({ error: 'Submission not found' });
    // }

    // await db.updateSubmission(submission.id, {
    //   status: status === 'campaign_approved' ? 'completed' : status,
    //   failureReason: FailureReason,
    //   updatedAt: new Date(),
    //   campaignResolvedAt: status === 'campaign_approved' || status === 'campaign_failed' ? new Date() : undefined,
    //   completedAt: status === 'campaign_approved' ? new Date() : undefined,
    // });

    // For now, simulate submission record
    const submission = {
      id: 'sim-456',
      input: {
        business: { businessName: 'Example Corp' },
        campaign: { useCase: 'ACCOUNT_NOTIFICATION' },
        notifyWebhook: process.env.NOTIFY_WEBHOOK_URL,
      },
      status: status === 'campaign_approved' ? 'completed' : status,
      sidChain: { campaignSid: CampaignSid },
      failureReason: FailureReason,
      attemptCount: 1,
      maxAttempts: 3,
      remediationHistory: [],
    };

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

    // If failed, trigger remediation
    if (status === 'campaign_failed') {
      logger.info({ submissionId: submission.id }, 'Triggering remediation for failed campaign');
      await remediateFailure(submission as any, 'campaign', FailureReason || 'Unknown failure');
    }

    res.status(200).json({ received: true });
  } catch (error) {
    logger.error({ error }, 'Error handling campaign webhook');
    res.status(500).json({ error: 'Internal error' });
  }
});

export default router;
