/**
 * IMAP Email Monitor
 * Polls adops@avbeat.com via Kerio Connect IMAP every 5 minutes.
 * Credentials stored as env vars (to be added after deployment).
 */

import { createClient } from '@/lib/supabase/server';
import { isSenderWhitelisted, isApprovalReply, isBlackmagicClient } from './adOpsConfig';
import { sendAdOpsEmail } from './adOpsEmailSender';

export interface ParsedEmail {
  messageId: string;
  from: string;
  subject: string;
  body: string;
  attachments: { filename: string; contentType: string; size: number; buffer?: Buffer }[];
  receivedAt: Date;
  threadId?: string;
}

export type RequestType = 'banner' | 'distribution' | 'newsletter' | 'inquiry' | 'approval' | 'unknown' | 'ignored';

/**
 * Poll IMAP inbox for new messages.
 * Returns parsed emails if IMAP credentials are configured.
 */
export async function pollImapInbox(): Promise<ParsedEmail[]> {
  const host = process.env.IMAP_HOST;
  const port = process.env.IMAP_PORT;
  const user = process.env.IMAP_USER;
  const pass = process.env.IMAP_PASS;

  if (!host || !user || !pass) {
    console.log('[IMAP] Credentials not yet configured — skipping poll');
    return [];
  }

  try {
    // Dynamic import to avoid build errors when imap-simple is not installed
    const imapSimple = await import('imap-simple').catch(() => null);
    if (!imapSimple) {
      console.log('[IMAP] imap-simple not available');
      return [];
    }

    const config = {
      imap: {
        user,
        password: pass,
        host,
        port: parseInt(port || '993'),
        tls: true,
        authTimeout: 10000,
      },
    };

    const connection = await imapSimple.default.connect(config);
    await connection.openBox('INBOX');

    const searchCriteria = ['UNSEEN'];
    const fetchOptions = {
      bodies: ['HEADER.FIELDS (FROM SUBJECT MESSAGE-ID)', 'TEXT'],
      markSeen: true,
      struct: true,
    };

    const messages = await connection.search(searchCriteria, fetchOptions);
    connection.end();

    return messages.map((msg: any) => {
      const header = msg.parts.find((p: any) => p.which === 'HEADER.FIELDS (FROM SUBJECT MESSAGE-ID)');
      const body = msg.parts.find((p: any) => p.which === 'TEXT');

      return {
        messageId: header?.body?.['message-id']?.[0] || `${Date.now()}`,
        from: header?.body?.from?.[0] || '',
        subject: header?.body?.subject?.[0] || '',
        body: body?.body || '',
        attachments: [],
        receivedAt: new Date(),
      } as ParsedEmail;
    });
  } catch (err: any) {
    console.error('[IMAP Poll Error]', err.message);
    return [];
  }
}

/**
 * Process a single inbound email through the ad ops pipeline.
 */
export async function processInboundEmail(email: ParsedEmail): Promise<void> {
  const supabase = await createClient();

  // Check for duplicate
  const { data: existing } = await supabase
    .from('adops_inbox_log')
    .select('id')
    .eq('message_id', email.messageId)
    .single();

  if (existing) return; // Already processed

  const fromEmail = extractEmail(email.from);
  const isWhitelisted = isSenderWhitelisted(fromEmail);

  // Log the inbound email
  const { data: logEntry } = await supabase
    .from('adops_inbox_log')
    .insert({
      message_id: email.messageId,
      from_email: fromEmail,
      subject: email.subject,
      received_at: email.receivedAt.toISOString(),
      is_whitelisted: isWhitelisted,
      processing_status: isWhitelisted ? 'processing' : 'ignored',
      request_type: isWhitelisted ? 'unknown' : 'ignored',
    })
    .select('id')
    .single();

  if (!isWhitelisted) return; // Silently ignore non-whitelisted senders

  // Check if this is an approval reply to an existing campaign
  if (isApprovalReply(email.body) || isApprovalReply(email.subject)) {
    await handleApprovalReply(email, logEntry?.id);
    return;
  }

  // Use AI to classify and parse the request
  const classification = await classifyEmailWithAI(email);

  await supabase
    .from('adops_inbox_log')
    .update({
      request_type: classification.type,
      parsed_data: classification.extractedData,
      processing_status: 'processing',
    })
    .eq('id', logEntry?.id);

  switch (classification.type) {
    case 'banner':
      await handleBannerRequest(email, classification.extractedData, logEntry?.id);
      break;
    case 'distribution':
      await handleDistributionRequest(email, classification.extractedData, logEntry?.id);
      break;
    case 'newsletter':
      await handleNewsletterInquiry(email, logEntry?.id);
      break;
    default:
      await handleUnknownRequest(email, logEntry?.id);
  }
}

