/**
 * Staff Support Messages API
 *
 * GET /api/staff/dashboard/support/[id]/messages - Get ticket messages (staff view)
 * POST /api/staff/dashboard/support/[id]/messages - Add staff reply to ticket
 *
 * Convex-first with Prisma fallback.
 */

import { NextRequest, NextResponse } from "next/server";
import { validateStaffSession } from "@/lib/staff-session";
import {
  getTicketWithMessages,
  addTicketMessage,
  getTicketById,
  markMessagesAsRead,
} from "@/lib/services/support-tickets.service";
import { sendStaffReplyNotification } from "@/lib/services/support-emails.service";
import { logger } from "@/lib/logger";
import { convexQuery, convexMutation } from "@/lib/convex-client";

export const dynamic = "force-dynamic";
export const runtime = "nodejs";

/**
 * GET /api/staff/dashboard/support/[id]/messages
 * Get a ticket with its message thread (staff view - no ownership check)
 */
export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  try {
    const session = await validateStaffSession(request);
    if (!session) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const { id: ticketId } = await params;

    if (!ticketId) {
      return NextResponse.json(
        { error: "Ticket ID is required" },
        { status: 400 },
      );
    }

    // --- Convex-first path ---
    try {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const result = (await convexQuery(
        "support/queries:getTicketWithMessages",
        { ticketId },
      )) as Record<string, unknown> | null;

      if (result) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const messageThread = (result.messageThread ?? []) as any[];
        const messages = messageThread.map((m) => ({
          id: m._id ?? m.id,
          ticketId: m.ticketId,
          senderId: m.senderId,
          senderType: m.senderType,
          message: m.message,
          attachments: m.attachments,
          isRead: m.isRead,
          createdAt: m.createdAt ? new Date(m.createdAt).toISOString() : null,
        }));

        return NextResponse.json({
          ticket: {
            id: result._id ?? result.id,
            userId: result.userId,
            subject: result.subject,
            category: result.category,
            priority: result.priority,
            status: result.status,
            attachments: result.attachments,
            resolvedAt: result.resolvedAt
              ? new Date(result.resolvedAt as number).toISOString()
              : null,
            resolvedBy: result.resolvedBy,
            resolution: result.resolution,
            createdAt: result.createdAt
              ? new Date(result.createdAt as number).toISOString()
              : null,
            updatedAt: result.updatedAt
              ? new Date(result.updatedAt as number).toISOString()
              : null,
            user: null, // User join not available in Convex path
          },
          messages,
        });
      }
    } catch (convexErr) {
      console.error(
        "Convex ticket messages failed, falling back to Prisma:",
        convexErr,
      );
    }

    // --- Prisma fallback ---
    const prismaResult = await getTicketWithMessages(ticketId);

    if (!prismaResult) {
      return NextResponse.json({ error: "Ticket not found" }, { status: 404 });
    }

    // Mark user messages as read when staff views
    await markMessagesAsRead(ticketId, "user_messages");

    return NextResponse.json({
      ticket: {
        id: prismaResult.id,
        userId: prismaResult.userId,
        subject: prismaResult.subject,
        category: prismaResult.category,
        priority: prismaResult.priority,
        status: prismaResult.status,
        attachments: prismaResult.attachments,
        resolvedAt: prismaResult.resolvedAt,
        resolvedBy: prismaResult.resolvedBy,
        resolution: prismaResult.resolution,
        createdAt: prismaResult.createdAt,
        updatedAt: prismaResult.updatedAt,
        user: prismaResult.user,
      },
      messages: prismaResult.messageThread,
    });
  } catch (error) {
    logger.error("Failed to fetch ticket messages for staff", { error });
    return NextResponse.json(
      { error: "Failed to fetch messages" },
      { status: 500 },
    );
  }
}

/**
 * POST /api/staff/dashboard/support/[id]/messages
 * Add a staff reply to a ticket thread
 * Only ADMIN or SUPER_ADMIN can reply
 */
