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 { CaptureService, CaptureResult, BatchCaptureResult } from './capture.service';

/**
 * Event Collection Controller
 * Analytics event ingestion endpoints.
 *
 * The controller validates (class-validator) and forwards to the edge
 * {@link CaptureService}, which normalizes and durably enqueues each event.
 * No database or enrichment happens here — those run on the black-side
 * ingest-writer. A 2xx means the event was durably accepted into redis
 * (black's queue, or the local spool during a black outage), not dropped.
 *
 * 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
 * - 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 capture: CaptureService) {}

  @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 accepted' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackView(@Body() dto: TrackViewDto, @Req() request: Request): Promise<CaptureResult> {
    return this.capture.trackView(dto, request);
  }

  @Post('engagement')
  @ApiOperation({
    summary: 'Track engagement event',
    description: 'Records a meaningful user interaction (like, comment, subscribe, purchase)',
  })
  @ApiResponse({ status: 201, description: 'Engagement accepted' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackEngagement(
    @Body() dto: TrackEngagementDto,
    @Req() request: Request,
  ): Promise<CaptureResult> {
    return this.capture.trackEngagement(dto, request);
  }

  @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 accepted' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackInteraction(
    @Body() dto: TrackInteractionBatchDto,
    @Req() request: Request,
  ): Promise<BatchCaptureResult> {
    return this.capture.trackInteraction(dto, request);
  }

  @Post('event')
  @ApiOperation({
    summary: 'Track single event',
    description: 'Records a generic analytics event',
  })
  @ApiResponse({ status: 201, description: 'Event accepted' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackEvent(@Body() dto: TrackEventDto, @Req() request: Request): Promise<CaptureResult> {
    return this.capture.trackEvent(dto, request);
  }

  @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 accepted' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackBatch(@Body() dto: TrackBatchDto, @Req() request: Request): Promise<BatchCaptureResult> {
    return this.capture.trackBatch(dto, request);
  }

  @Post('conversion')
  @ApiOperation({
    summary: 'Track conversion',
    description: 'Records a conversion event with optional revenue value',
  })
  @ApiResponse({ status: 201, description: 'Conversion accepted' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackConversion(
    @Body() dto: TrackConversionDto,
    @Req() request: Request,
  ): Promise<CaptureResult> {
    return this.capture.trackConversion(dto, request);
  }

  @Post('funnel')
  @ApiOperation({
    summary: 'Track funnel step',
    description: 'Records a step in a conversion funnel',
  })
  @ApiResponse({ status: 201, description: 'Funnel step accepted' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackFunnelStep(
    @Body() dto: TrackFunnelStepDto,
    @Req() request: Request,
  ): Promise<CaptureResult> {
    return this.capture.trackFunnelStep(dto, request);
  }

  @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 accepted' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async trackRegistrationFunnel(
    @Body() dto: TrackRegistrationFunnelDto,
    @Req() request: Request,
  ): Promise<CaptureResult> {
    return this.capture.trackRegistrationFunnel(dto, request);
  }
}
