/**
 * CRM Activity EventBus Listener
 *
 * Auto-creates ContactActivity entries for every meaningful engagement touchpoint.
 * This makes the CRM contact timeline actually useful — staff can see a contact's
 * full interaction history across campaigns, canvassing, donations, and SMS.
 *
 * No feature guard — always active (activities are core CRM data).
 */

import { eventBus } from '../event-bus.service';
import { logger } from '../../utils/logger';

// Lazy-import prisma to avoid circular dependency at module load time
let prismaPromise: ReturnType<typeof getPrisma> | null = null;
async function getPrisma() {
  const { prisma } = await import('../../config/database');
  return prisma;
}
function lazyPrisma() {
  if (!prismaPromise) prismaPromise = getPrisma();
  return prismaPromise;
}

/**
 * Find a contact by email. Returns null if not found or no email provided.
 */
async function findContactByEmail(email?: string | null): Promise<string | null> {
  if (!email) return null;
  try {
    const prisma = await lazyPrisma();
    const contactEmail = await prisma.contactEmail.findFirst({
      where: { email: email.toLowerCase() },
      select: { contactId: true },
    });
    return contactEmail?.contactId ?? null;
  } catch {
    return null;
  }
}

/**
 * Create a ContactActivity entry. Silently fails if contact not found.
 */
async function createActivity(
  contactId: string,
  type: string,
  title: string,
  description?: string,
  metadata?: Record<string, unknown>,
): Promise<void> {
  try {
    const prisma = await lazyPrisma();
    await prisma.contactActivity.create({
      data: {
        contactId,
        type: type as any,
        title,
        description,
        metadata: metadata ? (metadata as unknown as import('@prisma/client').Prisma.InputJsonValue) : undefined,
      },
    });
  } catch (err) {
    logger.debug(`CRM activity creation failed for contact ${contactId}:`, err);
  }
}

