/**
 * Monitor: Remediation Engine
 * Auto-fixes known failure patterns
 */

import pino from 'pino';
import type { SubmissionRecord, RemediationEntry, BusinessInfo, CampaignInfo } from '../types';
import { sendNotification } from './notifier';

const logger = pino({ name: 'remediation-engine' });

type FailureType = 'brand' | 'campaign';

interface RemediationStrategy {
  pattern: RegExp;
  name: string;
  fix: (submission: SubmissionRecord) => Promise<RemediationResult>;
}

interface RemediationResult {
  success: boolean;
  fixApplied: string;
  fieldsChanged: Record<string, { old: string; new: string }>;
  newInput?: any; // Modified input to resubmit
}

/**
 * Main remediation entry point
 */
export async function remediateFailure(
  submission: SubmissionRecord,
  failureType: FailureType,
  failureReason: string
): Promise<void> {
  const { id, input, attemptCount, maxAttempts, remediationHistory } = submission;

  logger.info({
    submissionId: id,
    failureType,
    failureReason,
    attemptCount,
    maxAttempts,
  }, 'Starting remediation');

  // Check if we've exceeded max attempts
  if (attemptCount >= maxAttempts) {
    logger.warn({ submissionId: id }, 'Max attempts reached, marking for manual review');
    
    // TODO: Update database
    // await db.updateSubmission(id, {
    //   status: 'manual_review',
    //   updatedAt: new Date(),
    // });

    await sendNotification({
      submissionId: id,
      businessName: input.business.businessName,
      status: 'manual_review',
      message: `Max remediation attempts (${maxAttempts}) reached. Manual review required.`,
      details: `Last failure: ${failureReason}`,
      timestamp: new Date(),
    }, input.notifyWebhook);

    return;
  }

  // Find matching remediation strategy
  const strategy = findRemediationStrategy(failureReason, failureType);

  if (!strategy) {
    logger.warn({ submissionId: id, failureReason }, 'No remediation strategy found, marking for manual review');
    
    // TODO: Update database
    // await db.updateSubmission(id, {
    //   status: 'manual_review',
    //   failureReason: `Unknown error pattern: ${failureReason}`,
    //   updatedAt: new Date(),
    // });

    await sendNotification({
      submissionId: id,
      businessName: input.business.businessName,
      status: 'manual_review',
      message: 'Unknown failure pattern detected. Manual review required.',
      details: failureReason,
      timestamp: new Date(),
    }, input.notifyWebhook);

    return;
  }

  // Apply the fix
  try {
    logger.info({ submissionId: id, strategy: strategy.name }, 'Applying remediation strategy');
    
    const result = await strategy.fix(submission);

    if (!result.success) {
      throw new Error('Remediation strategy failed');
    }

    // Create remediation entry
    const remediationEntry: RemediationEntry = {
      timestamp: new Date(),
      failureReason,
      fixApplied: result.fixApplied,
      fieldsChanged: result.fieldsChanged,
      resubmittedAt: new Date(),
    };

    // TODO: Update database and resubmit
    // await db.updateSubmission(id, {
    //   status: 'remediation',
    //   input: result.newInput || input,
    //   attemptCount: attemptCount + 1,
    //   remediationHistory: [...remediationHistory, remediationEntry],
    //   updatedAt: new Date(),
    // });

    // Log the remediation details
    logger.info({
      submissionId: id,
      strategy: strategy.name,
      fixApplied: result.fixApplied,
      fieldsChanged: result.fieldsChanged,
    }, 'Remediation applied successfully');

    // Send notification
    const changesDescription = Object.entries(result.fieldsChanged)
      .map(([field, { old, new: newVal }]) => `${field}: "${old}" → "${newVal}"`)
      .join(', ');

    await sendNotification({
      submissionId: id,
      businessName: input.business.businessName,
      status: 'remediation',
      message: `Auto-fixing detected issue: ${failureReason}`,
      details: `Applied fix: ${result.fixApplied}. Changes: ${changesDescription}. Resubmitting...`,
      timestamp: new Date(),
    }, input.notifyWebhook);

    // TODO: Trigger resubmission workflow
    // await resubmitRegistration(id, failureType);

  } catch (error) {
    logger.error({ error, submissionId: id }, 'Error during remediation');
    
    // TODO: Update database
    // await db.updateSubmission(id, {
    //   status: 'manual_review',
    //   failureReason: `Remediation failed: ${error.message}`,
    //   updatedAt: new Date(),
    // });

    await sendNotification({
      submissionId: id,
      businessName: input.business.businessName,
      status: 'manual_review',
      message: 'Auto-remediation failed. Manual review required.',
      details: `Error: ${error instanceof Error ? error.message : String(error)}`,
      timestamp: new Date(),
    }, input.notifyWebhook);
  }
}

