import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
import { edgeLogger, startRequest, endRequest } from "../_shared/logger.ts";
import { createErrorResponse } from "../_shared/errorSanitizer.ts";

const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};

interface InboundEmailPayload {
  from: string;
  to: string;
  subject: string;
  text: string;
  html?: string;
  messageId: string;
  inReplyTo?: string;
  references?: string[];
  headers: Record<string, string>;
}

const handler = async (req: Request): Promise<Response> => {
  if (req.method === 'OPTIONS') {
    return new Response(null, { headers: corsHeaders });
  }

  const tracking = startRequest();

  try {
    const supabase = createClient(
      Deno.env.get('SUPABASE_URL')!,
      Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
    );

    const payload: InboundEmailPayload = await req.json();
    const { from, to, subject, text, html, messageId, inReplyTo, references, headers } = payload;

    edgeLogger.info('Inbound email received', {
      requestId: tracking.requestId,
      from,
      to,
      messageId
    });

    // Extract thread ID from headers or inReplyTo
    let threadId = headers['X-Thread-ID'] || 
                   (inReplyTo ? inReplyTo.replace(/<|>/g, '').split('@')[0] : null);

    // If no thread ID, this is a NEW direct email (not a reply)
    const isNewEmail = !threadId;

    if (isNewEmail) {
      edgeLogger.info('New direct email received (no thread ID)', {
        requestId: tracking.requestId,
        from,
        subject,
        messageId
      });
    }

    // Find or create submission
    let submission = null;
    let submissionError = null;

    if (isNewEmail) {
      // Extract sender email
      const senderEmail = from.match(/<(.+)>/)?.[1] || from;
      const senderName = from.match(/^(.+?)\s*</)?.[1]?.trim() || senderEmail.split('@')[0];
      
      // Check for existing submission from this email in last 5 minutes (avoid duplicates)
      const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000).toISOString();
      const { data: existingRecent } = await supabase
        .from('contact_submissions')
        .select('id, ticket_number, thread_id, email')
        .eq('email', senderEmail.toLowerCase())
        .eq('subject', subject || '(No Subject)')
        .gte('created_at', fiveMinutesAgo)
        .maybeSingle();
      
      if (existingRecent) {
        // Use existing recent submission (duplicate email)
        submission = existingRecent;
        threadId = existingRecent.thread_id;
        
        edgeLogger.info('Using existing recent submission', {
          requestId: tracking.requestId,
          submissionId: existingRecent.id,
          ticketNumber: existingRecent.ticket_number
        });
      } else {
        // Create new contact submission
        const { data: newSubmission, error: createError } = await supabase
          .from('contact_submissions')
          .insert({
            name: senderName,
            email: senderEmail.toLowerCase(),
            subject: subject || '(No Subject)',
            message: text || html || '(Empty message)',
            category: 'general',
            status: 'pending',
            user_agent: 'Email Client',
            ip_address_hash: null
          })
          .select('id, ticket_number, email, status')
          .single();
        
        if (createError || !newSubmission) {
          edgeLogger.error('Failed to create submission from direct email', {
            requestId: tracking.requestId,
            error: createError
          });
          return createErrorResponse(createError, 500, corsHeaders);
        }
        
        submission = newSubmission;
        threadId = `${newSubmission.ticket_number}.${newSubmission.id}`;
        
        // Update thread_id
        await supabase
          .from('contact_submissions')
          .update({ thread_id: threadId })
          .eq('id', newSubmission.id);
        
        edgeLogger.info('Created new submission from direct email', {
          requestId: tracking.requestId,
          submissionId: newSubmission.id,
          ticketNumber: newSubmission.ticket_number,
          threadId
        });
      }
    } else {
      // EXISTING LOGIC: Find submission by thread_id or ticket_number
      const ticketMatch = threadId.match(/(?:ticket-)?(TW-\d+)/i);
      const ticketNumber = ticketMatch ? ticketMatch[1] : null;

      edgeLogger.info('Thread ID extracted', {
        requestId: tracking.requestId,
        rawThreadId: threadId,
        ticketNumber
      });

      // Strategy 1: Try exact thread_id match
      const { data: submissionByThreadId, error: error1 } = await supabase
        .from('contact_submissions')
        .select('id, email, status, ticket_number')
        .eq('thread_id', threadId)
        .maybeSingle();

      if (submissionByThreadId) {
        submission = submissionByThreadId;
      } else if (ticketNumber) {
        // Strategy 2: Try ticket_number match
        const { data: submissionByTicket, error: error2 } = await supabase
          .from('contact_submissions')
          .select('id, email, status, ticket_number, thread_id')
          .eq('ticket_number', ticketNumber)
          .maybeSingle();
        
        if (submissionByTicket) {
          submission = submissionByTicket;
          
          // Update thread_id if it's null or in old format
          if (!submissionByTicket.thread_id || submissionByTicket.thread_id !== threadId) {
            await supabase
              .from('contact_submissions')
              .update({ thread_id: threadId })
              .eq('id', submissionByTicket.id);
            
            edgeLogger.info('Updated submission thread_id', {
              requestId: tracking.requestId,
              submissionId: submissionByTicket.id,
              oldThreadId: submissionByTicket.thread_id,
              newThreadId: threadId
            });
          }
        } else {
          submissionError = error2;
        }
      } else {
        submissionError = error1;
      }

      if (submissionError || !submission) {
        edgeLogger.warn('Submission not found for thread ID', {
          requestId: tracking.requestId,
          threadId,
          ticketNumber,
          error: submissionError
        });
        return new Response(JSON.stringify({ success: false, reason: 'submission_not_found' }), {
          status: 200,
          headers: { ...corsHeaders, 'Content-Type': 'application/json' }
        });
      }

      // Verify sender email matches (only for existing submissions)
      const senderEmail = from.match(/<(.+)>/)?.[1] || from;
      if (senderEmail.toLowerCase() !== submission.email.toLowerCase()) {
        edgeLogger.warn('Sender email mismatch', {
          requestId: tracking.requestId,
          expected: submission.email,
          received: senderEmail
        });
        return new Response(JSON.stringify({ success: false, reason: 'email_mismatch' }), {
          status: 200,
          headers: { ...corsHeaders, 'Content-Type': 'application/json' }
        });
      }
    }

    // Insert email thread record
    const senderEmail = from.match(/<(.+)>/)?.[1] || from;
    const { error: insertError } = await supabase
      .from('contact_email_threads')
      .insert({
        submission_id: submission.id,
        message_id: messageId,
        in_reply_to: inReplyTo || null,
        reference_chain: references || [],
        from_email: senderEmail,
        to_email: to,
        subject,
        body_text: text,
        body_html: html,
        direction: 'inbound',
        metadata: {
          received_at: new Date().toISOString(),
          headers: headers,
          is_new_ticket: isNewEmail
        }
      });

    if (insertError) {
      edgeLogger.error('Failed to insert inbound email thread', {
        requestId: tracking.requestId,
        error: insertError
      });
      return createErrorResponse(insertError, 500, corsHeaders);
    }

    // Update submission status if pending
    if (submission.status === 'pending') {
      await supabase
        .from('contact_submissions')
        .update({ status: 'in_progress' })
        .eq('id', submission.id);
    }

    edgeLogger.info('Inbound email processed successfully', {
      requestId: tracking.requestId,
      submissionId: submission.id,
      duration: endRequest(tracking)
    });

    return new Response(
      JSON.stringify({ success: true }),
      { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    );

  } catch (error) {
    edgeLogger.error('Unexpected error in receive-inbound-email', {
      requestId: tracking.requestId,
      error: error instanceof Error ? error.message : String(error)
    });
    return createErrorResponse(error, 500, corsHeaders);
  }
};

serve(handler);