import { query } from "../_generated/server";
import { v } from "convex/values";

/**
 * Get support tickets for a user
 * Phase 3: Notifications & Support
 */
export const getTickets = query({
  args: {
    userId: v.string(),
    status: v.optional(v.string()),
    limit: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    const limit = args.limit ?? 20;
    return await ctx.db
      .query("support_tickets")
      .withIndex("by_userId", (q) => q.eq("userId", args.userId))
      .order("desc")
      .take(limit);
  },
});

/**
 * Get a single support ticket by ID
 * Phase 3: Notifications & Support
 */
export const getTicketById = query({
  args: { id: v.id("support_tickets") },
  handler: async (ctx, args) => {
    return await ctx.db.get(args.id);
  },
});

/**
 * Get messages for a support ticket
 * Phase 3: Notifications & Support
 */
export const getMessages = query({
  args: { ticketId: v.string() },
  handler: async (ctx, args) => {
    return await ctx.db
      .query("ticket_messages")
      .withIndex("by_ticketId_createdAt", (q) =>
        q.eq("ticketId", args.ticketId),
      )
      .order("asc")
      .collect();
  },
});

/**
 * Get published support FAQs by category
 * Phase 3: Notifications & Support
 */
export const getFAQs = query({
  args: {
    category: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    let q = ctx.db
      .query("support_faqs")
      .filter((f) => f.eq(f.field("isPublished"), true));

    if (args.category) {
      q = q.filter((f) => f.eq(f.field("category"), args.category));
    }

    return await q.collect();
  },
});

/**
 * Get contact submissions with optional filtering
 * Group G: Contact Form Migration
 */
export const getContactSubmissions = query({
  args: {
    status: v.optional(v.string()),
    limit: v.optional(v.number()),
    search: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    const limit = args.limit ?? 100;

    let q;
    if (args.status) {
      q = ctx.db
        .query("contact_submissions")
        .withIndex("by_status", (idx) => idx.eq("status", args.status!));
    } else {
      q = ctx.db.query("contact_submissions").withIndex("by_created_at");
    }

    const results = await q.order("desc").take(limit);

    if (args.search) {
      const term = args.search.toLowerCase();
      return results.filter(
        (submission) =>
          submission.email.toLowerCase().includes(term) ||
          submission.name.toLowerCase().includes(term),
      );
    }

    return results;
  },
});

/**
 * Get a single contact submission by ID
 * Group G: Contact Form Migration
 */
export const getContactSubmissionById = query({
  args: { id: v.id("contact_submissions") },
  handler: async (ctx, args) => {
    return await ctx.db.get(args.id);
  },
});

/**
 * Get all contact submissions by email
 * Group G: Contact Form Migration
 */
export const getContactSubmissionsByEmail = query({
  args: { email: v.string() },
  handler: async (ctx, args) => {
    return await ctx.db
      .query("contact_submissions")
      .withIndex("by_email", (q) => q.eq("email", args.email))
      .order("desc")
      .collect();
  },
});

// ── WU-14 gap-fill queries (staff support) ──────────────────────────────

/**
 * Get tickets for staff view (all users, paginated, filtered)
 * WU-14: Staff support tickets data-source routing
 */
export const getTicketsStaff = query({
  args: {
    status: v.optional(v.string()),
    priority: v.optional(v.string()),
    category: v.optional(v.string()),
    search: v.optional(v.string()),
    page: v.optional(v.number()),
    limit: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    const limit = args.limit ?? 20;
    const page = args.page ?? 1;
    const offset = (page - 1) * limit;

    let all = await ctx.db.query("support_tickets").order("desc").collect();

    // Apply filters
    if (args.status) {
      all = all.filter((t) => t.status === args.status);
    }
    if (args.priority) {
      all = all.filter((t) => t.priority === args.priority);
    }
    if (args.category) {
      all = all.filter((t) => t.category === args.category);
    }
    if (args.search) {
      const term = args.search.toLowerCase();
      all = all.filter(
        (t) =>
          t.subject.toLowerCase().includes(term) ||
          (t.userId && t.userId.toLowerCase().includes(term)),
      );
    }

    const total = all.length;
    const tickets = all.slice(offset, offset + limit).map((t) => ({
      id: t._id,
      ...t,
      createdAt: t.createdAt ? new Date(t.createdAt).toISOString() : null,
      updatedAt: t.updatedAt ? new Date(t.updatedAt).toISOString() : null,
    }));

    return {
      tickets,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  },
});

/**
 * Get ticket metrics (counts by status)
 * WU-14: Staff support metrics data-source routing
 */
export const getTicketMetrics = query({
  args: {},
  handler: async (ctx) => {
    const all = await ctx.db.query("support_tickets").collect();

    const total = all.length;
    const open = all.filter((t) => t.status === "OPEN").length;
    const inProgress = all.filter((t) => t.status === "IN_PROGRESS").length;
    const resolved = all.filter((t) => t.status === "RESOLVED").length;
    const closed = all.filter((t) => t.status === "CLOSED").length;

    // Recent tickets (last 24 hours)
    const oneDayAgo = Date.now() - 24 * 60 * 60 * 1000;
    const newToday = all.filter((t) => t.createdAt >= oneDayAgo).length;

    return {
      total,
      open,
      inProgress,
      resolved,
      closed,
      newToday,
    };
  },
});

/**
 * Get a ticket with its message thread
 * WU-14: Staff support ticket detail + messages data-source routing
 */
export const getTicketWithMessages = query({
  args: { ticketId: v.string() },
  handler: async (ctx, args) => {
    // Find ticket by prismaId or _id
    let ticket = await ctx.db
      .query("support_tickets")
      .filter((q) => q.eq(q.field("prismaId"), args.ticketId))
      .first();

    if (!ticket) {
      try {
        ticket = (await ctx.db.get(args.ticketId as any)) as typeof ticket;
      } catch {
        return null;
      }
    }
    if (!ticket) return null;

    // Get messages for this ticket
    const ticketIdStr = ticket.prismaId || ticket._id;
    const messages = await ctx.db
      .query("ticket_messages")
      .withIndex("by_ticketId_createdAt", (q) => q.eq("ticketId", ticketIdStr))
      .order("asc")
      .collect();

    // Also try with _id as ticketId
    let allMessages = messages;
    if (messages.length === 0 && ticket.prismaId) {
      const byConvexId = await ctx.db
        .query("ticket_messages")
        .withIndex("by_ticketId_createdAt", (q) =>
          q.eq("ticketId", ticket!._id),
        )
        .order("asc")
        .collect();
      allMessages = byConvexId;
    }

    // For tickets created before atomic message creation was added,
    // the initial message exists only on the ticket record, not in
    // ticket_messages. Prepend a synthetic message if the thread
    // doesn't already contain the initial message.
    if (ticket.message) {
      const hasInitialMessage = allMessages.some(
        (m) =>
          m.senderId === ticket!.userId &&
          m.message === ticket!.message,
      );
      if (!hasInitialMessage) {
        allMessages = [
          {
            _id: `synthetic-${ticket._id}`,
            _creationTime: ticket.createdAt,
            ticketId: ticket._id,
            senderId: ticket.userId,
            senderType: "USER" as const,
            message: ticket.message,
            isRead: true,
            createdAt: ticket.createdAt,
          } as any,
          ...allMessages,
        ];
      }
    }

    return { ...ticket, messageThread: allMessages };
  },
});
