// src/app/(frontend)/api/timelines/route.ts
// Dedizierte Timeline-API für Frontend-Anwendungen

import { NextRequest, NextResponse } from 'next/server'
import { getPayload } from 'payload'
import type { Where } from 'payload'
import config from '@payload-config'
import type { Media } from '@/payload-types'

type Locale = 'de' | 'en' | 'all'
import {
  searchLimiter,
  rateLimitHeaders,
  getClientIpFromRequest,
  isIpBlocked,
} from '@/lib/security'

// Validation constants
const TIMELINE_RATE_LIMIT = 30

// Valid timeline types
const TIMELINE_TYPES = ['history', 'milestones', 'releases', 'career', 'events', 'process'] as const
type TimelineType = (typeof TIMELINE_TYPES)[number]

interface TimelineEvent {
  dateType: string
  year?: number
  month?: string
  day?: number
  endYear?: number
  endMonth?: string
  ongoing?: boolean
  customDate?: string
  title: string
  subtitle?: string
  description?: unknown
  shortDescription?: string
  image?: Media | number
  gallery?: Array<{ image: Media | number; caption?: string }>
  category?: string
  importance?: string
  icon?: string
  color?: string
  links?: Array<{ label: string; url: string; type: string }>
  metadata?: unknown
}

// Helper to format date for display
function formatEventDate(event: TimelineEvent): string {
  const months = [
    '',
    'Januar',
    'Februar',
    'März',
    'April',
    'Mai',
    'Juni',
    'Juli',
    'August',
    'September',
    'Oktober',
    'November',
    'Dezember',
  ]

  switch (event.dateType) {
    case 'year':
      return event.year?.toString() || ''
    case 'monthYear':
      return `${months[parseInt(event.month || '0')]} ${event.year}`
    case 'fullDate':
      return `${event.day}. ${months[parseInt(event.month || '0')]} ${event.year}`
    case 'range': {
      const start = event.year?.toString() || ''
      const end = event.ongoing ? 'heute' : event.endYear?.toString() || ''
      return `${start} - ${end}`
    }
    case 'custom':
      return event.customDate || ''
    default:
      return event.year?.toString() || ''
  }
}

// Helper to get sortable date value
function getEventSortValue(event: TimelineEvent): number {
  const year = event.year || 0
  const month = parseInt(event.month || '1')
  const day = event.day || 1
  return year * 10000 + month * 100 + day
}

