import { serve } from 'https://deno.land/std@0.168.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, sanitizeError } from '../_shared/errorSanitizer.ts';

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

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

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

serve(async (req) => {
  const tracking = startRequest();

  if (req.method === 'OPTIONS') {
    return new Response(null, { headers: corsHeaders });
  }

  try {
    const authHeader = req.headers.get('Authorization');
    if (!authHeader) {
      throw new Error('Missing authorization header');
    }

    const supabase = createClient(
      Deno.env.get('SUPABASE_URL') ?? '',
      Deno.env.get('SUPABASE_ANON_KEY') ?? '',
      { global: { headers: { Authorization: authHeader } } }
    );

    // Authenticate user
    const { data: { user }, error: authError } = await supabase.auth.getUser();
    if (authError || !user) {
      throw new Error('Unauthorized');
    }

    edgeLogger.info('Merge tickets request started', {
      requestId: tracking.requestId,
      userId: user.id,
    });

    // Check if user has moderator/admin role
    const { data: hasRole, error: roleError } = await supabase.rpc('has_role', {
      _user_id: user.id,
      _role: 'moderator'
    });

    const { data: isAdmin, error: adminError } = await supabase.rpc('has_role', {
      _user_id: user.id,
      _role: 'admin'
    });

    const { data: isSuperuser, error: superuserError } = await supabase.rpc('has_role', {
      _user_id: user.id,
      _role: 'superuser'
    });

    if (roleError || adminError || superuserError || (!hasRole && !isAdmin && !isSuperuser)) {
      throw new Error('Insufficient permissions. Moderator role required.');
    }

    // 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');
    }

    // 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 (prevent re-merging)
    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`);
    }

    edgeLogger.info('Starting merge process', {
      requestId: tracking.requestId,
      primaryTicket: primaryTicket.ticket_number,
      mergeTicketCount: mergeTickets.length,
    });

    // Step 1: Move all email threads to primary ticket
    edgeLogger.info('Step 1: Moving email threads', { 
      requestId: tracking.requestId,
      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;

    edgeLogger.info('Threads moved successfully', { 
      requestId: tracking.requestId,
      threadsMovedCount 
    });

    if (threadsMovedCount === 0) {
      edgeLogger.warn('No email threads found to move', {
        requestId: tracking.requestId,
        mergeTicketIds
      });
    }

    // Step 2: Consolidate admin notes
    edgeLogger.info('Step 2: Consolidating admin notes', { requestId: tracking.requestId });
    
    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
    edgeLogger.info('Step 3: Recalculating metadata from threads', { requestId: tracking.requestId });
    
    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;

    edgeLogger.info('Metadata recalculated', { 
      requestId: tracking.requestId,
      outboundCount,
      lastAdminResponse,
      lastUserResponse
    });

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

    // Step 4: Update primary ticket with consolidated data
    edgeLogger.info('Step 4: Updating primary ticket', { requestId: tracking.requestId });
    
    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;

    edgeLogger.info('Primary ticket updated successfully', { requestId: tracking.requestId });

    // Step 5: Delete merged tickets
    edgeLogger.info('Step 5: Deleting merged tickets', { 
      requestId: tracking.requestId,
      ticketsToDelete: mergeTicketIds.length
    });
    
    const { error: deleteError } = await supabase
      .from('contact_submissions')
      .delete()
      .in('id', mergeTicketIds);

    if (deleteError) throw deleteError;

    edgeLogger.info('Merged tickets deleted successfully', { requestId: tracking.requestId });

    // Step 6: Audit log
    edgeLogger.info('Step 6: Creating audit log', { requestId: tracking.requestId });
    
    const { error: auditError } = await supabase.from('admin_audit_log').insert({
      admin_user_id: user.id,
      target_user_id: user.id, // No specific target user for this action
      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) {
      edgeLogger.warn('Failed to create audit log for merge', {
        requestId: tracking.requestId,
        error: auditError.message,
        primaryTicket: primaryTicket.ticket_number
      });
      // Don't throw - merge already succeeded
    }

    const duration = endRequest(tracking);
    edgeLogger.info('Merge tickets completed successfully', {
      requestId: tracking.requestId,
      duration,
      primaryTicket: primaryTicket.ticket_number,
      mergedCount: mergeTickets.length,
    });

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

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

  } catch (error) {
    const duration = endRequest(tracking);
    edgeLogger.error('Merge tickets failed', {
      requestId: tracking.requestId,
      duration,
      error: error instanceof Error ? error.message : 'Unknown error',
    });

    return createErrorResponse(error, 500, corsHeaders, 'merge_contact_tickets');
  }
});