async function classifyEmailWithAI(email: ParsedEmail): Promise<{
  type: RequestType;
  extractedData: Record<string, any>;
}> {
  try {
    const response = await fetch('/api/ai/chat-completion', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        messages: [
          {
            role: 'system',
            content: `You are an ad operations assistant. Classify this email and extract all relevant details.
Respond with JSON only:
{
  "type": "banner" | "distribution" | "newsletter" | "inquiry" | "unknown",
  "clientName": string or null,
  "publication": string or null,
  "placementZone": string or null,
  "destinationUrl": string or null,
  "startDate": string or null,
  "endDate": string or null,
  "agreedRate": number or null,
  "subject": string or null,
  "listName": string or null,
  "sendDate": string or null,
  "hasAttachment": boolean,
  "missingFields": string[]
}`,
          },
          {
            role: 'user',
            content: `Subject: ${email.subject}\n\nBody: ${email.body.substring(0, 2000)}`,
          },
        ],
        model: 'claude-3-5-haiku-20241022',
        max_tokens: 500,
      }),
    });

    if (response.ok) {
      const data = await response.json();
      const content = data.content || data.choices?.[0]?.message?.content || '{}';
      const parsed = JSON.parse(content.replace(/```json\n?|\n?```/g, '').trim());
      return { type: parsed.type || 'unknown', extractedData: parsed };
    }
  } catch {
    // AI unavailable — return unknown
  }

  return { type: 'unknown', extractedData: {} };
}

