import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
import { createEdgeFunction, type EdgeFunctionContext } from '../_shared/edgeFunctionWrapper.ts';
import { corsHeaders } from '../_shared/cors.ts';
import { addSpanEvent } from '../_shared/logger.ts';

interface MergeTicketsRequest {
  primaryTicketId: string;
  mergeTicketIds: string[];
  mergeReason?: string;
}

interface MergeTicketsResponse {
  success: boolean;
  primaryTicketNumber: string;
  mergedCount: number;
  threadsConsolidated: number;
  deletedTickets: string[];
}

const handler = async (req: Request, { supabase, user, span, requestId }: EdgeFunctionContext) => {
  // Parse request body
  const { primaryTicketId, mergeTicketIds, mergeReason }: MergeTicketsRequest = await req.json();

  // Validation
  if (!primaryTicketId || !mergeTicketIds || mergeTicketIds.length === 0) {
    throw new Error('Invalid request: primaryTicketId and mergeTicketIds required');
  }

  if (mergeTicketIds.includes(primaryTicketId)) {
    throw new Error('Cannot merge a ticket into itself');
  }

  if (mergeTicketIds.length > 10) {
    throw new Error('Maximum 10 tickets can be merged at once');
  }

  addSpanEvent(span, 'merge_tickets_started', { 
    primaryTicketId, 
    mergeCount: mergeTicketIds.length 
  });

  // Start transaction-like operations
  const allTicketIds = [primaryTicketId, ...mergeTicketIds];

  // Fetch all tickets
  const { data: tickets, error: fetchError } = await supabase
    .from('contact_submissions')
    .select('id, ticket_number, admin_notes, merged_ticket_numbers')
    .in('id', allTicketIds);

  if (fetchError) throw fetchError;
  if (!tickets || tickets.length !== allTicketIds.length) {
    throw new Error('One or more tickets not found');
  }

  const primaryTicket = tickets.find(t => t.id === primaryTicketId);
  const mergeTickets = tickets.filter(t => mergeTicketIds.includes(t.id));

  if (!primaryTicket) {
    throw new Error('Primary ticket not found');
  }

  // Check if any ticket already has merged_ticket_numbers
  const alreadyMerged = tickets.find(t => 
    t.merged_ticket_numbers && t.merged_ticket_numbers.length > 0
  );
  if (alreadyMerged) {
    throw new Error(`Ticket ${alreadyMerged.ticket_number} has already been used in a merge`);
  }

  addSpanEvent(span, 'tickets_validated', { 
    primaryTicket: primaryTicket.ticket_number,
    mergeTicketCount: mergeTickets.length
  });

  // Step 1: Move all email threads to primary ticket
  addSpanEvent(span, 'moving_email_threads', { 
    fromTickets: mergeTickets.map(t => t.ticket_number)
  });
  
  const { data: movedThreads, error: moveError } = await supabase
    .from('contact_email_threads')
    .update({ submission_id: primaryTicketId })
    .in('submission_id', mergeTicketIds)
    .select('id');

  if (moveError) throw moveError;

  const threadsMovedCount = movedThreads?.length || 0;

  addSpanEvent(span, 'threads_moved', { threadsMovedCount });

  if (threadsMovedCount === 0) {
    addSpanEvent(span, 'no_threads_found', { mergeTicketIds });
  }

  // Step 2: Consolidate admin notes
  let consolidatedNotes = primaryTicket.admin_notes || '';
  
  for (const ticket of mergeTickets) {
    if (ticket.admin_notes) {
      consolidatedNotes = consolidatedNotes.trim()
        ? `${consolidatedNotes}\n\n${ticket.admin_notes}`
        : ticket.admin_notes;
    }
  }

  // Step 3: Recalculate metadata from consolidated threads
  const { data: threadStats, error: statsError } = await supabase
    .from('contact_email_threads')
    .select('direction, created_at')
    .eq('submission_id', primaryTicketId);

  if (statsError) throw statsError;

  const outboundCount = threadStats?.filter(t => t.direction === 'outbound').length || 0;
  const lastAdminResponse = threadStats
    ?.filter(t => t.direction === 'outbound')
    .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0]?.created_at;
  const lastUserResponse = threadStats
    ?.filter(t => t.direction === 'inbound')
    .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0]?.created_at;

  addSpanEvent(span, 'metadata_recalculated', { 
    outboundCount,
    lastAdminResponse,
    lastUserResponse
  });

  // Get merged ticket numbers
  const mergedTicketNumbers = mergeTickets.map(t => t.ticket_number);

  // Step 4: Update primary ticket with consolidated data
  const { error: updateError } = await supabase
    .from('contact_submissions')
    .update({
      admin_notes: consolidatedNotes,
      response_count: outboundCount,
      last_admin_response_at: lastAdminResponse || null,
      merged_ticket_numbers: [
        ...(primaryTicket.merged_ticket_numbers || []),
        ...mergedTicketNumbers
      ],
      updated_at: new Date().toISOString(),
    })
    .eq('id', primaryTicketId);

  if (updateError) throw updateError;

  addSpanEvent(span, 'primary_ticket_updated', { primaryTicket: primaryTicket.ticket_number });

  // Step 5: Delete merged tickets
  const { error: deleteError } = await supabase
    .from('contact_submissions')
    .delete()
    .in('id', mergeTicketIds);

  if (deleteError) throw deleteError;

  addSpanEvent(span, 'merged_tickets_deleted', { count: mergeTicketIds.length });

  // Step 6: Audit log
  const { error: auditError } = await supabase.from('admin_audit_log').insert({
    admin_user_id: user.id,
    target_user_id: user.id,
    action: 'merge_contact_tickets',
    details: {
      primary_ticket_id: primaryTicketId,
      primary_ticket_number: primaryTicket.ticket_number,
      merged_ticket_ids: mergeTicketIds,
      merged_ticket_numbers: mergedTicketNumbers,
      merge_reason: mergeReason || null,
      threads_moved: threadsMovedCount,
      merged_count: mergeTickets.length,
    }
  });

  if (auditError) {
    addSpanEvent(span, 'audit_log_failed', { error: auditError.message });
  }

  addSpanEvent(span, 'merge_completed', { 
    primaryTicket: primaryTicket.ticket_number,
    mergedCount: mergeTickets.length
  });

  const response: MergeTicketsResponse = {
    success: true,
    primaryTicketNumber: primaryTicket.ticket_number,
    mergedCount: mergeTickets.length,
    threadsConsolidated: threadsMovedCount,
    deletedTickets: mergedTicketNumbers,
  };

  return response;
};

serve(createEdgeFunction({
  name: 'merge-contact-tickets',
  requireAuth: true,
  requiredRoles: ['superuser', 'admin', 'moderator'],
  corsHeaders,
  enableTracing: true,
  logRequests: true,
}, handler));
