// src/app/(frontend)/api/news/[slug]/route.ts
// Single news article detail with related posts

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

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

const NEWS_RATE_LIMIT = 30
const RELATED_POSTS_LIMIT = 4

interface RouteParams {
  params: Promise<{ slug: string }>
}

export async function GET(request: NextRequest, { params }: RouteParams) {
  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, NEWS_RATE_LIMIT) }
      )
    }

    // Get slug from params
    const { slug } = await params
    if (!slug) {
      return NextResponse.json({ error: 'Slug is required' }, { status: 400 })
    }

    // Parse query parameters
    const { searchParams } = new URL(request.url)
    const tenantParam = searchParams.get('tenant')
    const localeParam = searchParams.get('locale')?.trim()
    const includeRelated = searchParams.get('includeRelated') !== 'false' // Default true

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

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

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

    // Build where clause (tenant is now required)
    const where: Where = {
      slug: { equals: slug },
      status: { equals: 'published' },
      tenant: { equals: tenantId },
    }

    // Find the post
    const result = await payload.find({
      collection: 'posts',
      where,
      limit: 1,
      locale,
      depth: 2,
    })

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

    const post = result.docs[0] as Post
    const featuredImage = post.featuredImage as Media | null
    const ogImage = post.seo?.ogImage as Media | null
    const categories = (post.categories || []) as Category[]

    // Transform the main article
    const article = {
      id: post.id,
      title: post.title,
      slug: post.slug,
      type: post.type || 'blog',
      excerpt: post.excerpt || null,
      content: post.content, // Full rich text content
      author: post.author || null,
      publishedAt: post.publishedAt || null,
      isFeatured: post.isFeatured || false,
      featuredImage: featuredImage
        ? {
            url: featuredImage.url,
            alt: featuredImage.alt || post.title,
            width: featuredImage.width,
            height: featuredImage.height,
            sizes: featuredImage.sizes || null,
          }
        : null,
      categories: categories
        .filter((cat): cat is Category => cat !== null && typeof cat === 'object' && 'name' in cat)
        .map((cat) => ({
          id: cat.id,
          name: cat.name,
          slug: cat.slug,
        })),
      seo: {
        metaTitle: post.seo?.metaTitle || post.title,
        metaDescription: post.seo?.metaDescription || post.excerpt || null,
        ogImage: ogImage
          ? {
              url: ogImage.url,
              width: ogImage.width,
              height: ogImage.height,
            }
          : featuredImage
            ? {
                url: featuredImage.url,
                width: featuredImage.width,
                height: featuredImage.height,
              }
            : null,
      },
    }

    // Build response
    const response: Record<string, unknown> = {
      article,
      locale,
    }

    // Get related posts if requested (filtered by same type AND category for relevance)
    if (includeRelated && categories.length > 0) {
      const categoryIds = categories
        .filter((cat): cat is Category => cat !== null && typeof cat === 'object' && 'id' in cat)
        .map((cat) => cat.id)

      const relatedResult = await payload.find({
        collection: 'posts',
        where: {
          id: { not_equals: post.id },
          status: { equals: 'published' },
          type: { equals: post.type || 'blog' }, // Same type for better relevance
          categories: { in: categoryIds },
          tenant: { equals: tenantId }, // Tenant is now required
        },
        sort: '-publishedAt',
        limit: RELATED_POSTS_LIMIT,
        locale,
        depth: 1,
      })

      response.relatedPosts = relatedResult.docs.map((relatedPost: Post) => {
        const relatedImage = relatedPost.featuredImage as Media | null
        return {
          id: relatedPost.id,
          title: relatedPost.title,
          slug: relatedPost.slug,
          type: relatedPost.type || 'blog',
          excerpt: relatedPost.excerpt || null,
          publishedAt: relatedPost.publishedAt || null,
          featuredImage: relatedImage
            ? {
                url: relatedImage.url,
                alt: relatedImage.alt || relatedPost.title,
                width: relatedImage.width,
                height: relatedImage.height,
              }
            : null,
        }
      })
    }

    // Get previous and next posts for navigation (same tenant, same type for consistency)
    const [prevResult, nextResult] = await Promise.all([
      payload.find({
        collection: 'posts',
        where: {
          status: { equals: 'published' },
          type: { equals: post.type || 'blog' },
          tenant: { equals: tenantId },
          publishedAt: { less_than: post.publishedAt || new Date().toISOString() },
        },
        sort: '-publishedAt',
        limit: 1,
        locale,
        depth: 0,
      }),
      payload.find({
        collection: 'posts',
        where: {
          status: { equals: 'published' },
          type: { equals: post.type || 'blog' },
          tenant: { equals: tenantId },
          publishedAt: { greater_than: post.publishedAt || new Date().toISOString() },
        },
        sort: 'publishedAt',
        limit: 1,
        locale,
        depth: 0,
      }),
    ])

    response.navigation = {
      previous: prevResult.docs[0]
        ? {
            title: prevResult.docs[0].title,
            slug: prevResult.docs[0].slug,
          }
        : null,
      next: nextResult.docs[0]
        ? {
            title: nextResult.docs[0].title,
            slug: nextResult.docs[0].slug,
          }
        : null,
    }

    return NextResponse.json(response, {
      headers: {
        ...rateLimitHeaders(rateLimit, NEWS_RATE_LIMIT),
        'Cache-Control': 'public, max-age=60, s-maxage=300',
      },
    })
  } catch (error) {
    console.error('[News Detail API] Error:', error)
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
  }
}
