import type { SegmentImportStatus } from '@/types/dataset'
import { fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { Plan } from '@/app/components/billing/type'
import { segmentImportStatus } from '@/types/dataset'

import { SegmentAdd } from '../index'

// Mock provider context
let mockPlan = { type: Plan.professional }
let mockEnableBilling = true
vi.mock('@/context/provider-context', () => ({
  useProviderContext: () => ({
    plan: mockPlan,
    enableBilling: mockEnableBilling,
  }),
}))

describe('SegmentAdd', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockPlan = { type: Plan.professional }
    mockEnableBilling = true
  })

  const defaultProps = {
    importStatus: undefined as SegmentImportStatus | undefined,
    clearImportStatus: vi.fn(),
    showNewSegmentModal: vi.fn(),
    showBatchModal: vi.fn(),
    embedding: false,
  }

  describe('Rendering', () => {
    it('should render without crashing', () => {
      const { container } = render(<SegmentAdd {...defaultProps} />)

      expect(container.firstChild).toBeInTheDocument()
    })

    it('should render add button when no importStatus', () => {
      render(<SegmentAdd {...defaultProps} />)

      expect(screen.getByText(/list\.action\.addButton/i)).toBeInTheDocument()
    })

    it('should render dropdown trigger for batch add', () => {
      render(<SegmentAdd {...defaultProps} />)

      expect(screen.getByRole('button', { name: /list\.action\.batchAdd/i })).toBeInTheDocument()
    })
  })

  // Import Status displays
  describe('Import Status Display', () => {
    it('should show processing indicator when status is WAITING', () => {
      render(<SegmentAdd {...defaultProps} importStatus={segmentImportStatus.waiting} />)

      expect(screen.getByText(/list\.batchModal\.processing/i)).toBeInTheDocument()
    })

    it('should show processing indicator when status is PROCESSING', () => {
      render(<SegmentAdd {...defaultProps} importStatus={segmentImportStatus.processing} />)

      expect(screen.getByText(/list\.batchModal\.processing/i)).toBeInTheDocument()
    })

    it('should show completed status with ok button', () => {
      render(<SegmentAdd {...defaultProps} importStatus={segmentImportStatus.completed} />)

      expect(screen.getByText(/list\.batchModal\.completed/i)).toBeInTheDocument()
      expect(screen.getByText(/list\.batchModal\.ok/i)).toBeInTheDocument()
    })

    it('should show error status with ok button', () => {
      render(<SegmentAdd {...defaultProps} importStatus={segmentImportStatus.error} />)

      expect(screen.getByText(/list\.batchModal\.error/i)).toBeInTheDocument()
      expect(screen.getByText(/list\.batchModal\.ok/i)).toBeInTheDocument()
    })

    it('should not show add button when importStatus is set', () => {
      render(<SegmentAdd {...defaultProps} importStatus={segmentImportStatus.processing} />)

      expect(screen.queryByText(/list\.action\.addButton/i)).not.toBeInTheDocument()
    })
  })

  describe('User Interactions', () => {
    it('should call showNewSegmentModal when add button is clicked', () => {
      const mockShowNewSegmentModal = vi.fn()
      render(<SegmentAdd {...defaultProps} showNewSegmentModal={mockShowNewSegmentModal} />)

      fireEvent.click(screen.getByText(/list\.action\.addButton/i))

      expect(mockShowNewSegmentModal).toHaveBeenCalledTimes(1)
    })

    it('should call clearImportStatus when ok is clicked on completed status', () => {
      const mockClearImportStatus = vi.fn()
      render(
        <SegmentAdd
          {...defaultProps}
          importStatus={segmentImportStatus.completed}
          clearImportStatus={mockClearImportStatus}
        />,
      )

      fireEvent.click(screen.getByRole('button', { name: /list\.batchModal\.ok/i }))

      expect(mockClearImportStatus).toHaveBeenCalledTimes(1)
    })

    it('should call clearImportStatus when ok is clicked on error status', () => {
      const mockClearImportStatus = vi.fn()
      render(
        <SegmentAdd
          {...defaultProps}
          importStatus={segmentImportStatus.error}
          clearImportStatus={mockClearImportStatus}
        />,
      )

      fireEvent.click(screen.getByRole('button', { name: /list\.batchModal\.ok/i }))

      expect(mockClearImportStatus).toHaveBeenCalledTimes(1)
    })

    it('should render batch add option in dropdown', async () => {
      render(<SegmentAdd {...defaultProps} />)

      fireEvent.click(screen.getByRole('button', { name: /list\.action\.batchAdd/i }))

      expect(await screen.findByRole('menuitem', { name: /list\.action\.batchAdd/i })).toBeInTheDocument()
    })

    it('should call showBatchModal when batch add is clicked', async () => {
      const mockShowBatchModal = vi.fn()
      render(<SegmentAdd {...defaultProps} showBatchModal={mockShowBatchModal} />)

      fireEvent.click(screen.getByRole('button', { name: /list\.action\.batchAdd/i }))
      fireEvent.click(await screen.findByRole('menuitem', { name: /list\.action\.batchAdd/i }))

      expect(mockShowBatchModal).toHaveBeenCalledTimes(1)
    })

    it('should show plan upgrade modal instead of batch modal for sandbox users', async () => {
      mockPlan = { type: Plan.sandbox }
      const mockShowBatchModal = vi.fn()
      render(<SegmentAdd {...defaultProps} showBatchModal={mockShowBatchModal} />)

      fireEvent.click(screen.getByRole('button', { name: /list\.action\.batchAdd/i }))
      fireEvent.click(await screen.findByRole('menuitem', { name: /list\.action\.batchAdd/i }))

      expect(screen.getByRole('dialog')).toBeInTheDocument()
      expect(mockShowBatchModal).not.toHaveBeenCalled()
    })
  })

  // Disabled state (embedding)
  describe('Embedding State', () => {
    it('should disable add button when embedding is true', () => {
      render(<SegmentAdd {...defaultProps} embedding={true} />)

      const addButton = screen.getByText(/list\.action\.addButton/i).closest('button')
      expect(addButton).toBeDisabled()
    })

    it('should disable batch menu trigger when embedding is true', () => {
      render(<SegmentAdd {...defaultProps} embedding={true} />)

      expect(screen.getByRole('button', { name: /list\.action\.batchAdd/i })).toBeDisabled()
    })

    it('should apply disabled styling when embedding is true', () => {
      const { container } = render(<SegmentAdd {...defaultProps} embedding={true} />)

      const wrapper = container.firstChild as HTMLElement
      expect(wrapper).toHaveClass('border-components-button-secondary-border-disabled')
    })
  })

  // Plan upgrade modal
  describe('Plan Upgrade Modal', () => {
    it('should show plan upgrade modal when sandbox user tries to add', () => {
      mockPlan = { type: Plan.sandbox }
      render(<SegmentAdd {...defaultProps} />)

      fireEvent.click(screen.getByText(/list\.action\.addButton/i))

      expect(screen.getByRole('dialog')).toBeInTheDocument()
    })

    it('should not call showNewSegmentModal for sandbox users', () => {
      mockPlan = { type: Plan.sandbox }
      const mockShowNewSegmentModal = vi.fn()
      render(<SegmentAdd {...defaultProps} showNewSegmentModal={mockShowNewSegmentModal} />)

      fireEvent.click(screen.getByText(/list\.action\.addButton/i))

      expect(mockShowNewSegmentModal).not.toHaveBeenCalled()
    })

    it('should allow add when billing is disabled regardless of plan', () => {
      mockPlan = { type: Plan.sandbox }
      mockEnableBilling = false
      const mockShowNewSegmentModal = vi.fn()
      render(<SegmentAdd {...defaultProps} showNewSegmentModal={mockShowNewSegmentModal} />)

      fireEvent.click(screen.getByText(/list\.action\.addButton/i))

      expect(mockShowNewSegmentModal).toHaveBeenCalledTimes(1)
    })

    it('should close plan upgrade modal when close button is clicked', () => {
      mockPlan = { type: Plan.sandbox }
      render(<SegmentAdd {...defaultProps} />)

      // Show modal
      fireEvent.click(screen.getByText(/list\.action\.addButton/i))
      expect(screen.getByRole('dialog')).toBeInTheDocument()

      fireEvent.click(screen.getByRole('button', { name: 'billing.triggerLimitModal.dismiss' }))

      expect(screen.queryByRole('dialog')).not.toBeInTheDocument()
    })
  })

  // Progress bar width tests
  describe('Progress Bar', () => {
    it('should show 3/12 width progress bar for WAITING status', () => {
      const { container } = render(<SegmentAdd {...defaultProps} importStatus={segmentImportStatus.waiting} />)

      const progressBar = container.querySelector('.w-3\\/12')
      expect(progressBar).toBeInTheDocument()
    })

    it('should show 2/3 width progress bar for PROCESSING status', () => {
      const { container } = render(<SegmentAdd {...defaultProps} importStatus={segmentImportStatus.processing} />)

      const progressBar = container.querySelector('.w-2\\/3')
      expect(progressBar).toBeInTheDocument()
    })
  })

  describe('Edge Cases', () => {
    it('should maintain structure when rerendered', () => {
      const { rerender } = render(<SegmentAdd {...defaultProps} />)

      rerender(<SegmentAdd {...defaultProps} embedding={true} />)

      const addButton = screen.getByText(/list\.action\.addButton/i).closest('button')
      expect(addButton).toBeDisabled()
    })

    it('should handle callback change', () => {
      const mockShowNewSegmentModal1 = vi.fn()
      const mockShowNewSegmentModal2 = vi.fn()
      const { rerender } = render(
        <SegmentAdd {...defaultProps} showNewSegmentModal={mockShowNewSegmentModal1} />,
      )

      rerender(<SegmentAdd {...defaultProps} showNewSegmentModal={mockShowNewSegmentModal2} />)
      fireEvent.click(screen.getByText(/list\.action\.addButton/i))

      expect(mockShowNewSegmentModal1).not.toHaveBeenCalled()
      expect(mockShowNewSegmentModal2).toHaveBeenCalledTimes(1)
    })
  })
})
