/**
 * Review Auto-Trigger Service
 *
 * Automatically sends review requests to customers ~24 hours after
 * a completed booking. Sends via both email and WhatsApp independently.
 * Designed to be called by a cron job.
 */

import { prisma } from '@/lib/db';
import { reviewQuestionTemplatesAdapter } from '@/lib/adapters/reviews';
import { logger } from '@/lib/logger';
import { createId } from '@paralleldrive/cuid2';
import crypto from 'crypto';
import { queueEmail } from '@/lib/queue/email-queue';
import { twilioWhatsAppService } from '@/lib/services/twilio-whatsapp.service';

export interface AutoTriggerResult {
  processed: number;
  skipped: number;
  errors: number;
}

/**
 * Get or create a question template for the user's industry.
 * Returns the questions JSON array, falling back to a generic set.
 */
async function getQuestionsForIndustry(
  userId: string,
  industry: string | null,
): Promise<Array<{ questionEn: string; questionAr: string; type?: string }>> {
  const resolvedIndustry = industry || 'general';

  const template = await reviewQuestionTemplatesAdapter.findUnique({
    where: {
      userId_industry: { userId, industry: resolvedIndustry },
    },
    select: { questions: true },
  });

  if (template?.questions) {
    return template.questions as Array<{ questionEn: string; questionAr: string; type?: string }>;
  }

  // Fallback: generic questions with types
  return [
    {
      questionEn: 'How would you rate your overall experience?',
      questionAr: 'كيف تقيّم تجربتك بشكل عام؟',
      type: 'rating',
    },
    {
      questionEn: 'Would you recommend us to others?',
      questionAr: 'هل تنصح الآخرين بنا؟',
      type: 'yesno',
    },
  ];
}

/**
 * Attempt to send a review request via WhatsApp.
 * Returns true if sent, false otherwise.
 */
async function sendWhatsAppReviewRequest(
  phone: string,
  customerName: string,
  reviewUrl: string,
  language: string,
  orgId: string | null,
): Promise<boolean> {
  if (!phone || !orgId) return false;

  try {
    const credentials = await twilioWhatsAppService.getCredentialsForOrg(orgId);
    if (!credentials) {
      logger.debug('review-auto-trigger: no WhatsApp credentials for org', { orgId });
      return false;
    }

    const body =
      language === 'ar'
        ? `مرحبًا ${customerName}، شكرًا لزيارتك! نود سماع رأيك. يرجى مشاركة تقييمك هنا: ${reviewUrl}`
        : `Hi ${customerName}, thank you for visiting! We'd love your feedback. Please share your review here: ${reviewUrl}`;

    const to = phone.startsWith('whatsapp:') ? phone : `whatsapp:${phone}`;
    const result = await twilioWhatsAppService.sendTextMessage(credentials, to, body);
    return result.success;
  } catch (error) {
    const msg = error instanceof Error ? error.message : 'Unknown error';
    logger.error('review-auto-trigger: WhatsApp send failed', { phone, error: msg });
    return false;
  }
}

/**
 * Process auto review requests for completed bookings.
 *
 * Finds bookings completed 23-25 hours ago with no existing review request,
 * then creates a review_request and sends via email + WhatsApp.
 */
