/**
 * E2E Tests für News API
 *
 * Testet die dedizierte News-API mit Tenant-Isolation und Filtering
 */

import { test, expect } from '@playwright/test'

// Test tenant ID (porwoll.de)
const TEST_TENANT_ID = 1

test.describe('News API - List Endpoint', () => {
  const newsEndpoint = '/api/news'

  test('GET /api/news requires tenant parameter', async ({ request }) => {
    const response = await request.get(newsEndpoint)

    expect(response.status()).toBe(400)

    const data = await response.json()
    expect(data).toHaveProperty('error')
    expect(data.error).toContain('Tenant ID is required')
  })

  test('GET /api/news returns 400 for invalid tenant ID', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=invalid`)

    expect(response.status()).toBe(400)

    const data = await response.json()
    expect(data).toHaveProperty('error')
    expect(data.error).toContain('Invalid tenant ID')
  })

  test('GET /api/news returns valid response structure with tenant', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}`)

    expect(response.ok()).toBe(true)

    const data = await response.json()

    // Validate response structure
    expect(data).toHaveProperty('docs')
    expect(data).toHaveProperty('pagination')
    expect(data).toHaveProperty('filters')

    expect(Array.isArray(data.docs)).toBe(true)
    expect(data.pagination).toHaveProperty('page')
    expect(data.pagination).toHaveProperty('limit')
    expect(data.pagination).toHaveProperty('totalPages')
    expect(data.pagination).toHaveProperty('totalDocs')
    expect(data.pagination).toHaveProperty('hasNextPage')
    expect(data.pagination).toHaveProperty('hasPrevPage')

    // Filters should contain tenant
    expect(data.filters).toHaveProperty('tenant')
    expect(data.filters.tenant).toBe(TEST_TENANT_ID)
  })

  test('GET /api/news validates type parameter', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}&type=invalid`)

    expect(response.status()).toBe(400)

    const data = await response.json()
    expect(data).toHaveProperty('error')
    expect(data.error).toContain('Invalid type')
  })

  test('GET /api/news accepts valid type parameter', async ({ request }) => {
    const validTypes = ['news', 'press', 'announcement', 'blog']

    for (const type of validTypes) {
      const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}&type=${type}`)

      expect(response.ok()).toBe(true)

      const data = await response.json()
      expect(data.filters.type).toBe(type)

      // All returned docs should match the type
      for (const doc of data.docs) {
        expect(doc.type).toBe(type)
      }
    }
  })

  test('GET /api/news supports multiple types', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}&types=news,blog`)

    expect(response.ok()).toBe(true)

    const data = await response.json()

    // All docs should be either news or blog
    for (const doc of data.docs) {
      expect(['news', 'blog']).toContain(doc.type)
    }
  })

  test('GET /api/news respects pagination parameters', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}&page=1&limit=5`)

    expect(response.ok()).toBe(true)

    const data = await response.json()
    expect(data.pagination.page).toBe(1)
    expect(data.pagination.limit).toBe(5)
    expect(data.docs.length).toBeLessThanOrEqual(5)
  })

  test('GET /api/news enforces max limit', async ({ request }) => {
    // Request more than max limit (50)
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}&limit=100`)

    expect(response.ok()).toBe(true)

    const data = await response.json()
    // Should cap at max limit
    expect(data.pagination.limit).toBeLessThanOrEqual(50)
  })

  test('GET /api/news includes categories when requested', async ({ request }) => {
    const response = await request.get(
      `${newsEndpoint}?tenant=${TEST_TENANT_ID}&includeCategories=true`
    )

    expect(response.ok()).toBe(true)

    const data = await response.json()
    expect(data).toHaveProperty('categories')
    expect(Array.isArray(data.categories)).toBe(true)

    // Each category should have id, name, slug
    for (const cat of data.categories) {
      expect(cat).toHaveProperty('id')
      expect(cat).toHaveProperty('name')
      expect(cat).toHaveProperty('slug')
    }
  })

  test('GET /api/news includes archive when requested', async ({ request }) => {
    const response = await request.get(
      `${newsEndpoint}?tenant=${TEST_TENANT_ID}&includeArchive=true`
    )

    expect(response.ok()).toBe(true)

    const data = await response.json()
    expect(data).toHaveProperty('archive')
    expect(Array.isArray(data.archive)).toBe(true)

    // Each archive entry should have year, months, total
    for (const entry of data.archive) {
      expect(entry).toHaveProperty('year')
      expect(entry).toHaveProperty('months')
      expect(entry).toHaveProperty('total')
      expect(Array.isArray(entry.months)).toBe(true)
    }
  })

  test('GET /api/news filters by featured', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}&featured=true`)

    expect(response.ok()).toBe(true)

    const data = await response.json()
    expect(data.filters.featured).toBe(true)

    // All docs should be featured
    for (const doc of data.docs) {
      expect(doc.isFeatured).toBe(true)
    }
  })

  test('GET /api/news validates year parameter', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}&year=1900`)

    expect(response.status()).toBe(400)

    const data = await response.json()
    expect(data.error).toContain('Invalid year')
  })

  test('GET /api/news validates month parameter', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}&month=13`)

    expect(response.status()).toBe(400)

    const data = await response.json()
    expect(data.error).toContain('Invalid month')
  })

  test('GET /api/news accepts valid locale parameter', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}&locale=en`)

    expect(response.ok()).toBe(true)

    const data = await response.json()
    expect(data.filters.locale).toBe('en')
  })

  test('GET /api/news doc items have correct structure', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}`)

    expect(response.ok()).toBe(true)

    const data = await response.json()

    for (const doc of data.docs) {
      expect(doc).toHaveProperty('id')
      expect(doc).toHaveProperty('title')
      expect(doc).toHaveProperty('slug')
      expect(doc).toHaveProperty('type')
      expect(doc).toHaveProperty('excerpt')
      expect(doc).toHaveProperty('publishedAt')
      expect(doc).toHaveProperty('isFeatured')
      expect(doc).toHaveProperty('featuredImage')
      expect(doc).toHaveProperty('categories')
      expect(doc).toHaveProperty('seo')

      // Categories should be an array
      expect(Array.isArray(doc.categories)).toBe(true)
    }
  })

  test('GET /api/news includes rate limit headers', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}`)

    expect(response.ok()).toBe(true)

    const headers = response.headers()
    expect(headers['x-ratelimit-remaining']).toBeDefined()
  })

  test('GET /api/news includes cache headers', async ({ request }) => {
    const response = await request.get(`${newsEndpoint}?tenant=${TEST_TENANT_ID}`)

    expect(response.ok()).toBe(true)

    const headers = response.headers()
    expect(headers['cache-control']).toBeDefined()
    expect(headers['cache-control']).toContain('max-age')
  })
})

test.describe('News API - Detail Endpoint', () => {
  test('GET /api/news/[slug] requires tenant parameter', async ({ request }) => {
    const response = await request.get('/api/news/some-article')

    expect(response.status()).toBe(400)

    const data = await response.json()
    expect(data).toHaveProperty('error')
    expect(data.error).toContain('Tenant ID is required')
  })

  test('GET /api/news/[slug] returns 404 for non-existent article', async ({ request }) => {
    const response = await request.get(
      `/api/news/non-existent-article-slug-12345?tenant=${TEST_TENANT_ID}`
    )

    expect(response.status()).toBe(404)

    const data = await response.json()
    expect(data).toHaveProperty('error')
    expect(data.error).toContain('not found')
  })

  test('GET /api/news/[slug] returns valid article structure', async ({ request }) => {
    // First get a list to find a valid slug
    const listResponse = await request.get(`/api/news?tenant=${TEST_TENANT_ID}&limit=1`)

    if (!listResponse.ok()) {
      test.skip()
      return
    }

    const listData = await listResponse.json()

    if (listData.docs.length === 0) {
      test.skip() // No articles to test with
      return
    }

    const slug = listData.docs[0].slug
    const response = await request.get(`/api/news/${slug}?tenant=${TEST_TENANT_ID}`)

    expect(response.ok()).toBe(true)

    const data = await response.json()

    expect(data).toHaveProperty('article')
    expect(data).toHaveProperty('locale')

    const article = data.article
    expect(article).toHaveProperty('id')
    expect(article).toHaveProperty('title')
    expect(article).toHaveProperty('slug')
    expect(article).toHaveProperty('type')
    expect(article).toHaveProperty('content')
    expect(article).toHaveProperty('seo')
  })

  test('GET /api/news/[slug] includes related posts by default', async ({ request }) => {
    // First get a list to find a valid slug
    const listResponse = await request.get(`/api/news?tenant=${TEST_TENANT_ID}&limit=1`)

    if (!listResponse.ok()) {
      test.skip()
      return
    }

    const listData = await listResponse.json()

    if (listData.docs.length === 0) {
      test.skip()
      return
    }

    const slug = listData.docs[0].slug
    const response = await request.get(`/api/news/${slug}?tenant=${TEST_TENANT_ID}`)

    expect(response.ok()).toBe(true)

    const data = await response.json()

    // Related posts may or may not exist, but structure should be valid
    if (data.relatedPosts) {
      expect(Array.isArray(data.relatedPosts)).toBe(true)

      for (const related of data.relatedPosts) {
        expect(related).toHaveProperty('id')
        expect(related).toHaveProperty('title')
        expect(related).toHaveProperty('slug')
        expect(related).toHaveProperty('type')
      }
    }
  })

  test('GET /api/news/[slug] includes navigation', async ({ request }) => {
    // First get a list to find a valid slug
    const listResponse = await request.get(`/api/news?tenant=${TEST_TENANT_ID}&limit=1`)

    if (!listResponse.ok()) {
      test.skip()
      return
    }

    const listData = await listResponse.json()

    if (listData.docs.length === 0) {
      test.skip()
      return
    }

    const slug = listData.docs[0].slug
    const response = await request.get(`/api/news/${slug}?tenant=${TEST_TENANT_ID}`)

    expect(response.ok()).toBe(true)

    const data = await response.json()

    expect(data).toHaveProperty('navigation')
    expect(data.navigation).toHaveProperty('previous')
    expect(data.navigation).toHaveProperty('next')
  })

  test('GET /api/news/[slug] can exclude related posts', async ({ request }) => {
    const listResponse = await request.get(`/api/news?tenant=${TEST_TENANT_ID}&limit=1`)

    if (!listResponse.ok()) {
      test.skip()
      return
    }

    const listData = await listResponse.json()

    if (listData.docs.length === 0) {
      test.skip()
      return
    }

    const slug = listData.docs[0].slug
    const response = await request.get(
      `/api/news/${slug}?tenant=${TEST_TENANT_ID}&includeRelated=false`
    )

    expect(response.ok()).toBe(true)

    const data = await response.json()

    // Related posts should not be included
    expect(data.relatedPosts).toBeUndefined()
  })
})

test.describe('News API - Tenant Isolation', () => {
  test('Different tenants return isolated data', async ({ request }) => {
    // Get news for tenant 1
    const response1 = await request.get('/api/news?tenant=1')
    // Get news for tenant 4 (C2S)
    const response4 = await request.get('/api/news?tenant=4')

    expect(response1.ok()).toBe(true)
    expect(response4.ok()).toBe(true)

    const data1 = await response1.json()
    const data4 = await response4.json()

    // Both should have valid structure
    expect(data1).toHaveProperty('docs')
    expect(data4).toHaveProperty('docs')

    // Filter responses should reflect tenant
    expect(data1.filters.tenant).toBe(1)
    expect(data4.filters.tenant).toBe(4)
  })

  test('Cannot access news from non-existent tenant', async ({ request }) => {
    const response = await request.get('/api/news?tenant=99999')

    expect(response.ok()).toBe(true)

    const data = await response.json()

    // Should return empty results, not error
    expect(data.docs).toEqual([])
    expect(data.pagination.totalDocs).toBe(0)
  })
})