export async function GET(request: NextRequest) {
  try {
    // IP-Blocklist prüfen
    const ip = getClientIpFromRequest(request)
    if (isIpBlocked(ip)) {
      return NextResponse.json({ error: 'Access denied' }, { status: 403 })
    }

    // Rate limiting
    const rateLimit = await searchLimiter.check(ip)
    if (!rateLimit.allowed) {
      return NextResponse.json(
        { error: 'Too many requests. Please try again later.' },
        { status: 429, headers: rateLimitHeaders(rateLimit, TIMELINE_RATE_LIMIT) }
      )
    }

    // Parse query parameters
    const { searchParams } = new URL(request.url)

    const tenantParam = searchParams.get('tenant')
    const slugParam = searchParams.get('slug')?.trim()
    const typeParam = searchParams.get('type')?.trim()
    const localeParam = searchParams.get('locale')?.trim()
    const categoryParam = searchParams.get('category')?.trim()
    const importanceParam = searchParams.get('importance')?.trim()

    // Validate tenant - REQUIRED for tenant isolation
    if (!tenantParam) {
      return NextResponse.json(
        { error: 'Tenant ID is required. Use ?tenant=<id> to specify the tenant.' },
        { status: 400 }
      )
    }
    const tenantId = parseInt(tenantParam, 10)
    if (isNaN(tenantId) || tenantId < 1) {
      return NextResponse.json({ error: 'Invalid tenant ID' }, { status: 400 })
    }

    // Validate locale
    const validLocales: Locale[] = ['de', 'en']
    const locale: Locale = localeParam && validLocales.includes(localeParam as Locale) ? (localeParam as Locale) : 'de'

    // Validate type if provided
    if (typeParam && !TIMELINE_TYPES.includes(typeParam as TimelineType)) {
      return NextResponse.json(
        { error: `Invalid type. Must be one of: ${TIMELINE_TYPES.join(', ')}` },
        { status: 400 }
      )
    }

    // Build where clause
    const where: Where = {
      status: { equals: 'published' },
      tenant: { equals: tenantId },
    }

    // Filter by slug (single timeline)
    if (slugParam) {
      where.slug = { equals: slugParam }
    }

    // Filter by type
    if (typeParam) {
      where.type = { equals: typeParam }
    }

    // Get payload instance
    const payload = await getPayload({ config })

    // Execute query
    const result = await payload.find({
      collection: 'timelines',
      where: where as Where,
      sort: '-updatedAt',
      limit: slugParam ? 1 : 100, // Single or list
      locale,
      depth: 2, // Load media relations
    })

    if (slugParam && result.docs.length === 0) {
      return NextResponse.json({ error: 'Timeline not found' }, { status: 404 })
    }

    // Transform timelines
    const transformedDocs = result.docs.map((timeline) => {
      // Filter and sort events
      let events = (timeline.events || []) as TimelineEvent[]

      // Filter by category if specified
      if (categoryParam) {
        events = events.filter((e) => e.category === categoryParam)
      }

      // Filter by importance if specified
      if (importanceParam) {
        events = events.filter((e) => e.importance === importanceParam)
      }

      // Sort events based on display options
      const sortOrder = (timeline.displayOptions as { sortOrder?: string })?.sortOrder || 'desc'
      events.sort((a, b) => {
        const diff = getEventSortValue(a) - getEventSortValue(b)
        return sortOrder === 'desc' ? -diff : diff
      })

      // Group by year if enabled
      const groupByYear = (timeline.displayOptions as { groupByYear?: boolean })?.groupByYear
      let groupedEvents: Record<number, typeof transformedEvents> | null = null

      // Transform events
      const transformedEvents = events.map((event) => {
        const image = event.image as Media | null
        const gallery = (event.gallery || []).map((item) => {
          const galleryImage = item.image as Media | null
          return {
            url: galleryImage?.url || null,
            alt: galleryImage?.alt || '',
            caption: item.caption || null,
          }
        })

        return {
          dateDisplay: formatEventDate(event),
          dateType: event.dateType,
          year: event.year,
          month: event.month,
          day: event.day,
          endYear: event.endYear,
          endMonth: event.endMonth,
          ongoing: event.ongoing,
          customDate: event.customDate,
          title: event.title,
          subtitle: event.subtitle || null,
          description: event.description || null,
          shortDescription: event.shortDescription || null,
          image: image
            ? {
                url: image.url,
                alt: image.alt || event.title,
                width: image.width,
                height: image.height,
              }
            : null,
          gallery: gallery.length > 0 ? gallery : null,
          category: event.category || null,
          importance: event.importance || 'normal',
          icon: event.icon || null,
          color: event.color || null,
          links: event.links || [],
          metadata: event.metadata || null,
        }
      })

      // Group by year if enabled
      if (groupByYear) {
        groupedEvents = {}
        for (const event of transformedEvents) {
          const year = event.year || 0
          if (!groupedEvents[year]) {
            groupedEvents[year] = []
          }
          groupedEvents[year].push(event)
        }
      }

      return {
        id: timeline.id,
        name: timeline.name,
        slug: timeline.slug,
        description: timeline.description || null,
        type: timeline.type,
        displayOptions: timeline.displayOptions,
        events: groupByYear ? null : transformedEvents,
        eventsByYear: groupedEvents,
        eventCount: transformedEvents.length,
        seo: timeline.seo || null,
      }
    })

    // Single timeline response
    if (slugParam) {
      return NextResponse.json(
        {
          timeline: transformedDocs[0],
          locale,
        },
        {
          headers: {
            ...rateLimitHeaders(rateLimit, TIMELINE_RATE_LIMIT),
            'Cache-Control': 'public, max-age=60, s-maxage=300',
          },
        }
      )
    }

    // List response
    return NextResponse.json(
      {
        docs: transformedDocs,
        total: result.totalDocs,
        filters: {
          tenant: tenantId,
          type: typeParam || null,
          locale,
        },
      },
      {
        headers: {
          ...rateLimitHeaders(rateLimit, TIMELINE_RATE_LIMIT),
          'Cache-Control': 'public, max-age=60, s-maxage=120',
        },
      }
    )
  } catch (error) {
    console.error('[Timeline API] Error:', error)
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
  }
}
