/**
 * Reviews Service
 * Manage customer reviews, review requests, and review stats.
 *
 * All database calls go through Convex via convexQuery / convexMutation.
 */

import { convexQuery, convexMutation } from '@/lib/convex-client';
import { logger } from '@/lib/logger';
import type {
  CreateReviewInput,
  RespondToReviewInput,
  CreateReviewRequestInput,
  SubmitReviewViaTokenInput,
  SubmitReviewWithQuestionsInput,
  ReviewFilterInput,
} from '@/lib/validators/reviews.validator';

const log = logger.scope('ReviewsService');

// ═══════════════════════════════════════════════════════════════════════
// Shared types for Convex document shapes
// ═══════════════════════════════════════════════════════════════════════

interface ReviewDoc {
  _id: string;
  userId: string;
  customerName: string;
  customerEmail?: string | null;
  customerPhone?: string | null;
  platform: string;
  rating: number;
  title?: string | null;
  content?: string | null;
  language: string;
  isVerified: boolean;
  responseText?: string | null;
  respondedAt?: number | null;
  reviewRequestId?: string | null;
  questionResponses?: unknown;
  isFeatured: boolean;
  featuredAt?: number | null;
  featuredOrder?: number | null;
  createdAt: number;
  updatedAt: number;
}

interface ReviewRequestDoc {
  _id: string;
  userId: string;
  customerName: string;
  customerEmail?: string | null;
  customerPhone?: string | null;
  channel: string;
  token: string;
  message?: string | null;
  language: string;
  status: string;
  sentAt?: number | null;
  completedAt?: number | null;
  expiresAt: number;
  bookingId?: string | null;
  customerId?: string | null;
  questions?: unknown;
  source: string;
  reminderCount: number;
  createdAt: number;
  updatedAt: number;
}

interface QuestionTemplateDoc {
  _id: string;
  userId: string;
  industry?: string | null;
  questions?: unknown;
  isDefault?: boolean;
}

// ═══════════════════════════════════════════════════════════════════════
// Reviews CRUD
// ═══════════════════════════════════════════════════════════════════════

export async function createReview(userId: string, input: CreateReviewInput) {
  const reviewId = await convexMutation<string>('reviews/mutations:createReview', {
    userId,
    customerName: input.customerName,
    customerEmail: input.customerEmail ?? undefined,
    customerPhone: input.customerPhone ?? undefined,
    platform: input.platform,
    rating: input.rating,
    title: input.title ?? undefined,
    content: input.content ?? undefined,
    language: input.language,
  });

  log.info('Review created', { reviewId, userId, rating: input.rating });

  // Return a shape compatible with callers
  return {
    id: reviewId,
    userId,
    customerName: input.customerName,
    customerEmail: input.customerEmail ?? null,
    customerPhone: input.customerPhone ?? null,
    platform: input.platform,
    rating: input.rating,
    title: input.title ?? null,
    content: input.content ?? null,
    language: input.language,
    isVerified: false,
  };
}