export async function POST(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  try {
    const session = await validateStaffSession(request);
    if (!session) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    // Only ADMIN or SUPER_ADMIN can reply
    if (session.role !== "ADMIN" && session.role !== "SUPER_ADMIN") {
      return NextResponse.json(
        {
          error:
            "Insufficient permissions. Only ADMIN or SUPER_ADMIN can reply to tickets.",
        },
        { status: 403 },
      );
    }

    const { id: ticketId } = await params;

    if (!ticketId) {
      return NextResponse.json(
        { error: "Ticket ID is required" },
        { status: 400 },
      );
    }

    const body = await request.json();
    const { message, attachments } = body;

    // Validation
    if (!message || typeof message !== "string" || message.trim().length < 1) {
      return NextResponse.json(
        { error: "Message is required" },
        { status: 400 },
      );
    }

    // Validate attachments if provided
    if (
      attachments &&
      (!Array.isArray(attachments) ||
        attachments.some((a: unknown) => typeof a !== "string"))
    ) {
      return NextResponse.json(
        { error: "Attachments must be an array of strings (URLs)" },
        { status: 400 },
      );
    }

    // --- Convex-first path ---
    try {
      // Check ticket exists and is not closed
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const ticket = (await convexQuery(
        "support/queries:getTicketWithMessages",
        { ticketId },
      )) as Record<string, unknown> | null;

      if (!ticket) {
        return NextResponse.json(
          { error: "Ticket not found" },
          { status: 404 },
        );
      }

      if (ticket.status === "CLOSED") {
        return NextResponse.json(
          { error: "Cannot reply to a closed ticket" },
          { status: 400 },
        );
      }

      const messageId = await convexMutation("support/mutations:addMessage", {
        ticketId,
        senderId: session.id,
        senderType: "STAFF",
        message: message.trim(),
        attachments: attachments || undefined,
      });

      logger.info("Staff added message to ticket via Convex", {
        ticketId,
        staffId: session.id,
        messageId,
      });

      // Send email notification (stays as-is regardless of data source)
      let emailSent = false;
      try {
        // We don't have user info from Convex ticket, use basic notification
        const emailResult = await sendStaffReplyNotification({
          ticketId,
          ticketSubject: ticket.subject as string,
          recipientEmail: ticket.userId as string,
          recipientName: "Customer",
          senderName: session.name || "Support Team",
          messagePreview: message.trim().substring(0, 300),
          lang: "en",
        });
        emailSent = emailResult.success;
      } catch (emailError) {
        logger.error("Failed to send reply notification email", {
          error: emailError,
          ticketId,
        });
      }

      return NextResponse.json(
        {
          message: {
            id: messageId,
            ticketId,
            senderId: session.id,
            senderType: "STAFF",
            message: message.trim(),
            attachments: attachments || [],
            isRead: false,
            createdAt: new Date().toISOString(),
          },
          emailSent,
        },
        { status: 201 },
      );
    } catch (convexErr) {
      console.error(
        "Convex add message failed, falling back to Prisma:",
        convexErr,
      );
    }

    // --- Prisma fallback ---
    const ticket = await getTicketById(ticketId);
    if (!ticket) {
      return NextResponse.json({ error: "Ticket not found" }, { status: 404 });
    }

    if (ticket.status === "CLOSED") {
      return NextResponse.json(
        { error: "Cannot reply to a closed ticket" },
        { status: 400 },
      );
    }

    const newMessage = await addTicketMessage(
      ticketId,
      session.id,
      "STAFF",
      message.trim(),
      attachments || undefined,
    );

    logger.info("Staff added message to ticket", {
      ticketId,
      staffId: session.id,
      staffName: session.name,
      messageId: newMessage.id,
    });

    // Send email notification to user
    let emailSent = false;
    try {
      const emailResult = await sendStaffReplyNotification({
        ticketId,
        ticketSubject: ticket.subject,
        recipientEmail: ticket.user.email,
        recipientName: ticket.user.name || "Customer",
        senderName: session.name || "Support Team",
        messagePreview: message.trim().substring(0, 300),
        lang: "en",
      });
      emailSent = emailResult.success;
    } catch (emailError) {
      logger.error("Failed to send reply notification email", {
        error: emailError,
        ticketId,
      });
    }

    return NextResponse.json(
      {
        message: newMessage,
        emailSent,
      },
      { status: 201 },
    );
  } catch (error) {
    logger.error("Failed to send staff reply", { error });
    return NextResponse.json(
      { error: "Failed to send reply" },
      { status: 500 },
    );
  }
}
