import { render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, test } from 'vitest'
import { SkeletonLoader } from './skeleton-loader'
import { useWidgetStore } from '../stores/widget-store'

// Mock Skeleton component
function MockSkeleton() {
  return <div aria-label='Loading skeleton'>Loading...</div>
}

describe('SkeletonLoader', () => {
  const widgetId = 'test-skeleton-widget'

  beforeEach(() => {
    useWidgetStore.getState().clearWidgets()
  })

  describe('when isLoading is true', () => {
    test('renders skeleton component', () => {
      useWidgetStore.getState().setWidget(widgetId, { isLoading: true })

      render(
        <SkeletonLoader id={widgetId} Skeleton={MockSkeleton}>
          <div>Content</div>
        </SkeletonLoader>,
      )

      expect(screen.getByLabelText('Loading skeleton')).toBeTruthy()
      expect(screen.queryByText('Content')).toBeNull()
    })

    test('returns null when Skeleton prop is null', () => {
      useWidgetStore.getState().setWidget(widgetId, { isLoading: true })

      const { container } = render(
        <SkeletonLoader id={widgetId} Skeleton={null}>
          <div>Content</div>
        </SkeletonLoader>,
      )

      expect(container.firstChild).toBeNull()
    })
  })

  describe('when isLoading is false', () => {
    test('renders children', () => {
      useWidgetStore.getState().setWidget(widgetId, { isLoading: false })

      render(
        <SkeletonLoader id={widgetId} Skeleton={MockSkeleton}>
          <div>Content</div>
        </SkeletonLoader>,
      )

      expect(screen.getByText('Content')).toBeTruthy()
      expect(screen.queryByLabelText('Loading skeleton')).toBeNull()
    })
  })

  describe('when isLoading is undefined', () => {
    test('renders children', () => {
      useWidgetStore.getState().setWidget(widgetId, { isLoading: undefined })

      render(
        <SkeletonLoader id={widgetId} Skeleton={MockSkeleton}>
          <div>Content</div>
        </SkeletonLoader>,
      )

      expect(screen.getByText('Content')).toBeTruthy()
      expect(screen.queryByLabelText('Loading skeleton')).toBeNull()
    })
  })

  describe('when widget does not exist in store', () => {
    test('renders children (isLoading is undefined)', () => {
      render(
        <SkeletonLoader id='non-existent-widget' Skeleton={MockSkeleton}>
          <div>Content</div>
        </SkeletonLoader>,
      )

      expect(screen.getByText('Content')).toBeTruthy()
      expect(screen.queryByLabelText('Loading skeleton')).toBeNull()
    })
  })

  describe('reactivity to store changes', () => {
    test('updates from skeleton to content when isLoading becomes false', () => {
      useWidgetStore.getState().setWidget(widgetId, { isLoading: true })

      const { rerender } = render(
        <SkeletonLoader id={widgetId} Skeleton={MockSkeleton}>
          <div>Content</div>
        </SkeletonLoader>,
      )

      expect(screen.getByLabelText('Loading skeleton')).toBeTruthy()

      // Update store with isLoading false
      useWidgetStore.getState().setWidget(widgetId, { isLoading: false })

      // Force rerender to pick up store changes
      rerender(
        <SkeletonLoader id={widgetId} Skeleton={MockSkeleton}>
          <div>Content</div>
        </SkeletonLoader>,
      )

      expect(screen.queryByLabelText('Loading skeleton')).toBeNull()
      expect(screen.getByText('Content')).toBeTruthy()
    })

    test('updates from content to skeleton when isLoading becomes true', () => {
      useWidgetStore.getState().setWidget(widgetId, { isLoading: false })

      const { rerender } = render(
        <SkeletonLoader id={widgetId} Skeleton={MockSkeleton}>
          <div>Content</div>
        </SkeletonLoader>,
      )

      expect(screen.getByText('Content')).toBeTruthy()

      // Update store to isLoading true
      useWidgetStore.getState().setWidget(widgetId, { isLoading: true })

      // Force rerender to pick up store changes
      rerender(
        <SkeletonLoader id={widgetId} Skeleton={MockSkeleton}>
          <div>Content</div>
        </SkeletonLoader>,
      )

      expect(screen.getByLabelText('Loading skeleton')).toBeTruthy()
      expect(screen.queryByText('Content')).toBeNull()
    })
  })
})
