import { getPayload, Payload } from 'payload'
import config from '@/payload.config'

import { describe, it, beforeAll, afterAll, expect } from 'vitest'

let payload: Payload
let testTenantId: number
let testVideoId: number
let testCategoryId: number

describe('Videos Collection API', () => {
  beforeAll(async () => {
    const payloadConfig = await config
    payload = await getPayload({ config: payloadConfig })

    // Find or use existing tenant for testing
    const tenants = await payload.find({
      collection: 'tenants',
      limit: 1,
    })

    if (tenants.docs.length > 0) {
      testTenantId = tenants.docs[0].id as number
    } else {
      // Create a test tenant if none exists
      const tenant = await payload.create({
        collection: 'tenants',
        data: {
          name: 'Test Tenant for Videos',
          slug: 'test-videos-tenant',
          domains: [{ domain: 'test-videos.local' }],
        },
      })
      testTenantId = tenant.id as number
    }
  })

  afterAll(async () => {
    // Cleanup: Delete test video and category if created
    if (testVideoId) {
      try {
        await payload.delete({
          collection: 'videos',
          id: testVideoId,
        })
      } catch {
        // Ignore if already deleted
      }
    }
    if (testCategoryId) {
      try {
        await payload.delete({
          collection: 'video-categories',
          id: testCategoryId,
        })
      } catch {
        // Ignore if already deleted
      }
    }
  })

  describe('VideoCategories CRUD', () => {
    it('creates a video category', async () => {
      const category = await payload.create({
        collection: 'video-categories',
        data: {
          name: 'Test Category',
          slug: 'test-category-' + Date.now(),
          tenant: testTenantId,
          isActive: true,
        },
      })

      expect(category).toBeDefined()
      expect(category.id).toBeDefined()
      expect(category.name).toBe('Test Category')
      testCategoryId = category.id as number
    })

    it('finds video categories', async () => {
      const categories = await payload.find({
        collection: 'video-categories',
        where: {
          tenant: { equals: testTenantId },
        },
      })

      expect(categories).toBeDefined()
      expect(categories.docs).toBeInstanceOf(Array)
      expect(categories.docs.length).toBeGreaterThan(0)
    })

    it('updates a video category', async () => {
      const updated = await payload.update({
        collection: 'video-categories',
        id: testCategoryId,
        data: {
          name: 'Updated Category Name',
        },
      })

      expect(updated.name).toBe('Updated Category Name')
    })
  })

  describe('Videos CRUD', () => {
    it('creates a video with YouTube embed', async () => {
      const video = await payload.create({
        collection: 'videos',
        data: {
          title: 'Test Video',
          slug: 'test-video-' + Date.now(),
          tenant: testTenantId,
          source: 'youtube',
          embedUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
          status: 'draft',
        },
      })

      expect(video).toBeDefined()
      expect(video.id).toBeDefined()
      expect(video.title).toBe('Test Video')
      expect(video.source).toBe('youtube')
      // Check that videoId was extracted by hook
      expect(video.videoId).toBe('dQw4w9WgXcQ')
      testVideoId = video.id as number
    })

    it('creates a video with Vimeo embed', async () => {
      const video = await payload.create({
        collection: 'videos',
        data: {
          title: 'Test Vimeo Video',
          slug: 'test-vimeo-video-' + Date.now(),
          tenant: testTenantId,
          source: 'vimeo',
          embedUrl: 'https://vimeo.com/76979871',
          status: 'draft',
        },
      })

      expect(video).toBeDefined()
      expect(video.videoId).toBe('76979871')

      // Cleanup this extra video
      await payload.delete({
        collection: 'videos',
        id: video.id,
      })
    })

    it('finds videos by tenant', async () => {
      const videos = await payload.find({
        collection: 'videos',
        where: {
          tenant: { equals: testTenantId },
        },
      })

      expect(videos).toBeDefined()
      expect(videos.docs).toBeInstanceOf(Array)
      expect(videos.docs.length).toBeGreaterThan(0)
    })

    it('finds videos by status', async () => {
      const videos = await payload.find({
        collection: 'videos',
        where: {
          and: [{ tenant: { equals: testTenantId } }, { status: { equals: 'draft' } }],
        },
      })

      expect(videos).toBeDefined()
      expect(videos.docs.every((v) => v.status === 'draft')).toBe(true)
    })

    it('updates a video', async () => {
      const updated = await payload.update({
        collection: 'videos',
        id: testVideoId,
        data: {
          title: 'Updated Video Title',
          status: 'published',
        },
      })

      expect(updated.title).toBe('Updated Video Title')
      expect(updated.status).toBe('published')
    })

    it('associates video with category', async () => {
      const updated = await payload.update({
        collection: 'videos',
        id: testVideoId,
        data: {
          category: testCategoryId,
        },
      })

      expect(updated.category).toBeDefined()
    })

    it('finds video by slug', async () => {
      // First get the video to know its slug
      const video = await payload.findByID({
        collection: 'videos',
        id: testVideoId,
      })

      const found = await payload.find({
        collection: 'videos',
        where: {
          and: [{ tenant: { equals: testTenantId } }, { slug: { equals: video.slug } }],
        },
      })

      expect(found.docs.length).toBe(1)
      expect(found.docs[0].id).toBe(testVideoId)
    })
  })

  describe('Slug Validation', () => {
    it('prevents duplicate slugs within same tenant', async () => {
      // Get the existing video's slug
      const existingVideo = await payload.findByID({
        collection: 'videos',
        id: testVideoId,
      })

      // Try to create another video with the same slug
      await expect(
        payload.create({
          collection: 'videos',
          data: {
            title: 'Duplicate Slug Video',
            slug: existingVideo.slug,
            tenant: testTenantId,
            source: 'youtube',
            embedUrl: 'https://www.youtube.com/watch?v=abc123',
            status: 'draft',
          },
        })
      ).rejects.toThrow()
    })

    it('prevents duplicate category slugs within same tenant', async () => {
      // Get the existing category's slug
      const existingCategory = await payload.findByID({
        collection: 'video-categories',
        id: testCategoryId,
      })

      // Try to create another category with the same slug
      await expect(
        payload.create({
          collection: 'video-categories',
          data: {
            name: 'Duplicate Category',
            slug: existingCategory.slug,
            tenant: testTenantId,
          },
        })
      ).rejects.toThrow()
    })
  })

  describe('Video Deletion', () => {
    it('deletes a video', async () => {
      const deleted = await payload.delete({
        collection: 'videos',
        id: testVideoId,
      })

      expect(deleted.id).toBe(testVideoId)

      // Verify it's gone
      const found = await payload.find({
        collection: 'videos',
        where: {
          id: { equals: testVideoId },
        },
      })

      expect(found.docs.length).toBe(0)
      testVideoId = 0 // Mark as deleted so afterAll doesn't try again
    })

    it('deletes a video category', async () => {
      const deleted = await payload.delete({
        collection: 'video-categories',
        id: testCategoryId,
      })

      expect(deleted.id).toBe(testCategoryId)
      testCategoryId = 0 // Mark as deleted
    })
  })
})
