/**
 * Gancio EventBus Listener
 *
 * Syncs shift and ticketed events to the Gancio public event calendar.
 * This replaces the inline gancioClient calls in shifts.service.ts and
 * ticketed-events.service.ts.
 *
 * Feature guard: GANCIO_SYNC_ENABLED=true (checked inside gancioClient)
 */

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

// Lazy-import to avoid circular dependency at module load
async function getGancioClient() {
  const { gancioClient } = await import('../gancio.client');
  return gancioClient;
}

export function registerGancioListener(): void {
  // Shift created → Create Gancio event
  eventBus.subscribe('shift.created', 'gancio:shift-created', async (payload) => {
    try {
      const gancio = await getGancioClient();
      if (!gancio.enabled) return;

      const eventId = await gancio.createEvent({
        title: payload.title,
        description: `Volunteer shift: ${payload.title}`,
        location: payload.cutName ?? 'TBD',
        date: new Date(payload.date),
        startTime: payload.startTime,
        endTime: payload.endTime,
        tags: ['volunteer', 'shift'],
      });

      // Store gancioEventId back on the shift
      if (eventId) {
        const { prisma } = await import('../../config/database');
        await prisma.shift.update({
          where: { id: payload.shiftId },
          data: { gancioEventId: eventId },
        });
      }
    } catch (err) {
      logger.debug('Gancio sync: shift create failed:', err);
    }
  });

  // Shift updated → Update Gancio event
  eventBus.subscribe('shift.updated', 'gancio:shift-updated', async (payload) => {
    try {
      const gancio = await getGancioClient();
      if (!gancio.enabled) return;

      const { prisma } = await import('../../config/database');
      const shift = await prisma.shift.findUnique({
        where: { id: payload.shiftId },
        select: { gancioEventId: true },
      });
      if (!shift?.gancioEventId) return;

      await gancio.updateEvent(shift.gancioEventId, {
        title: payload.title,
        description: `Volunteer shift: ${payload.title}`,
        location: payload.cutName ?? 'TBD',
        date: new Date(payload.date),
        startTime: payload.startTime,
        endTime: payload.endTime,
      });
    } catch (err) {
      logger.debug('Gancio sync: shift update failed:', err);
    }
  });

  // Shift deleted → Delete Gancio event
  eventBus.subscribe('shift.deleted', 'gancio:shift-deleted', async (payload) => {
    try {
      const gancio = await getGancioClient();
      if (!gancio.enabled) return;

      const { prisma } = await import('../../config/database');
      const shift = await prisma.shift.findUnique({
        where: { id: payload.shiftId },
        select: { gancioEventId: true },
      });
      if (!shift?.gancioEventId) return;

      await gancio.deleteEvent(shift.gancioEventId);
    } catch (err) {
      logger.debug('Gancio sync: shift delete failed:', err);
    }
  });

  // =========================================================================
  // TICKETED EVENT LISTENERS
  // =========================================================================

  // Ticketed event published → Create or update Gancio event
  eventBus.subscribe('ticketed-event.published', 'gancio:ticketed-event-published', async (payload) => {
    try {
      const gancio = await getGancioClient();
      if (!gancio.enabled) return;

      const { prisma } = await import('../../config/database');
      const event = await prisma.ticketedEvent.findUnique({
        where: { id: payload.eventId },
        select: {
          id: true,
          title: true,
          description: true,
          venueAddress: true,
          venueName: true,
          eventFormat: true,
          date: true,
          startTime: true,
          endTime: true,
          gancioEventId: true,
        },
      });
      if (!event) return;

      // Determine location based on event format
      const format = event.eventFormat || 'IN_PERSON';
      let location: string | null;
      if (format === 'ONLINE') {
        location = 'Online Event';
      } else if (format === 'HYBRID') {
        const venue = event.venueAddress || event.venueName || '';
        location = venue ? `${venue} (also streaming online)` : 'Online + In-Person';
      } else {
        location = event.venueAddress || event.venueName || null;
      }

      const tags = ['ticketed', 'community'];
      if (format === 'ONLINE') tags.push('online');
      if (format === 'HYBRID') tags.push('hybrid');

      if (event.gancioEventId) {
        // Update existing Gancio event
        await gancio.updateEvent(event.gancioEventId, {
          title: event.title,
          description: event.description,
          location,
          date: event.date,
          startTime: event.startTime,
          endTime: event.endTime,
        });
      } else {
        // Create new Gancio event and store ID back
        const gancioId = await gancio.createEvent({
          title: event.title,
          description: event.description,
          location,
          date: event.date,
          startTime: event.startTime,
          endTime: event.endTime,
          tags,
        });
        if (gancioId) {
          await prisma.ticketedEvent.update({
            where: { id: event.id },
            data: { gancioEventId: gancioId },
          });
        }
      }
    } catch (err) {
      logger.debug('Gancio sync: ticketed event publish failed:', err);
    }
  });

  // Ticketed event cancelled → Delete Gancio event
  eventBus.subscribe('ticketed-event.cancelled', 'gancio:ticketed-event-cancelled', async (payload) => {
    try {
      const gancio = await getGancioClient();
      if (!gancio.enabled) return;

      const { prisma } = await import('../../config/database');
      const event = await prisma.ticketedEvent.findUnique({
        where: { id: payload.eventId },
        select: { gancioEventId: true },
      });
      if (!event?.gancioEventId) return;

      await gancio.deleteEvent(event.gancioEventId);
    } catch (err) {
      logger.debug('Gancio sync: ticketed event cancel failed:', err);
    }
  });
}
