import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { http } from 'msw'
import { server } from '../../../../tests/msw/server'
import { jsonResponse } from '../../../../tests/msw/helpers'
import { renderWithProviders, screen, waitFor, userEvent } from '../../../../tests/helpers/render'
import { seedBearer, clearBearer } from '../../../../tests/helpers/auth'
import { AdminPage } from '..'

// v2 admin — GPS Device Link panel.
//
// AI and GPS share APPLY label; GPS is the SECOND APPLY in DOM order.

function gpsApplyButton(): HTMLElement {
  return screen.getAllByRole('button', { name: /apply/i })[1]
}

beforeEach(() => {
  seedBearer()
})
afterEach(() => {
  clearBearer()
})

describe('AdminPage — GPS Device Link', () => {
  it('renders initial settings + telemetry from GET /api/admin/gps-settings', async () => {
    renderWithProviders(<AdminPage />)
    expect(await screen.findByDisplayValue('192.168.1.100')).toBeInTheDocument()
    expect(screen.getByDisplayValue('9001')).toBeInTheDocument()
    expect(screen.getByText('UDP/192.168.1.100:9001')).toBeInTheDocument()
  })

  it('protocol segmented control switches active value and APPLY PATCHes', async () => {
    const calls: { body: unknown }[] = []
    server.use(
      http.patch('/api/admin/gps-settings', async ({ request }) => {
        const body = await request.json()
        calls.push({ body })
        return jsonResponse({
          settings: { ...(body as object), address: '192.168.1.100', port: 9001 },
          telemetry: { socket: 'UDP/192.168.1.100:9001', connected: true, fix: '3D', satellites: 11, hdop: 0.82, lastPacketMs: 12 },
        })
      }),
    )
    renderWithProviders(<AdminPage />)
    await screen.findByDisplayValue('192.168.1.100')

    const ubxBtn = screen.getByRole('button', { name: 'UBX' })
    await userEvent.click(ubxBtn)
    expect(ubxBtn).toHaveAttribute('aria-pressed', 'true')

    await userEvent.click(gpsApplyButton())

    await waitFor(() => expect(calls.length).toBe(1))
    expect((calls[0].body as { protocol: string }).protocol).toBe('UBX')
  })

  it('PING and RECONNECT fire their dedicated endpoints', async () => {
    let pingHits = 0
    let reconnectHits = 0
    server.use(
      http.post('/api/admin/gps-settings/ping', () => { pingHits += 1; return new Response(null, { status: 204 }) }),
      http.post('/api/admin/gps-settings/reconnect', () => {
        reconnectHits += 1
        return jsonResponse({
          settings: { address: '192.168.1.100', port: 9001, protocol: 'NMEA' },
          telemetry: { socket: 'UDP/192.168.1.100:9001', connected: true, fix: '3D', satellites: 11, hdop: 0.82, lastPacketMs: 0 },
        })
      }),
    )
    renderWithProviders(<AdminPage />)
    await screen.findByDisplayValue('192.168.1.100')

    await userEvent.click(screen.getByRole('button', { name: /^ping$/i }))
    await waitFor(() => expect(pingHits).toBe(1))

    await userEvent.click(screen.getByRole('button', { name: /reconnect/i }))
    await waitFor(() => expect(reconnectHits).toBe(1))
  })
})
