import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
import { getWeatherData } from '../mission-planner/src/services/WeatherService'

// AZ-499 — mission-planner WeatherService env-var hardening.
//
// Lives under tests/ (Blackbox-Tests-owned) rather than colocated under
// mission-planner/ because mission-planner does not have its own runner;
// the suite Vitest config already includes mission-planner/src in coverage
// and tsconfig.test.json picks up tests/** for type-check (STC-T1).

type FetchMock = ReturnType<typeof vi.fn>

describe('AZ-499 — mission-planner getWeatherData (env vars + fail-soft)', () => {
  let fetchMock: FetchMock

  beforeEach(() => {
    fetchMock = vi.fn(async () =>
      new Response(JSON.stringify({ wind: { speed: 5, deg: 90 } }), { status: 200 }),
    )
    vi.spyOn(globalThis, 'fetch').mockImplementation(fetchMock)
  })

  afterEach(() => {
    vi.restoreAllMocks()
    vi.unstubAllEnvs()
  })

  it('AC-1: env-var resolved API key reaches the outgoing fetch URL', async () => {
    // Arrange
    vi.stubEnv('VITE_OWM_API_KEY', 'abc123')
    vi.stubEnv('VITE_OWM_BASE_URL', '')

    // Act
    await getWeatherData(50, 30)

    // Assert
    expect(fetchMock).toHaveBeenCalledTimes(1)
    const url = String(fetchMock.mock.calls[0][0])
    expect(url).toContain('appid=abc123')
    expect(url).toContain('units=metric')
  })

  it('AC-2: env-var resolved base URL prefixes the outgoing fetch URL', async () => {
    // Arrange
    vi.stubEnv('VITE_OWM_API_KEY', 'abc123')
    vi.stubEnv('VITE_OWM_BASE_URL', 'https://example.test/data/2.5')

    // Act
    await getWeatherData(50, 30)

    // Assert
    const url = String(fetchMock.mock.calls[0][0])
    expect(url.startsWith('https://example.test/data/2.5/weather?')).toBe(true)
  })

  it('AC-2: trailing slash on env base URL is stripped', async () => {
    // Arrange
    vi.stubEnv('VITE_OWM_API_KEY', 'abc123')
    vi.stubEnv('VITE_OWM_BASE_URL', 'https://example.test/data/2.5/')

    // Act
    await getWeatherData(50, 30)

    // Assert
    const url = String(fetchMock.mock.calls[0][0])
    expect(url.startsWith('https://example.test/data/2.5/weather?')).toBe(true)
  })

  it('AC-3: returns null and issues no fetch when VITE_OWM_API_KEY is unset', async () => {
    // Arrange
    vi.stubEnv('VITE_OWM_API_KEY', '')

    // Act
    const result = await getWeatherData(50, 30)

    // Assert
    expect(result).toBeNull()
    expect(fetchMock).not.toHaveBeenCalled()
  })

  it('AC-4: defaults to public OWM base URL when only VITE_OWM_BASE_URL is unset', async () => {
    // Arrange
    vi.stubEnv('VITE_OWM_API_KEY', 'abc123')
    vi.stubEnv('VITE_OWM_BASE_URL', '')

    // Act
    await getWeatherData(50, 30)

    // Assert
    const url = String(fetchMock.mock.calls[0][0])
    expect(url.startsWith('https://api.openweathermap.org/data/2.5/weather?')).toBe(true)
  })

  it('returns the parsed wind shape on a successful response', async () => {
    // Arrange
    vi.stubEnv('VITE_OWM_API_KEY', 'abc123')

    // Act
    const result = await getWeatherData(50, 30)

    // Assert
    expect(result).toEqual({ windSpeed: 5, windAngle: 90 })
  })

  it('returns null when fetch rejects (network error fail-soft)', async () => {
    // Arrange
    vi.stubEnv('VITE_OWM_API_KEY', 'abc123')
    fetchMock.mockRejectedValueOnce(new Error('boom'))

    // Act
    const result = await getWeatherData(50, 30)

    // Assert
    expect(result).toBeNull()
  })
})
