import { describe, test, expect, beforeEach } from 'vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import { LockSelection, LOCK_SELECTION_TOOL_ID } from './lock-selection'
import { useWidgetStore } from '../../stores/widget-store'
import type { EchartWidgetData } from '../../echart/types'
import type { LockSelectionState } from './types'
import { WidgetLoader } from '../../loader/loader'

// Test data
const mockData: EchartWidgetData = [
  [
    { name: 'Electronics', value: 440 },
    { name: 'Clothing', value: 280 },
    { name: 'Books', value: 100 },
  ],
]

describe('LockSelection', () => {
  const widgetId = 'test-lock-selection'

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

  test('renders nothing when no selections', () => {
    const { container } = render(
      <LockSelection id={widgetId} selectedItems={[]} />,
    )

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

  test('renders lock button when there are selections', () => {
    render(<LockSelection id={widgetId} selectedItems={['Electronics']} />)

    const button = screen.getByRole('button')
    expect(button).toBeTruthy()
  })

  test('shows lock tooltip when unlocked', () => {
    render(<LockSelection id={widgetId} selectedItems={['Electronics']} />)

    const button = screen.getByRole('button', { name: 'Lock selection' })
    expect(button).toBeTruthy()
  })

  test('shows unlock tooltip when locked', () => {
    render(<LockSelection id={widgetId} selectedItems={['Electronics']} />)

    // Lock by clicking the button
    const button = screen.getByRole('button')
    fireEvent.click(button)

    const unlockedButton = screen.getByRole('button', {
      name: 'Unlock selection',
    })
    expect(unlockedButton).toBeTruthy()
  })

  test('toggles isLocked in tool state when clicked', () => {
    render(<LockSelection id={widgetId} selectedItems={['Electronics']} />)

    const button = screen.getByRole('button')
    fireEvent.click(button)

    const widget = useWidgetStore.getState().getWidget(widgetId)
    const tool = widget?.registeredTools?.find(
      (t) => t.id === LOCK_SELECTION_TOOL_ID,
    )
    expect(tool?.enabled).toBe(true)
  })

  test('filters data in store when locking', async () => {
    const selectedItems = ['Electronics']

    render(
      <WidgetLoader
        id={widgetId}
        type='test'
        data={mockData}
        isLoading={false}
        isFetching={false}
      >
        <LockSelection id={widgetId} selectedItems={selectedItems} />
      </WidgetLoader>,
    )

    const button = screen.getByRole('button')
    fireEvent.click(button)

    await useWidgetStore.getState().executeToolPipeline(widgetId, mockData)

    const widget = useWidgetStore.getState().getWidget(widgetId)
    expect(widget?.data).toEqual([[{ name: 'Electronics', value: 440 }]])
  })

  test('clears locked items when unlocking', () => {
    render(<LockSelection id={widgetId} selectedItems={['Electronics']} />)

    // Lock first
    const button = screen.getByRole('button')
    fireEvent.click(button)

    // Then unlock
    fireEvent.click(button)

    const widget = useWidgetStore.getState().getWidget(widgetId)
    const tool = widget?.registeredTools?.find(
      (t) => t.id === LOCK_SELECTION_TOOL_ID,
    )
    expect(tool?.enabled).toBe(false)
  })

  test('clears lock state when selectedItems becomes empty while locked', () => {
    // Simulate remount: isLocked persists in store but selectedItems is now empty
    useWidgetStore
      .getState()
      .setWidget(widgetId, { isLocked: true, lockedItems: ['Electronics'] })

    render(<LockSelection id={widgetId} selectedItems={[]} />)

    const widget = useWidgetStore.getState().getWidget(widgetId)
    expect((widget as LockSelectionState | undefined)?.isLocked).toBe(false)
    expect((widget as LockSelectionState | undefined)?.lockedItems).toEqual([])
  })

  test('has active state when locked', () => {
    render(<LockSelection id={widgetId} selectedItems={['Electronics']} />)

    const button = screen.getByRole('button')
    fireEvent.click(button)

    expect(button.getAttribute('data-active')).toBe('true')
  })

  test('has inactive state when unlocked', () => {
    render(<LockSelection id={widgetId} selectedItems={['Electronics']} />)

    const button = screen.getByRole('button')
    expect(button.getAttribute('data-active')).toBe('false')
  })

  test('uses custom labels', () => {
    render(
      <LockSelection
        id={widgetId}
        selectedItems={['Electronics']}
        labels={{
          lock: 'Bloquear selección',
          unlock: 'Desbloquear selección',
          ariaLabel: 'Toggle lock',
        }}
      />,
    )

    const button = screen.getByRole('button', { name: 'Toggle lock' })
    expect(button).toBeTruthy()
  })

  test('filters multiple series when locking', async () => {
    const multiSeriesData: EchartWidgetData = [
      [
        { name: 'Electronics', value: 440 },
        { name: 'Clothing', value: 280 },
      ],
      [
        { name: 'Electronics', value: 520 },
        { name: 'Clothing', value: 350 },
      ],
    ]
    const selectedItems = ['Electronics']

    render(
      <WidgetLoader
        id={widgetId}
        type='test'
        data={multiSeriesData}
        isLoading={false}
        isFetching={false}
      >
        <LockSelection id={widgetId} selectedItems={selectedItems} />
      </WidgetLoader>,
    )

    const button = screen.getByRole('button')
    fireEvent.click(button)

    await useWidgetStore
      .getState()
      .executeToolPipeline(widgetId, multiSeriesData)

    const widget = useWidgetStore.getState().getWidget(widgetId)
    expect(widget?.data).toEqual([
      [{ name: 'Electronics', value: 440 }],
      [{ name: 'Electronics', value: 520 }],
    ])
  })
})
