import { Controller, Post, Body, Req } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import type { Request } from 'express';

import { TrackViewDto } from '../dto/track-view.dto';
import { TrackEngagementDto } from '../dto/track-engagement.dto';
import { TrackInteractionBatchDto } from '../dto/track-interaction.dto';
import {
  TrackEventDto,
  TrackBatchDto,
  TrackConversionDto,
  TrackFunnelStepDto,
  TrackRegistrationFunnelDto,
} from '../dto/track-event.dto';
import { TrackingService, TrackingResult, BatchTrackingResult } from './tracking.service';

/**
 * Event Collection Controller
 * Analytics event ingestion endpoints
 *
 * Endpoints:
 * - POST /track/view - Page view with device fingerprinting
 * - POST /track/engagement - Meaningful user interactions (like, subscribe, purchase)
 * - POST /track/interaction - Batched low-level interactions (click, scroll, funnel_step, resize)
 * - POST /track/event - Single generic event
 * - POST /track/batch - Batch of generic events
 * - POST /track/conversion - Conversion event (higher priority)
 * - POST /track/funnel - Funnel step event
 * - POST /track/registration-funnel - Registration funnel event (Lilith-specific)
 */
@ApiTags('Event Collection')
@Controller('track')
export class TrackingController {
  constructor(private readonly trackingService: TrackingService) {}

  @Post('view')
  @ApiOperation({
    summary: 'Track page view',
    description: 'Records a page view with device fingerprinting and first-touch attribution. Accepts both collector shape (pageUrl) and analytics-client shape (contentId + contentType).',
  })
  @ApiResponse({ status: 201, description: 'View tracked successfully' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackView(@Body() dto: TrackViewDto, @Req() request: Request): Promise<TrackingResult> {
    // Normalise: analytics-client sends contentId as the page URL
    const pageUrl = dto.pageUrl ?? dto.contentId ?? '';

    return this.trackingService.trackView(
      {
        pageUrl,
        referrer: dto.referrer,
        userId: dto.userId,
        sessionId: dto.sessionId,
        metadata: {
          ...dto.metadata,
          ...(dto.contentType ? { contentType: dto.contentType } : {}),
          ...(dto.app ? { app: dto.app } : {}),
          ...(dto.duration !== undefined ? { duration: dto.duration } : {}),
        },
        clientDevice: dto.clientDevice,
        attribution: dto.attribution,
      },
      request,
    );
  }

  @Post('engagement')
  @ApiOperation({
    summary: 'Track engagement event',
    description: 'Records a meaningful user interaction (like, comment, subscribe, purchase)',
  })
  @ApiResponse({ status: 201, description: 'Engagement tracked successfully' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackEngagement(@Body() dto: TrackEngagementDto): Promise<TrackingResult> {
    return this.trackingService.trackEvent({
      eventType: `engagement_${dto.metricType}`,
      sessionId: dto.userId, // engagement events are user-scoped
      userId: dto.userId,
      metadata: {
        metricType: dto.metricType,
        targetId: dto.targetId,
        targetType: dto.targetType,
        ...dto.metadata,
      },
    });
  }

  @Post('interaction')
  @ApiOperation({
    summary: 'Track interaction events (batched)',
    description: 'Records a batch of low-level interactions (clicks, scrolls, funnel steps, resizes)',
  })
  @ApiResponse({ status: 201, description: 'Interactions tracked successfully' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackInteraction(@Body() dto: TrackInteractionBatchDto): Promise<BatchTrackingResult> {
    return this.trackingService.trackBatch(
      dto.events.map((event) => ({
        eventType: event.type,
        sessionId: event.sessionId,
        userId: event.userId,
        metadata: event.data,
        timestamp: event.timestamp,
      })),
    );
  }

  @Post('event')
  @ApiOperation({
    summary: 'Track single event',
    description: 'Records a generic analytics event',
  })
  @ApiResponse({ status: 201, description: 'Event tracked successfully' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackEvent(@Body() dto: TrackEventDto): Promise<TrackingResult> {
    return this.trackingService.trackEvent({
      eventType: dto.eventType,
      sessionId: dto.sessionId,
      userId: dto.userId,
      pageUrl: dto.pageUrl,
      metadata: dto.metadata,
      timestamp: dto.timestamp,
    });
  }

  @Post('batch')
  @ApiOperation({
    summary: 'Track batch of events',
    description: 'Records multiple events in a single request (for client-side batching)',
  })
  @ApiResponse({ status: 201, description: 'Events tracked successfully' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackBatch(@Body() dto: TrackBatchDto): Promise<BatchTrackingResult> {
    return this.trackingService.trackBatch(
      dto.events.map((e) => ({
        eventType: e.eventType,
        sessionId: e.sessionId,
        userId: e.userId,
        pageUrl: e.pageUrl,
        metadata: e.metadata,
        timestamp: e.timestamp,
      })),
    );
  }

  @Post('conversion')
  @ApiOperation({
    summary: 'Track conversion',
    description: 'Records a conversion event with optional revenue value',
  })
  @ApiResponse({ status: 201, description: 'Conversion tracked successfully' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackConversion(@Body() dto: TrackConversionDto): Promise<TrackingResult> {
    return this.trackingService.trackConversion({
      conversionType: dto.conversionType,
      sessionId: dto.sessionId,
      userId: dto.userId,
      value: dto.value,
      currency: dto.currency,
      metadata: dto.metadata,
    });
  }

  @Post('funnel')
  @ApiOperation({
    summary: 'Track funnel step',
    description: 'Records a step in a conversion funnel',
  })
  @ApiResponse({ status: 201, description: 'Funnel step tracked successfully' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackFunnelStep(@Body() dto: TrackFunnelStepDto): Promise<TrackingResult> {
    return this.trackingService.trackEvent({
      eventType: 'funnel_step',
      sessionId: dto.sessionId,
      userId: dto.userId,
      metadata: {
        funnelId: dto.funnelId,
        stepId: dto.stepId,
        stepOrder: dto.stepOrder,
        ...dto.metadata,
      },
    });
  }

  @Post('registration-funnel')
  @ApiOperation({
    summary: 'Track registration funnel event',
    description: 'Records a registration funnel event (visit, signup, profile, conversion)',
  })
  @ApiResponse({ status: 201, description: 'Registration funnel event tracked' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackRegistrationFunnel(@Body() dto: TrackRegistrationFunnelDto): Promise<TrackingResult> {
    return this.trackingService.trackEvent({
      eventType: `registration_funnel_${dto.event}`,
      sessionId: dto.sessionId,
      userId: dto.userId,
      pageUrl: dto.route,
      timestamp: Date.parse(dto.timestamp),
      metadata: {
        audience: dto.audience,
        userType: dto.userType,
        registrationPath: dto.registrationPath,
        registrationType: dto.registrationType,
        entryReferrer: dto.entryReferrer,
        referrer: dto.referrer,
      },
    });
  }
}
