import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
import { render, screen, waitFor, fireEvent, cleanup } from '@testing-library/react'
import App from '../App'

const tasksResponse = {
  tasks: [
    { id: 't_1', title: 'Build thing', status: 'ready', assignee: 'developer', priority: 5, age: '1m' },
  ],
  groups: {
    triage: [],
    todo: [],
    ready: [{ id: 't_1', title: 'Build thing', status: 'ready', assignee: 'developer', priority: 5 }],
    running: [],
    blocked: [],
    done: [],
    archived: [],
  },
}

beforeEach(() => {
  vi.stubGlobal('fetch', vi.fn(async (url: string, init?: RequestInit) => {
    if (String(url).includes('/api/tasks/t_1/events')) return new Response(JSON.stringify({ events: [{ kind: 'created' }] }))
    if (String(url).includes('/api/tasks/t_1/runs')) return new Response(JSON.stringify({ runs: [{ id: 1, status: 'completed' }] }))
    if (String(url).includes('/api/tasks/t_1/log')) return new Response(JSON.stringify({ log: 'tail', missing: false }))
    if (String(url).endsWith('/api/tasks/t_1')) return new Response(JSON.stringify({ task: { ...tasksResponse.tasks[0], body: 'Full body' } }))
    if (String(url).includes('/api/tasks') && init?.method === 'POST') return new Response(JSON.stringify({ task: { id: 't_new', title: 'Created', status: 'todo' } }))
    if (String(url).includes('/api/tasks')) return new Response(JSON.stringify(tasksResponse))
    return new Response(JSON.stringify({ status: 'ok' }))
  }))
})

afterEach(() => {
  cleanup()
  vi.unstubAllGlobals()
})

describe('App', () => {
  it('renders board columns', async () => {
    render(<App />)
    expect(await screen.findByText('ready')).toBeInTheDocument()
    expect(screen.getByText('blocked')).toBeInTheDocument()
  })

  it('renders task cards with title status and assignee', async () => {
    render(<App />)
    expect(await screen.findByText('Build thing')).toBeInTheDocument()
    expect(screen.getByText('developer')).toBeInTheDocument()
  })

  it('opens detail drawer and shows body events and log sections', async () => {
    render(<App />)
    fireEvent.click(await screen.findByText('Build thing'))
    expect(await screen.findByText('Full body')).toBeInTheDocument()
    expect(screen.getByText('Events')).toBeInTheDocument()
    expect(screen.getByText('Log')).toBeInTheDocument()
  })

  it('create form validates title', async () => {
    render(<App />)
    fireEvent.click(await screen.findByText('Create task'))
    fireEvent.click(screen.getByText('Create'))
    expect(await screen.findByText('Title is required')).toBeInTheDocument()
  })

  it('shows API error state', async () => {
    vi.stubGlobal('fetch', vi.fn(async () => new Response(JSON.stringify({ detail: { message: 'boom' } }), { status: 500 })))
    render(<App />)
    expect(await screen.findByText(/boom/)).toBeInTheDocument()
  })

  it('does not crash when Telegram WebApp is absent', async () => {
    vi.stubGlobal('Telegram', undefined)
    render(<App />)
    await waitFor(() => expect(screen.getByText('Hermes Kanban')).toBeInTheDocument())
  })
})
