import { VueWrapper } from '@vue/test-utils'
import { ComponentPublicInstance } from 'vue'

export interface TestHelpers {
  findByText: (text: string) => HTMLElement | null
  findByTestId: (testId: string) => HTMLElement | null
  clickByText: (text: string) => Promise<void>
  clickByTestId: (testId: string) => Promise<void>
  fillByTestId: (testId: string, value: string) => Promise<void>
}

export function createTestHelpers(wrapper: VueWrapper<ComponentPublicInstance>): TestHelpers {
  return {
    findByText: (text: string) => {
      return wrapper.element.textContent?.includes(text) ? wrapper.element : null
    },
    findByTestId: (testId: string) => {
      return wrapper.element.querySelector(`[data-testid="${testId}"]`)
    },
    clickByText: async (text: string) => {
      const element = wrapper.element.textContent?.includes(text) ? wrapper.element : null
      if (element) {
        element.click()
        await wrapper.vm.$nextTick()
      }
    },
    clickByTestId: async (testId: string) => {
      const element = wrapper.element.querySelector(`[data-testid="${testId}"]`)
      if (element) {
        element.click()
        await wrapper.vm.$nextTick()
      }
    },
    fillByTestId: async (testId: string, value: string) => {
      const element = wrapper.element.querySelector(`[data-testid="${testId}"]`) as HTMLInputElement
      if (element) {
        element.value = value
        element.dispatchEvent(new Event('input', { bubbles: true }))
        await wrapper.vm.$nextTick()
      }
    },
  }
}

export function waitFor(condition: () => boolean, timeout = 5000): Promise<void> {
  return new Promise((resolve, reject) => {
    const startTime = Date.now()
    
    const check = () => {
      if (condition()) {
        resolve()
      } else if (Date.now() - startTime > timeout) {
        reject(new Error(`Timeout waiting for condition`))
      } else {
        setTimeout(check, 100)
      }
    }
    
    check()
  })
}