/**
 * Find the appropriate remediation strategy based on failure reason
 */
function findRemediationStrategy(
  failureReason: string,
  failureType: FailureType
): RemediationStrategy | null {
  const strategies = getRemediationStrategies();
  
  for (const strategy of strategies) {
    if (strategy.pattern.test(failureReason)) {
      return strategy;
    }
  }

  return null;
}

/**
 * Define all remediation strategies
 */
function getRemediationStrategies(): RemediationStrategy[] {
  return [
    // Business name mismatch
    {
      pattern: /business.*name|identity.*unverified|ein.*mismatch/i,
      name: 'business-name-variation',
      fix: async (submission) => {
        const { businessName } = submission.input.business;
        const variations = generateBusinessNameVariations(businessName);
        
        // Try the first variation
        const newName = variations[0];
        
        return {
          success: true,
          fixApplied: 'Tried business name variation (added/removed legal suffix)',
          fieldsChanged: {
            'business.businessName': { old: businessName, new: newName },
          },
          newInput: {
            ...submission.input,
            business: {
              ...submission.input.business,
              businessName: newName,
            },
          },
        };
      },
    },

    // Website not accessible
    {
      pattern: /website.*not.*accessible|url.*unreachable|domain.*invalid/i,
      name: 'website-accessibility',
      fix: async (submission) => {
        const { websiteUrl } = submission.input.business;
        
        // TODO: Check if landing page is deployed
        // TODO: Redeploy if needed
        // For now, just add https:// if missing
        let newUrl = websiteUrl;
        if (!websiteUrl.startsWith('http')) {
          newUrl = `https://${websiteUrl}`;
        }
        
        return {
          success: true,
          fixApplied: 'Ensured website URL has proper https:// prefix, will retry verification',
          fieldsChanged: {
            'business.websiteUrl': { old: websiteUrl, new: newUrl },
          },
          newInput: {
            ...submission.input,
            business: {
              ...submission.input.business,
              websiteUrl: newUrl,
            },
          },
        };
      },
    },

    // Insufficient opt-in description
    {
      pattern: /opt.*in|consent|tcpa|insufficient.*description/i,
      name: 'opt-in-enhancement',
      fix: async (submission) => {
        const { messageFlow, description } = submission.input.campaign;
        
        const enhancedMessageFlow = enhanceOptInDescription(messageFlow);
        const enhancedDescription = enhanceCampaignDescription(description);
        
        return {
          success: true,
          fixApplied: 'Enhanced opt-in description with stronger TCPA-compliant language',
          fieldsChanged: {
            'campaign.messageFlow': { old: messageFlow, new: enhancedMessageFlow },
            'campaign.description': { old: description, new: enhancedDescription },
          },
          newInput: {
            ...submission.input,
            campaign: {
              ...submission.input.campaign,
              messageFlow: enhancedMessageFlow,
              description: enhancedDescription,
            },
          },
        };
      },
    },

    // Sample messages non-compliant
    {
      pattern: /sample.*message|message.*content|prohibited.*content/i,
      name: 'sample-message-rewrite',
      fix: async (submission) => {
        const { sampleMessages } = submission.input.campaign;
        
        const compliantMessages = sampleMessages.map(msg => makeMessageCompliant(msg));
        
        return {
          success: true,
          fixApplied: 'Rewrote sample messages to include opt-out footer and remove prohibited content',
          fieldsChanged: {
            'campaign.sampleMessages': {
              old: sampleMessages.join(' | '),
              new: compliantMessages.join(' | '),
            },
          },
          newInput: {
            ...submission.input,
            campaign: {
              ...submission.input.campaign,
              sampleMessages: compliantMessages,
            },
          },
        };
      },
    },

    // Missing keywords
    {
      pattern: /keyword|stop|help|cancel/i,
      name: 'add-standard-keywords',
      fix: async (submission) => {
        const campaign = submission.input.campaign;
        
        const standardOptOut = ['STOP', 'CANCEL', 'END', 'QUIT', 'UNSUBSCRIBE'];
        const standardHelp = ['HELP', 'INFO', 'SUPPORT'];
        
        return {
          success: true,
          fixApplied: 'Added standard STOP and HELP keywords',
          fieldsChanged: {
            'campaign.optOutKeywords': {
              old: (campaign.optOutKeywords || []).join(', '),
              new: standardOptOut.join(', '),
            },
            'campaign.helpKeywords': {
              old: (campaign.helpKeywords || []).join(', '),
              new: standardHelp.join(', '),
            },
          },
          newInput: {
            ...submission.input,
            campaign: {
              ...submission.input.campaign,
              optOutKeywords: standardOptOut,
              helpKeywords: standardHelp,
            },
          },
        };
      },
    },

    // Duplicate brand
    {
      pattern: /duplicate.*brand|brand.*exists|already.*registered/i,
      name: 'reuse-existing-brand',
      fix: async (submission) => {
        // TODO: Check for existing approved brand
        // TODO: Reuse if found
        
        return {
          success: true,
          fixApplied: 'Will check for existing approved brand and reuse if available',
          fieldsChanged: {},
          newInput: submission.input,
        };
      },
    },

    // Rate limited
    {
      pattern: /rate.*limit|too.*many.*requests|429/i,
      name: 'exponential-backoff',
      fix: async (submission) => {
        const backoffMs = Math.min(1000 * Math.pow(2, submission.attemptCount), 60000);
        
        logger.info({ submissionId: submission.id, backoffMs }, 'Rate limited, applying exponential backoff');
        
        // TODO: Schedule retry after backoff period
        
        return {
          success: true,
          fixApplied: `Applied exponential backoff: waiting ${backoffMs}ms before retry`,
          fieldsChanged: {},
          newInput: submission.input,
        };
      },
    },
  ];
}