async function handleBannerRequest(
  email: ParsedEmail,
  data: Record<string, any>,
  logId?: string
): Promise<void> {
  const supabase = await createClient();

  const requiredFields = [
    { key: 'clientName', label: 'Client/advertiser name' },
    { key: 'publication', label: 'Which publication(s) to run on (AV Beat / AV Beat)' },
    { key: 'placementZone', label: 'Ad placement zone (leaderboard, sidebar, in-article, etc.)' },
    { key: 'destinationUrl', label: 'Click-through URL' },
    { key: 'startDate', label: 'Campaign start date' },
    { key: 'endDate', label: 'Campaign end date' },
    { key: 'agreedRate', label: 'Agreed campaign rate for invoicing' },
  ];

  const missingFields = requiredFields
    .filter(f => !data[f.key])
    .map(f => f.label);

  const hasImage = email.attachments.some(a =>
    a.contentType?.startsWith('image/') || /\.(jpg|jpeg|png|gif|webp)$/i.test(a.filename)
  );

  if (!hasImage) {
    missingFields.unshift('Banner image file (please attach the banner creative)');
  }

  const hasIO = email.attachments.some(a =>
    a.contentType === 'application/pdf' || /\.pdf$/i.test(a.filename)
  );

  if (!hasIO) {
    missingFields.push('Signed insertion order (PDF attachment)');
  }

  // Check Blackmagic rule
  const isBlackmagic = data.clientName && isBlackmagicClient(data.clientName);

  if (missingFields.length > 0) {
    // Create pending campaign
    const { data: campaign } = await supabase
      .from('ad_campaigns')
      .insert({
        campaign_name: `${data.clientName || 'Unknown'} — ${data.publication || 'TBD'}`,
        client_name: data.clientName || 'Unknown',
        publication_id: data.publication,
        placement_zone: data.placementZone,
        destination_url: data.destinationUrl,
        start_date: data.startDate,
        end_date: data.endDate,
        agreed_rate: data.agreedRate,
        status: 'pending_info',
        blackmagic_excluded: isBlackmagic,
        pending_info_fields: missingFields,
        created_by: extractEmail(email.from),
        campaign_type: 'banner',
      })
      .select('id')
      .single();

    const { subject, html } = (await import('./emailTemplates')).missingInfoBannerEmail({
      clientName: data.clientName || 'your client',
      missingFields,
      hasImage,
    });

    await sendAdOpsEmail({
      to: extractEmail(email.from),
      subject,
      html,
    });

    if (logId) {
      await supabase
        .from('adops_inbox_log')
        .update({
          processing_status: 'replied',
          action_taken: 'sent_missing_info_request',
          campaign_id: campaign?.id,
        })
        .eq('id', logId);
    }
  } else {
    // All info present — create campaign and send preview
    const { data: campaign } = await supabase
      .from('ad_campaigns')
      .insert({
        campaign_name: `${data.clientName} — ${data.publication}`,
        client_name: data.clientName,
        publication_id: data.publication,
        placement_zone: data.placementZone,
        destination_url: data.destinationUrl,
        start_date: data.startDate,
        end_date: data.endDate,
        agreed_rate: data.agreedRate,
        status: 'pending_approval',
        blackmagic_excluded: isBlackmagic,
        created_by: extractEmail(email.from),
        campaign_type: 'banner',
      })
      .select('id')
      .single();

    if (campaign) {
      const { generateBannerPreview } = await import('./screenshotService');
      const screenshot = await generateBannerPreview({
        bannerUrl: data.bannerUrl || '',
        destinationUrl: data.destinationUrl,
        width: 728,
        height: 90,
        publicationName: data.publication,
        campaignId: campaign.id,
      });

      if (screenshot.screenshotUrl) {
        await supabase
          .from('ad_campaigns')
          .update({ approval_screenshot_url: screenshot.screenshotUrl })
          .eq('id', campaign.id);
      }

      const { subject, html } = (await import('./emailTemplates')).bannerPreviewEmail({
        clientName: data.clientName,
        publication: data.publication,
        screenshotUrl: screenshot.fallback ? undefined : screenshot.screenshotUrl,
        campaignId: campaign.id,
      });

      await sendAdOpsEmail({ to: extractEmail(email.from), subject, html });
    }
  }
}

async function handleDistributionRequest(
  email: ParsedEmail,
  data: Record<string, any>,
  logId?: string
): Promise<void> {
  const supabase = await createClient();

  const requiredFields = [
    { key: 'subject', label: 'Email subject line' },
    { key: 'listName', label: 'Recipient list (e.g. "AV Beat full list")' },
    { key: 'sendDate', label: 'Preferred send date and time (default: Thursday 11:00 AM ET)' },
    { key: 'clientName', label: 'Client name (for tracking and invoicing)' },
  ];

  const hasHtml = email.attachments.some(a =>
    a.contentType === 'text/html' || /\.html?$/i.test(a.filename)
  );

  const missingFields = requiredFields
    .filter(f => !data[f.key])
    .map(f => f.label);

  if (!hasHtml) {
    missingFields.unshift('HTML file (please attach the email HTML)');
  }

  if (missingFields.length > 0) {
    const { subject, html } = (await import('./emailTemplates')).missingInfoEmailDistEmail({
      clientName: data.clientName || 'your client',
      missingFields,
    });

    await sendAdOpsEmail({ to: extractEmail(email.from), subject, html });
  }

  if (logId) {
    await supabase
      .from('adops_inbox_log')
      .update({ processing_status: 'replied', action_taken: 'sent_distribution_info_request' })
      .eq('id', logId);
  }
}

