import '@testing-library/jest-dom'
import { axe, toHaveNoViolations } from 'jest-axe'
import { fireEvent } from '@testing-library/dom'
import { vi } from 'vitest'
import { createElementTest, BaseTestConfig } from '../../tests/test-framework'
import { CustomElementFor } from '../../tests/component-registry'
import './link'

expect.extend(toHaveNoViolations)

export interface LinkTestConfig extends BaseTestConfig {
  href?: string
  target?: string
  skin?: string
  variant?: string
  iconName?: string
  iconPosition?: string
  openInNewTab?: boolean
  external?: boolean
}

// Use shared framework
export const createLinkTest = async (config: LinkTestConfig = {}) => {
  const { container, element } = await createElementTest<
    CustomElementFor<'pkt-link'>,
    LinkTestConfig
  >('pkt-link', config)

  return {
    container,
    link: element,
  }
}

describe('PktLink', () => {
  describe('Rendering and basic functionality', () => {
    test('renders without errors', async () => {
      const { link } = await createLinkTest()

      expect(link).toBeInTheDocument()
      await link.updateComplete
      expect(link).toBeTruthy()
    })

    test('renders with correct structure', async () => {
      const { link } = await createLinkTest({
        href: 'https://example.com',
        content: 'Click me',
      })
      await link.updateComplete

      expect(link).toBeInTheDocument()
      const anchor = link.querySelector('a')
      expect(anchor).toBeInTheDocument()
      expect(anchor?.href).toBe('https://example.com/')
      expect(anchor?.textContent).toContain('Click me')
    })
  })

  describe('Properties and attributes', () => {
    test('applies default properties correctly', async () => {
      const { link } = await createLinkTest()
      await link.updateComplete

      expect(link.href).toBe('#')
      expect(link.external).toBe(false)
      expect(link.iconName).toBeUndefined()
      expect(link.target).toBe('_self')
    })

    test('sets href property correctly', async () => {
      const { link } = await createLinkTest({
        href: 'https://example.com',
      })
      await link.updateComplete

      expect(link.href).toBe('https://example.com')
      const anchor = link.querySelector('a')
      expect(anchor?.href).toBe('https://example.com/')
    })

    test('sets external property correctly', async () => {
      const { link } = await createLinkTest({
        href: 'https://example.com',
        external: true,
      })
      await link.updateComplete

      expect(link.external).toBe(true)
    })
  })

  describe('Icon functionality', () => {
    test('renders icon when iconName is provided', async () => {
      const { link } = await createLinkTest({
        href: '#',
        iconName: 'arrow-right',
      })
      await link.updateComplete

      const icon = link.querySelector('pkt-icon')
      expect(icon).toBeInTheDocument()
      expect(icon?.getAttribute('name')).toBe('arrow-right')
    })

    test('positions icon correctly', async () => {
      const { link } = await createLinkTest({
        href: '#',
        iconName: 'arrow-right',
        iconPosition: 'right',
      })
      await link.updateComplete

      const anchor = link.querySelector('a')
      expect(anchor?.classList.contains('pkt-link--icon-right')).toBe(true)
    })
  })

  describe('External link functionality', () => {
    test('applies external class and rel attribute', async () => {
      const { link } = await createLinkTest({
        href: 'https://example.com',
        external: true,
      })
      await link.updateComplete

      const anchor = link.querySelector('a')
      expect(anchor?.classList.contains('pkt-link--external')).toBe(true)
      expect(anchor?.rel).toBe('noopener noreferrer')
    })

    test('does not set rel attribute for internal links', async () => {
      const { link } = await createLinkTest({
        href: '/internal-page',
      })
      await link.updateComplete

      const anchor = link.querySelector('a')
      expect(anchor?.rel).toBe('')
    })
  })

  describe('Event handling', () => {
    test('handles click events', async () => {
      const { link } = await createLinkTest({
        href: '#test',
      })
      await link.updateComplete

      const anchor = link.querySelector('a')
      const clickHandler = vi.fn()
      anchor?.addEventListener('click', clickHandler)

      fireEvent.click(anchor!)
      expect(clickHandler).toHaveBeenCalled()
    })
  })

  describe('Dynamic updates', () => {
    test('updates href dynamically', async () => {
      const { link } = await createLinkTest({
        href: 'https://example.com',
      })
      await link.updateComplete

      link.href = 'https://updated.com'
      await link.updateComplete

      expect(link.href).toBe('https://updated.com')
      const anchor = link.querySelector('a')
      expect(anchor?.href).toBe('https://updated.com/')
    })

    test('updates external property dynamically', async () => {
      const { link } = await createLinkTest({
        href: 'https://example.com',
      })
      await link.updateComplete

      link.external = true
      await link.updateComplete

      expect(link.external).toBe(true)
      const anchor = link.querySelector('a')
      expect(anchor?.classList.contains('pkt-link--external')).toBe(true)
      expect(anchor?.rel).toBe('noopener noreferrer')
    })
  })

  describe('Accessibility', () => {
    test('basic link is accessible', async () => {
      const { container } = await createLinkTest({
        href: 'https://example.com',
        content: 'Accessible Link',
      })
      await new Promise((resolve) => setTimeout(resolve, 100))

      const results = await axe(container)
      expect(results).toHaveNoViolations()
    })
  })

  describe('Integration scenarios', () => {
    test('works with complex configurations', async () => {
      const { link } = await createLinkTest({
        href: 'https://external-site.com',
        iconName: 'external',
        iconPosition: 'right',
        external: true,
        target: '_blank',
        content: 'Complex External Link',
      })
      await link.updateComplete

      expect(link.href).toBe('https://external-site.com')
      expect(link.iconName).toBe('external')
      expect(link.external).toBe(true)
      expect(link.target).toBe('_blank')

      const anchor = link.querySelector('a')
      expect(anchor?.classList.contains('pkt-link--external')).toBe(true)
      expect(anchor?.classList.contains('pkt-link--icon-right')).toBe(true)
    })
  })
})