export function registerCrmActivityListener(): void {
  // Campaign email sent
  eventBus.subscribe('campaign.email.sent', 'crm:campaign-email', async (payload) => {
    const contactId = await findContactByEmail(payload.email);
    if (!contactId) return;
    await createActivity(contactId, 'EMAIL_SENT', `Sent advocacy email for "${payload.campaignSlug}"`, undefined, {
      campaignSlug: payload.campaignSlug,
      postalCode: payload.postalCode,
    });
  });

  // Shift signup
  eventBus.subscribe('shift.signup.created', 'crm:shift-signup', async (payload) => {
    const contactId = await findContactByEmail(payload.userEmail);
    if (!contactId) return;
    await createActivity(contactId, 'SHIFT_SIGNUP', `Signed up for shift: ${payload.shiftTitle}`, undefined, {
      shiftId: payload.shiftId,
      shiftDate: payload.shiftDate,
      signupType: payload.signupType,
    });
  });

  // Canvass visit recorded
  eventBus.subscribe('canvass.visit.recorded', 'crm:canvass-visit', async (payload) => {
    const contactId = await findContactByEmail(payload.email);
    if (!contactId) return;
    await createActivity(contactId, 'CANVASS_VISIT', `Canvass visit: ${payload.outcome}`, undefined, {
      visitId: payload.visitId,
      outcome: payload.outcome,
      supportLevel: payload.supportLevel,
    });
  });

  // Response submitted
  eventBus.subscribe('response.submitted', 'crm:response-submitted', async (payload) => {
    const contactId = await findContactByEmail(payload.userEmail);
    if (!contactId) return;
    await createActivity(contactId, 'RESPONSE_SUBMITTED', `Submitted response for "${payload.campaignTitle}"`, undefined, {
      responseId: payload.responseId,
      campaignId: payload.campaignId,
      representativeName: payload.representativeName,
    });
  });

  // Donation completed
  eventBus.subscribe('payment.donation.completed', 'crm:donation', async (payload) => {
    const contactId = await findContactByEmail(payload.email);
    if (!contactId) return;
    const amount = (payload.amountCents / 100).toFixed(2);
    await createActivity(contactId, 'DONATION', `Donated $${amount}`, undefined, {
      orderId: payload.orderId,
      amountCents: payload.amountCents,
    });
  });

  // Product purchased
  eventBus.subscribe('payment.product.purchased', 'crm:product-purchase', async (payload) => {
    const contactId = await findContactByEmail(payload.email);
    if (!contactId) return;
    const amount = (payload.amountCents / 100).toFixed(2);
    await createActivity(contactId, 'PURCHASE', `Purchased "${payload.productTitle}" ($${amount})`, undefined, {
      orderId: payload.orderId,
      productTitle: payload.productTitle,
      amountCents: payload.amountCents,
    });
  });

  // SMS sent
  eventBus.subscribe('sms.message.sent', 'crm:sms-sent', async (payload) => {
    // SMS uses phone numbers — find contact by phone
    try {
      const prisma = await lazyPrisma();
      const contactPhone = await prisma.contactPhone.findFirst({
        where: { phone: payload.phone },
        select: { contactId: true },
      });
      if (!contactPhone) return;
      await createActivity(contactPhone.contactId, 'SMS_SENT', `SMS sent to ${payload.phone}`, payload.body.slice(0, 200), {
        messageId: payload.messageId,
        campaignId: payload.campaignId,
      });
    } catch {
      // silent
    }
  });

  // SMS received
  eventBus.subscribe('sms.message.received', 'crm:sms-received', async (payload) => {
    try {
      const prisma = await lazyPrisma();
      const contactPhone = await prisma.contactPhone.findFirst({
        where: { phone: payload.phone },
        select: { contactId: true },
      });
      if (!contactPhone) return;
      await createActivity(contactPhone.contactId, 'SMS_RECEIVED', `SMS received from ${payload.phone}`, payload.body.slice(0, 200), {
        messageId: payload.messageId,
        conversationId: payload.conversationId,
        responseType: payload.responseType,
      });
    } catch {
      // silent
    }
  });

  // Video viewed (only logged-in users)
  eventBus.subscribe('media.video.viewed', 'crm:video-view', async (payload) => {
    if (!payload.userId) return;
    try {
      const prisma = await lazyPrisma();
      const user = await prisma.user.findUnique({
        where: { id: payload.userId },
        select: { email: true },
      });
      if (!user) return;
      const contactId = await findContactByEmail(user.email);
      if (!contactId) return;
      await createActivity(contactId, 'VIDEO_VIEW', `Watched "${payload.videoTitle}"`, undefined, {
        videoId: payload.videoId,
      });
    } catch {
      // silent
    }
  });

  // Subscription activated
  eventBus.subscribe('payment.subscription.activated', 'crm:subscription', async (payload) => {
    const contactId = await findContactByEmail(payload.email);
    if (!contactId) return;
    await createActivity(contactId, 'PURCHASE', `Subscribed to "${payload.planName}"`, undefined, {
      subscriptionId: payload.subscriptionId,
      planName: payload.planName,
    });
  });

  // Listmonk email bounced → flag contact
  eventBus.subscribe('listmonk.email.bounced', 'crm:email-bounced', async (payload) => {
    const contactId = await findContactByEmail(payload.subscriberEmail);
    if (!contactId) return;
    await createActivity(contactId, 'NOTE_ADDED', `Email bounced (${payload.bounceType})`, `Email address may be invalid — bounced on campaign #${payload.campaignId}`, {
      listmonkCampaignId: payload.campaignId,
      bounceType: payload.bounceType,
      action: 'bounced',
    });
  });

  // Listmonk email opened → activity
  eventBus.subscribe('listmonk.email.opened', 'crm:email-opened', async (payload) => {
    const contactId = await findContactByEmail(payload.subscriberEmail);
    if (!contactId) return;
    await createActivity(contactId, 'EMAIL_SENT', `Opened newsletter: "${payload.campaignName}"`, undefined, {
      listmonkCampaignId: payload.campaignId,
      action: 'opened',
    });
  });

  // Listmonk email link clicked → activity
  eventBus.subscribe('listmonk.email.clicked', 'crm:email-clicked', async (payload) => {
    const contactId = await findContactByEmail(payload.subscriberEmail);
    if (!contactId) return;
    await createActivity(contactId, 'EMAIL_SENT', `Clicked link in "${payload.campaignName}"`, payload.url, {
      listmonkCampaignId: payload.campaignId,
      action: 'clicked',
      url: payload.url,
    });
  });
}