export async function processAutoReviewRequests(): Promise<AutoTriggerResult> {
  const result: AutoTriggerResult = { processed: 0, skipped: 0, errors: 0 };

  const now = new Date();
  const from23HoursAgo = new Date(now.getTime() - 25 * 60 * 60 * 1000);
  const to23HoursAgo = new Date(now.getTime() - 23 * 60 * 60 * 1000);

  logger.info('review-auto-trigger: starting batch', {
    windowStart: from23HoursAgo.toISOString(),
    windowEnd: to23HoursAgo.toISOString(),
  });

  let bookings;
  try {
    bookings = await prisma.bookings.findMany({
      where: {
        status: 'completed',
        appointmentDate: {
          gte: from23HoursAgo,
          lte: to23HoursAgo,
        },
        review_requests: {
          none: {},
        },
      },
      select: {
        id: true,
        userId: true,
        organizationId: true,
        customerName: true,
        customerPhone: true,
        customerEmail: true,
        service: true,
      },
    });
  } catch (error) {
    const msg = error instanceof Error ? error.message : 'Unknown error';
    logger.error('review-auto-trigger: failed to query bookings', { error: msg });
    throw error;
  }

  logger.info('review-auto-trigger: found eligible bookings', { count: bookings.length });

  for (const booking of bookings) {
    try {
      const user = await prisma.users.findUnique({
        where: { id: booking.userId },
        select: { industry: true },
      });
      const language: string = 'en';
      const industry = user?.industry || null;

      // Look up customer by phone
      const customer = await prisma.customers.findFirst({
        where: {
          userId: booking.userId,
          phone: booking.customerPhone,
        },
        select: { id: true },
      });

      // Get question template
      const questions = await getQuestionsForIndustry(booking.userId, industry);

      // Generate token and ID
      const token = crypto.randomBytes(32).toString('hex');
      const requestId = createId();

      // Create review request
      const sentAt = new Date();
      const expiresAt = new Date(sentAt.getTime() + 14 * 24 * 60 * 60 * 1000); // 14 days
      const nextReminderAt = new Date(sentAt.getTime() + 3 * 24 * 60 * 60 * 1000); // 3 days

      await prisma.review_requests.create({
        data: {
          id: requestId,
          userId: booking.userId,
          customerName: booking.customerName,
          customerEmail: booking.customerEmail,
          customerPhone: booking.customerPhone,
          channel: booking.customerEmail && booking.customerPhone ? 'email' : booking.customerPhone ? 'whatsapp' : 'email',
          token,
          language,
          status: 'SENT',
          sentAt,
          expiresAt,
          bookingId: booking.id,
          customerId: customer?.id || null,
          questions,
          source: 'auto_booking',
          reminderCount: 0,
          nextReminderAt,
        },
      });

      const reviewUrl = `${process.env.NEXT_PUBLIC_APP_URL || 'https://mawidi.com'}/review/${token}`;

      // Send email (independent of WhatsApp)
      let emailSent = false;
      if (booking.customerEmail) {
        try {
          const subject =
            language === 'ar'
              ? 'نود سماع رأيك!'
              : 'We\'d love your feedback!';

          const html =
            language === 'ar'
              ? `<p>مرحبًا ${booking.customerName}،</p><p>شكرًا لحجزك معنا! نود سماع رأيك حول تجربتك.</p><p><a href="${reviewUrl}">شاركنا تقييمك</a></p>`
              : `<p>Hi ${booking.customerName},</p><p>Thank you for your booking with us! We'd love to hear about your experience.</p><p><a href="${reviewUrl}">Share your review</a></p>`;

          const text =
            language === 'ar'
              ? `مرحبًا ${booking.customerName}، شكرًا لحجزك معنا! شاركنا تقييمك: ${reviewUrl}`
              : `Hi ${booking.customerName}, thank you for your booking! Share your review: ${reviewUrl}`;

          await queueEmail({
            to: booking.customerEmail,
            subject,
            html,
            text,
            category: 'review_request',
            metadata: { reviewRequestId: requestId, bookingId: booking.id },
          });
          emailSent = true;
        } catch (emailError) {
          const msg = emailError instanceof Error ? emailError.message : 'Unknown error';
          logger.error('review-auto-trigger: email failed', {
            bookingId: booking.id,
            error: msg,
          });
        }
      }

      // Send WhatsApp (independent of email)
      let whatsAppSent = false;
      if (booking.customerPhone) {
        whatsAppSent = await sendWhatsAppReviewRequest(
          booking.customerPhone,
          booking.customerName,
          reviewUrl,
          language,
          booking.organizationId,
        );
      }

      // Update reminder status based on delivery results
      if (emailSent || whatsAppSent) {
        await prisma.review_requests.update({
          where: { id: requestId },
          data: { reminderStatus: 'SENT' },
        });
      } else {
        await prisma.review_requests.update({
          where: { id: requestId },
          data: { reminderStatus: 'FAILED' },
        });
      }

      result.processed++;
      logger.info('review-auto-trigger: request created', {
        bookingId: booking.id,
        requestId,
        emailSent,
        whatsAppSent,
      });
    } catch (itemError) {
      result.errors++;
      const msg = itemError instanceof Error ? itemError.message : 'Unknown error';
      logger.error('review-auto-trigger: failed to process booking', {
        bookingId: booking.id,
        error: msg,
      });
    }
  }

  logger.info('review-auto-trigger: batch complete', { ...result });
  return result;
}

// =============================================================================
// Immediate trigger — called when a booking is marked completed in real time
// =============================================================================

export interface ImmediateTriggerResult {
  sent: boolean;
  requestId?: string;
  emailSent: boolean;
  whatsAppSent: boolean;
  skipped?: boolean;
  reason?: string;
}

