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

/**
 * Get reviews for a user's business
 * Phase 8: Content, Careers, Real Estate, Analytics, Reviews
 */
export const getReviews = query({
  args: {
    userId: v.string(),
    platform: v.optional(v.string()),
    limit: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    const limit = args.limit ?? 50;
    return await ctx.db
      .query("reviews")
      .withIndex("by_userId", (q) => q.eq("userId", args.userId))
      .order("desc")
      .take(limit);
  },
});

/**
 * Get review requests for a user
 * Phase 8: Content, Careers, Real Estate, Analytics, Reviews
 */
export const getReviewRequests = query({
  args: {
    userId: v.string(),
    status: v.optional(v.string()),
    limit: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    const limit = args.limit ?? 50;
    const q = ctx.db
      .query("review_requests")
      .withIndex("by_userId", (q) => q.eq("userId", args.userId));

    if (args.status) {
      return await q
        .filter((f) => f.eq(f.field("status"), args.status))
        .order("desc")
        .take(limit);
    }

    return await q.order("desc").take(limit);
  },
});

/**
 * Get review widget settings for a user
 * Phase 8: Content, Careers, Real Estate, Analytics, Reviews
 */
export const getWidgetSettings = query({
  args: { userId: v.string() },
  handler: async (ctx, args) => {
    return await ctx.db
      .query("review_widget_settings")
      .withIndex("by_userId", (q) => q.eq("userId", args.userId))
      .unique();
  },
});

/**
 * Get aggregate review statistics for a user's business
 * Wave 1: Reviews gap-fill
 */
export const getReviewStats = query({
  args: { userId: v.string() },
  handler: async (ctx, args) => {
    const reviews = await ctx.db
      .query("reviews")
      .withIndex("by_userId", (q) => q.eq("userId", args.userId))
      .collect();

    const total = reviews.length;
    if (total === 0) {
      return {
        total: 0,
        averageRating: 0,
        distribution: { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 },
        responseRate: 0,
        byPlatform: {} as Record<string, number>,
        recentCount: 0,
      };
    }

    const distribution: Record<number, number> = {
      1: 0,
      2: 0,
      3: 0,
      4: 0,
      5: 0,
    };
    const byPlatform: Record<string, number> = {};
    let totalRating = 0;
    let respondedCount = 0;
    const thirtyDaysAgo = Date.now() - 30 * 24 * 60 * 60 * 1000;
    let recentCount = 0;

    for (const r of reviews) {
      totalRating += r.rating;
      distribution[r.rating] = (distribution[r.rating] ?? 0) + 1;
      byPlatform[r.platform] = (byPlatform[r.platform] ?? 0) + 1;
      if (r.responseText) respondedCount++;
      if (r.createdAt >= thirtyDaysAgo) recentCount++;
    }

    return {
      total,
      averageRating: Math.round((totalRating / total) * 10) / 10,
      distribution,
      responseRate: Math.round((respondedCount / total) * 100),
      byPlatform,
      recentCount,
    };
  },
});

/**
 * Get all question templates for a user, sorted by updatedAt descending
 * Wave 1: Reviews gap-fill
 */
export const getQuestionTemplates = query({
  args: { userId: v.string() },
  handler: async (ctx, args) => {
    const templates = await ctx.db
      .query("review_question_templates")
      .withIndex("by_userId", (q) => q.eq("userId", args.userId))
      .collect();

    // Sort by updatedAt descending (most recently updated first)
    return templates.sort((a, b) => b.updatedAt - a.updatedAt);
  },
});

/**
 * Get review request statistics: counts by status and channel
 * Wave 1: Reviews gap-fill
 */
export const getReviewRequestStats = query({
  args: { userId: v.string() },
  handler: async (ctx, args) => {
    const requests = await ctx.db
      .query("review_requests")
      .withIndex("by_userId", (q) => q.eq("userId", args.userId))
      .collect();

    const total = requests.length;
    const byStatus: Record<string, number> = {};
    const byChannel: Record<string, number> = {};

    for (const r of requests) {
      byStatus[r.status] = (byStatus[r.status] ?? 0) + 1;
      byChannel[r.channel] = (byChannel[r.channel] ?? 0) + 1;
    }

    const completedCount = byStatus["COMPLETED"] ?? 0;

    return {
      total,
      byStatus,
      byChannel,
      completionRate:
        total > 0 ? Math.round((completedCount / total) * 100) : 0,
    };
  },
});