export async function listReviews(
  userId: string,
  filters: ReviewFilterInput,
) {
  const page = filters.page ?? 1;
  const limit = Math.min(filters.limit ?? 20, 100);

  // Fetch all reviews for this user from Convex (indexed by userId)
  const allReviews =
    (await convexQuery<ReviewDoc[]>('reviews/queries:getReviews', {
      userId,
      limit: 10000, // fetch all for filtering
    })) ?? [];

  // Apply filters in the service layer (Convex doesn't support complex WHERE)
  let filtered = allReviews;

  if (filters.platform) {
    filtered = filtered.filter((r) => r.platform === filters.platform);
  }
  if (filters.minRating !== undefined) {
    filtered = filtered.filter((r) => r.rating >= filters.minRating!);
  }
  if (filters.maxRating !== undefined) {
    filtered = filtered.filter((r) => r.rating <= filters.maxRating!);
  }
  if (filters.hasResponse === 'true') {
    filtered = filtered.filter((r) => r.responseText != null);
  }
  if (filters.hasResponse === 'false') {
    filtered = filtered.filter((r) => r.responseText == null);
  }
  if (filters.search) {
    const term = filters.search.toLowerCase();
    filtered = filtered.filter(
      (r) =>
        r.customerName?.toLowerCase().includes(term) ||
        r.content?.toLowerCase().includes(term) ||
        r.title?.toLowerCase().includes(term),
    );
  }

  const total = filtered.length;
  const skip = (page - 1) * limit;
  const reviews = filtered.slice(skip, skip + limit);

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

export async function respondToReview(userId: string, input: RespondToReviewInput) {
  try {
    const resultId = await convexMutation<string>('reviews/mutations:updateReview', {
      userId,
      reviewId: input.reviewId,
      responseText: input.response,
    });

    if (!resultId) return null;

    log.info('Review responded', { reviewId: input.reviewId, userId });
    return { id: resultId };
  } catch {
    // Review not found or access denied
    return null;
  }
}

export async function getReviewStats(userId: string) {
  const stats = await convexQuery<{
    total: number;
    averageRating: number;
    distribution: Record<number, number>;
    responseRate: number;
    byPlatform: Record<string, number>;
    recentCount: number;
  }>('reviews/queries:getReviewStats', { userId });

  return (
    stats ?? {
      total: 0,
      averageRating: 0,
      distribution: { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 },
      responseRate: 0,
      byPlatform: {},
      recentCount: 0,
    }
  );
}

// ═══════════════════════════════════════════════════════════════════════
// Review Requests
// ═══════════════════════════════════════════════════════════════════════

export async function createReviewRequest(userId: string, input: CreateReviewRequestInput) {
  // Fetch user's configured questions for the public review form
  let questions: unknown[] = [];
  try {
    const template = await convexQuery<QuestionTemplateDoc>(
      'reviews/queries:getQuestionTemplateByIndustry',
      { userId, industry: 'general' },
    );
    if (template?.questions) {
      questions = (template.questions as unknown[]).filter(Boolean);
    }
  } catch {
    // Non-fatal — request is still created, public form falls back to default
  }

  const result = await convexMutation<{ id: string; token: string }>(
    'reviews/mutations:createReviewRequest',
    {
      userId,
      customerName: input.customerName,
      customerEmail: input.customerEmail ?? undefined,
      customerPhone: input.customerPhone ?? undefined,
      channel: input.channel,
      message: input.message ?? undefined,
      language: input.language,
      bookingId: input.bookingId ?? undefined,
      questions: questions.length > 0 ? questions : undefined,
    },
  );

  if (!result) {
    throw new Error('Failed to create review request');
  }

  log.info('Review request created', {
    requestId: result.id,
    userId,
    channel: input.channel,
  });

  return {
    id: result.id,
    token: result.token,
    userId,
    customerName: input.customerName,
    customerEmail: input.customerEmail ?? null,
    customerPhone: input.customerPhone ?? null,
    channel: input.channel,
    status: 'PENDING',
  };
}

interface SendReviewRequestResult {
  id: string;
  customerName: string;
  customerEmail?: string;
  customerPhone?: string;
  channel: string;
  token: string;
  language?: string;
}

export async function sendReviewRequest(userId: string, requestId: string) {
  try {
    const result = await convexMutation<SendReviewRequestResult>(
      'reviews/mutations:sendReviewRequest',
      { userId, requestId },
    );
    if (!result) return null;

    log.info('Review request sent', { requestId, userId });
    return result;
  } catch {
    // Request not found or access denied
    return null;
  }
}

export async function submitReviewViaToken(
  token: string,
  input: SubmitReviewViaTokenInput | SubmitReviewWithQuestionsInput,
) {
  // Look up the review request by token
  const request = await convexQuery<ReviewRequestDoc>(
    'reviews/queries:getReviewRequestByToken',
    { token, statuses: ['PENDING', 'SENT'], notExpired: true },
  );

  if (!request) return null;

  const questionResponses =
    'questionResponses' in input && input.questionResponses?.length
      ? input.questionResponses
      : [];

  // Create review linked to the request — the Convex mutation also marks
  // the request as COMPLETED automatically.
  const reviewId = await convexMutation<string>('reviews/mutations:createReview', {
    userId: request.userId,
    customerName: input.customerName,
    customerEmail: request.customerEmail ?? undefined,
    customerPhone: request.customerPhone ?? undefined,
    platform: 'website',
    rating: input.rating,
    title: input.title ?? undefined,
    content: input.content ?? undefined,
    language: input.language,
    reviewRequestId: request._id,
    questionResponses: questionResponses.length > 0 ? questionResponses : undefined,
  });

  log.info('Review submitted via token', { reviewId, requestId: request._id });

  return {
    id: reviewId,
    userId: request.userId,
    customerName: input.customerName,
    rating: input.rating,
    isVerified: true,
    reviewRequestId: request._id,
  };
}

export async function listReviewRequests(
  userId: string,
  page = 1,
  limit = 20,
) {
  // Fetch all review requests for this user
  const allRequests =
    (await convexQuery<ReviewRequestDoc[]>('reviews/queries:getReviewRequests', {
      userId,
      limit: 10000,
    })) ?? [];

  const total = allRequests.length;
  const skip = (page - 1) * limit;
  const requests = allRequests.slice(skip, skip + limit);

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

export async function getReviewRequestStats(userId: string) {
  const stats = await convexQuery<{
    total: number;
    byStatus: Record<string, number>;
    byChannel: Record<string, number>;
    completionRate: number;
  }>('reviews/queries:getReviewRequestStats', { userId });

  return (
    stats ?? {
      total: 0,
      byStatus: {},
      byChannel: {},
      completionRate: 0,
    }
  );
}

// ═══════════════════════════════════════════════════════════════════════
// Featured Reviews
// ═══════════════════════════════════════════════════════════════════════

export async function toggleFeaturedReview(
  userId: string,
  reviewId: string,
  featured: boolean,
) {
  try {
    const resultId = await convexMutation<string>('reviews/mutations:updateReview', {
      userId,
      reviewId,
      isFeatured: featured,
    });
    if (!resultId) return null;

    log.info('Featured review toggled', { reviewId, userId, featured });
    return { id: resultId };
  } catch {
    // Review not found or access denied
    return null;
  }
}

export async function listFeaturedReviews(userId: string) {
  return (
    (await convexQuery<ReviewDoc[]>('reviews/queries:getFeaturedReviews', {
      userId,
    })) ?? []
  );
}

export async function reorderFeaturedReviews(userId: string, orderedIds: string[]) {
  await convexMutation('reviews/mutations:reorderFeaturedReviews', {
    userId,
    orderedIds,
  });
  log.info('Featured reviews reordered', { userId, count: orderedIds.length });
}

export async function getPublicFeaturedReviews(userId: string) {
  const docs =
    (await convexQuery<ReviewDoc[]>('reviews/queries:getFeaturedReviews', {
      userId,
      limit: 100,
    })) ?? [];

  // Return only public-safe fields
  return docs.map((r) => ({
    id: r._id,
    customerName: r.customerName,
    rating: r.rating,
    title: r.title,
    content: r.content,
    language: r.language,
    platform: r.platform,
    createdAt: r.createdAt,
  }));
}

// ═══════════════════════════════════════════════════════════════════════
// Embed Code
// ═══════════════════════════════════════════════════════════════════════

export function generateEmbedCode(userId: string, baseUrl: string): string {
  const widgetUrl = `${baseUrl}/widget/reviews/${encodeURIComponent(userId)}`;
  return `<iframe src="${widgetUrl}" width="100%" height="500" frameborder="0" style="border:none;border-radius:12px;overflow:hidden;" title="Customer Reviews" loading="lazy"></iframe>`;
}