/**
 * Generate business name variations
 */
function generateBusinessNameVariations(name: string): string[] {
  const variations: string[] = [];
  const trimmed = name.trim();
  
  // Add/remove common suffixes
  const suffixes = ['Inc', 'Inc.', 'LLC', 'Corp', 'Corp.', 'Corporation', 'Company', 'Co', 'Co.'];
  
  for (const suffix of suffixes) {
    // Try adding suffix if not present
    if (!trimmed.includes(suffix)) {
      variations.push(`${trimmed} ${suffix}`);
      variations.push(`${trimmed}, ${suffix}`);
    }
    
    // Try removing suffix if present
    const withoutSuffix = trimmed
      .replace(new RegExp(`[,\\s]+${suffix}$`, 'i'), '')
      .trim();
    if (withoutSuffix !== trimmed) {
      variations.push(withoutSuffix);
    }
  }
  
  return variations;
}

/**
 * Enhance opt-in description with TCPA language
 */
function enhanceOptInDescription(original: string): string {
  const tcpaLanguage = `
Users explicitly opt in via web form with clear disclosure. 
By submitting the form, users affirmatively consent to receive text messages at the number provided. 
Users are informed that consent is not a condition of purchase and can opt out at any time by replying STOP. 
Message and data rates may apply.
  `.trim();
  
  if (original.toLowerCase().includes('tcpa') || original.toLowerCase().includes('consent')) {
    return original; // Already has TCPA language
  }
  
  return `${original}\n\n${tcpaLanguage}`;
}

/**
 * Enhance campaign description
 */
function enhanceCampaignDescription(original: string): string {
  if (original.length > 200) {
    return original; // Already detailed
  }
  
  return `${original}\n\nUsers receive automated notifications and updates related to their account or service. All messages include clear opt-out instructions. Users must explicitly opt in before receiving any messages.`;
}

/**
 * Make a message compliant
 */
function makeMessageCompliant(message: string): string {
  // Remove any potentially prohibited content (simplified)
  let compliant = message
    .replace(/\b(free|win|winner|prize|click here)\b/gi, '')
    .trim();
  
  // Ensure opt-out footer
  if (!compliant.toLowerCase().includes('stop')) {
    compliant += '\n\nReply STOP to opt out.';
  }
  
  return compliant;
}
