import { createClient } from "@/lib/supabase/server";
import { NextRequest, NextResponse } from "next/server";
import { validateCSRFToken, isSameOrigin } from "@/lib/csrf";
import { sanitizeInput } from "@/lib/sanitize";
import { checkRateLimit, getClientIP, createRateLimitResponse } from "@/lib/rate-limit";
import { logger } from "@/lib/logger";
import { z } from "zod";
import { 
  SEND_MESSAGE_RATE_LIMIT, 
  RATE_LIMIT_WINDOW_MS as SEND_MESSAGE_WINDOW_MS,
  MAX_LENGTH_MESSAGE_CONTENT 
} from '@/lib/constants';

// 60 messages per 15 min window per IP (prevents message spam)

// Attachment validation schema
const attachmentSchema = z.object({
  url: z.string().url().max(2048),
  filename: z.string().min(1).max(255),
  contentType: z.string().regex(/^[a-z]+\/[a-z0-9\-\+\.]+$/i).max(127),
  size: z.number().int().min(1).max(10 * 1024 * 1024), // 10MB max
});

const sendMessageSchema = z.object({
  content: z.string().max(MAX_LENGTH_MESSAGE_CONTENT),
  attachments: z.array(attachmentSchema).max(5).optional().default([]),
});

export async function POST(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const clientIP = getClientIP(request);
    const rateLimit = await checkRateLimit(`messages-send:${clientIP}`, SEND_MESSAGE_RATE_LIMIT, SEND_MESSAGE_WINDOW_MS);

    if (!rateLimit.allowed) {
      const retryAfter = Math.ceil((rateLimit.resetTime - Date.now()) / 1000);
      return createRateLimitResponse(clientIP, retryAfter);
    }

    // CSRF protection: validate same-origin and token
    if (!isSameOrigin(request)) {
      return NextResponse.json({ error: 'Cross-origin request not allowed' }, { status: 403 });
    }
    const csrfValid = await validateCSRFToken(request);
    if (!csrfValid) {
      return NextResponse.json({ error: 'Invalid or missing CSRF token' }, { status: 403 });
    }

    const { id: conversationId } = await params;
    const supabase = await createClient();

    // Check if user is authenticated
    const { data: { user }, error: authError } = await supabase.auth.getUser();
    
    if (authError || !user) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    // Parse and validate request body
    const body = await request.json();
    const validationResult = sendMessageSchema.safeParse(body);

    if (!validationResult.success) {
      return NextResponse.json(
        {
          error: "Invalid request data",
          details: validationResult.error.issues.map(e => ({
            field: e.path.join('.'),
            message: e.message
          }))
        },
        { status: 400 }
      );
    }

    const { content, attachments } = validationResult.data;
    const sanitizedContent = sanitizeInput(content, { maxLength: MAX_LENGTH_MESSAGE_CONTENT });

    if (!sanitizedContent) {
      return NextResponse.json(
        { error: "Message content is required" },
        { status: 400 }
      );
    }

    // Verify user is a participant in this conversation
    const { data: participant, error: participantError } = await supabase
      .from('conversation_participants')
      .select('id')
      .eq('conversation_id', conversationId)
      .eq('profile_id', user.id)
      .single();

    if (participantError || !participant) {
      return NextResponse.json({ error: "Conversation not found" }, { status: 404 });
    }

    // Insert the message
    const { data: message, error: messageError } = await supabase
      .from('messages')
      .insert({
        conversation_id: conversationId,
        sender_id: user.id,
        content: sanitizedContent,
        attachments: attachments
      })
      .select(`
        id,
        content,
        sender_id,
        status,
        created_at,
        attachments
      `)
      .single();

    if (messageError) {
      logger.error("Error sending message:", messageError);
      return NextResponse.json(
        { error: "Failed to send message" },
        { status: 500 }
      );
    }

    // Get the other participant to send notification
    const { data: otherParticipant } = await supabase
      .from('conversation_participants')
      .select('profile_id')
      .eq('conversation_id', conversationId)
      .neq('profile_id', user.id)
      .single();

    if (otherParticipant) {
      // Create notification for the other participant
      const { data: senderProfile } = await supabase
        .from('profiles')
        .select('name')
        .eq('id', user.id)
        .single();

      const { error: notifError } = await supabase.from('notifications').insert({
        profile_id: otherParticipant.profile_id,
        type: 'system',
        title: 'New message',
        body: `${senderProfile?.name || 'Someone'} sent you a message`,
        data: {
          conversationId: conversationId,
          senderId: user.id
        }
      });
      if (notifError) {
        logger.error('Failed to create message notification:', notifError);
      }
    }

    return NextResponse.json({
      message: {
        id: message.id,
        content: message.content,
        isOwn: true,
        timestamp: message.created_at,
        status: message.status,
        attachments: message.attachments
      }
    });
  } catch (error) {
    logger.error("Error in send message API:", error);
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 }
    );
  }
}