/**
 * Get completed bookings from last 90 days that do not have a review request
 * Wave 1: Reviews gap-fill
 */
export const getEligibleBookings = query({
  args: {
    userId: v.string(),
    limit: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    const limit = args.limit ?? 100;
    const ninetyDaysAgo = Date.now() - 90 * 24 * 60 * 60 * 1000;

    // Get all review requests with a bookingId for this user
    const existingRequests = await ctx.db
      .query("review_requests")
      .withIndex("by_userId", (q) => q.eq("userId", args.userId))
      .collect();

    const requestedBookingIds = new Set(
      existingRequests
        .map((r) => r.bookingId)
        .filter((id): id is string => id !== undefined && id !== null),
    );

    // Get completed bookings from the last 90 days
    const bookings = await ctx.db
      .query("bookings")
      .withIndex("by_userId_status", (q) =>
        q.eq("userId", args.userId).eq("status", "completed"),
      )
      .filter((f) => f.gte(f.field("appointmentDate"), ninetyDaysAgo))
      .order("desc")
      .collect();

    // Filter out bookings that already have a review request
    const eligible = bookings
      .filter((b) => !requestedBookingIds.has(b._id))
      .slice(0, limit)
      .map((b) => ({
        id: b._id,
        customerName: b.customerName,
        customerPhone: b.customerPhone,
        customerEmail: b.customerEmail,
        serviceName: b.service,
        completedAt: b.appointmentDate,
      }));

    return eligible;
  },
});

/**
 * Get a review request by its unique token.
 * Used when a customer submits a review via the public link.
 * Wave 1: Reviews gap-fill
 */
export const getReviewRequestByToken = query({
  args: {
    token: v.string(),
    statuses: v.optional(v.array(v.string())),
    notExpired: v.optional(v.boolean()),
  },
  handler: async (ctx, args) => {
    const request = await ctx.db
      .query("review_requests")
      .withIndex("by_token", (q) => q.eq("token", args.token))
      .unique();

    if (!request) return null;

    // Filter by status if provided
    if (args.statuses && args.statuses.length > 0) {
      if (!args.statuses.includes(request.status)) return null;
    }

    // Filter out expired requests
    if (args.notExpired && request.expiresAt < Date.now()) return null;

    return request;
  },
});

/**
 * Get featured reviews for a user, ordered by featuredOrder ascending.
 * Wave 1: Reviews gap-fill
 */
export const getFeaturedReviews = query({
  args: {
    userId: v.string(),
    limit: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    const limit = args.limit ?? 100;
    const reviews = await ctx.db
      .query("reviews")
      .withIndex("by_userId_isFeatured", (q) =>
        q.eq("userId", args.userId).eq("isFeatured", true),
      )
      .collect();

    // Sort by featuredOrder ascending
    reviews.sort((a, b) => (a.featuredOrder ?? 0) - (b.featuredOrder ?? 0));
    return reviews.slice(0, limit);
  },
});

/**
 * Get a single review by its document ID (with ownership check).
 */
export const getReviewById = query({
  args: {
    userId: v.string(),
    reviewId: v.id("reviews"),
  },
  handler: async (ctx, args) => {
    const review = await ctx.db.get(args.reviewId);
    if (!review || review.userId !== args.userId) return null;
    return review;
  },
});

/**
 * Get a question template by userId + industry.
 * Wave 1: Reviews gap-fill
 */
export const getQuestionTemplateByIndustry = query({
  args: {
    userId: v.string(),
    industry: v.string(),
  },
  handler: async (ctx, args) => {
    return await ctx.db
      .query("review_question_templates")
      .withIndex("by_userId_industry", (q) =>
        q.eq("userId", args.userId).eq("industry", args.industry),
      )
      .unique();
  },
});