/**
 * Immediately send a review request for a single just-completed booking.
 * Safe to call from the booking status route — never throws.
 */
export async function triggerReviewForBooking(
  bookingId: string,
  userId: string,
): Promise<ImmediateTriggerResult> {
  const empty: ImmediateTriggerResult = { sent: false, emailSent: false, whatsAppSent: false };

  try {
    // Fetch booking (without relation join to avoid TS issues with non-standard includes)
    const booking = await prisma.bookings.findFirst({
      where: { id: bookingId, userId },
      select: {
        id: true,
        userId: true,
        organizationId: true,
        customerName: true,
        customerPhone: true,
        customerEmail: true,
        service: true,
      },
    });

    if (!booking) {
      return { ...empty, skipped: true, reason: 'booking not found' };
    }

    if (!booking.customerEmail && !booking.customerPhone) {
      return { ...empty, skipped: true, reason: 'no contact info' };
    }

    // Skip if a review request already exists for this booking
    const existing = await prisma.review_requests.findFirst({
      where: { bookingId },
      select: { id: true },
    });
    if (existing) {
      return { ...empty, skipped: true, reason: 'already requested' };
    }

    // Fetch user language/industry separately to avoid Prisma join TS issue
    const user = await prisma.users.findUnique({
      where: { id: userId },
      select: { industry: true },
    });
    const language: string = 'en'; // Default; user language pref not stored on users model
    const industry = (user as { industry?: string | null } | null)?.industry || null;
    const questions = await getQuestionsForIndustry(userId, industry);

    const token = crypto.randomBytes(32).toString('hex');
    const requestId = createId();
    const sentAt = new Date();
    const expiresAt = new Date(sentAt.getTime() + 14 * 24 * 60 * 60 * 1000);
    const nextReminderAt = new Date(sentAt.getTime() + 3 * 24 * 60 * 60 * 1000);

    await prisma.review_requests.create({
      data: {
        id: requestId,
        userId,
        customerName: booking.customerName,
        customerEmail: booking.customerEmail,
        customerPhone: booking.customerPhone,
        channel: booking.customerEmail ? 'email' : 'whatsapp',
        token,
        language,
        status: 'SENT',
        sentAt,
        expiresAt,
        bookingId: booking.id,
        questions,
        source: 'auto_booking',
        reminderCount: 0,
        nextReminderAt,
      },
    });

    const reviewUrl = `${process.env.NEXT_PUBLIC_APP_URL || 'https://mawidi.com'}/${language}/review/${token}`;

    // Send email
    let emailSent = false;
    if (booking.customerEmail) {
      try {
        const { buildReviewRequestEmailHtml } = await import('@/lib/email/review-request-email');
        const widgetSettings = await prisma.review_widget_settings
          .findUnique({ where: { userId } })
          .catch(() => null);
        const businessName =
          (language === 'ar' ? widgetSettings?.businessNameAr : widgetSettings?.businessName) ?? 'Mawidi';
        const email = buildReviewRequestEmailHtml({
          customerName: booking.customerName,
          businessName,
          reviewUrl,
          language: language as 'en' | 'ar',
          isReminder: false,
        });
        await queueEmail({
          to: booking.customerEmail,
          subject: email.subject,
          html: email.html,
          text: email.text,
          category: 'review_request',
          metadata: { reviewRequestId: requestId, bookingId: booking.id },
        });
        emailSent = true;
      } catch (e) {
        logger.error('review-auto-trigger: immediate email failed', {
          bookingId,
          error: e instanceof Error ? e.message : 'Unknown',
        });
      }
    }

    // Send WhatsApp
    let whatsAppSent = false;
    if (booking.customerPhone) {
      whatsAppSent = await sendWhatsAppReviewRequest(
        booking.customerPhone,
        booking.customerName,
        reviewUrl,
        language,
        booking.organizationId,
      );
    }

    // Update reminder status
    await prisma.review_requests.update({
      where: { id: requestId },
      data: { reminderStatus: emailSent || whatsAppSent ? 'SENT' : 'FAILED' },
    });

    logger.info('review-auto-trigger: immediate request sent', {
      bookingId,
      requestId,
      emailSent,
      whatsAppSent,
    });

    return { sent: true, requestId, emailSent, whatsAppSent };
  } catch (error) {
    logger.error('review-auto-trigger: immediate trigger failed', {
      bookingId,
      error: error instanceof Error ? error.message : 'Unknown',
    });
    return empty;
  }
}