async function handleApprovalReply(email: ParsedEmail, logId?: string): Promise<void> {
  const supabase = await createClient();

  // Find the most recent pending_approval campaign from this sender
  const { data: campaign } = await supabase
    .from('ad_campaigns')
    .select('*')
    .eq('created_by', extractEmail(email.from))
    .eq('status', 'pending_approval')
    .order('created_at', { ascending: false })
    .limit(1)
    .single();

  if (campaign) {
    await supabase
      .from('ad_campaigns')
      .update({
        status: 'active',
        approved_at: new Date().toISOString(),
        approved_by: extractEmail(email.from),
        deployed_at: new Date().toISOString(),
      })
      .eq('id', campaign.id);

    const { bannerLiveEmail } = await import('./emailTemplates');
    const { subject, html } = bannerLiveEmail({
      clientName: campaign.client_name,
      publication: campaign.publication_id,
      startDate: campaign.start_date,
      endDate: campaign.end_date,
      campaignId: campaign.id,
    });

    await sendAdOpsEmail({ to: extractEmail(email.from), subject, html });

    // Create invoice (Ryan only)
    if (campaign.agreed_rate) {
      const { createAdOpsMoonInvoice } = await import('./adOpsInvoiceService');
      const invoiceResult = await createAdOpsMoonInvoice({
        campaignId: campaign.id,
        clientName: campaign.client_name,
        publication: campaign.publication_id,
        placementZone: campaign.placement_zone,
        startDate: campaign.start_date,
        endDate: campaign.end_date,
        agreedRate: campaign.agreed_rate,
      });

      if (invoiceResult.success) {
        const { invoiceCreatedEmail } = await import('./emailTemplates');
        const { subject: invSubject, html: invHtml } = invoiceCreatedEmail({
          clientName: campaign.client_name,
          campaignDescription: `${campaign.publication_id} — ${campaign.placement_zone}`,
          amount: campaign.agreed_rate,
          invoiceNumber: invoiceResult.invoiceNumber || invoiceResult.invoiceId || 'TBD',
          dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
          campaignId: campaign.id,
        });
        const { sendToRyanOnly } = await import('./adOpsEmailSender');
        await sendToRyanOnly({ subject: invSubject, html: invHtml });
      }
    }
  }

  if (logId) {
    await supabase
      .from('adops_inbox_log')
      .update({ processing_status: 'completed', action_taken: 'processed_approval' })
      .eq('id', logId);
  }
}

async function handleNewsletterInquiry(email: ParsedEmail, logId?: string): Promise<void> {
  const supabase = await createClient();
  await sendAdOpsEmail({
    to: extractEmail(email.from),
    subject: 'Re: Newsletter Inquiry',
    html: `<p>Hi Jeff — I received your newsletter inquiry. Ryan will follow up shortly.</p>`,
  });
  if (logId) {
    await supabase
      .from('adops_inbox_log')
      .update({ processing_status: 'replied', action_taken: 'newsletter_inquiry_forwarded' })
      .eq('id', logId);
  }
}

async function handleUnknownRequest(email: ParsedEmail, logId?: string): Promise<void> {
  const supabase = await createClient();
  await sendAdOpsEmail({
    to: extractEmail(email.from),
    subject: `Re: ${email.subject}`,
    html: `<p>Hi Jeff — I received your email but wasn't sure what you needed. Could you clarify whether this is a banner ad request, an email distribution, or something else? I'll take care of it right away.</p>`,
  });
  if (logId) {
    await supabase
      .from('adops_inbox_log')
      .update({ processing_status: 'replied', action_taken: 'sent_clarification_request' })
      .eq('id', logId);
  }
}

function extractEmail(from: string): string {
  const match = from.match(/<([^>]+)>/);
  return match ? match[1].toLowerCase() : from.toLowerCase().trim();
}
