/**
 * Tests for Tibber test button in ConfigPage.
 *
 * Coverage:
 * 1. Tibber test button appears when Tibber section is in config.
 * 2. Success tri-state shows green alert.
 * 3. Config-error tri-state shows orange alert.
 * 4. Failed tri-state shows red alert.
 */

import { describe, it, expect, vi, beforeEach } from 'vitest'
import { screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { renderWithProviders } from '../test-utils'

// ---------------------------------------------------------------------------
// Mock apiClient
// ---------------------------------------------------------------------------

const mockGet = vi.fn()
const mockPost = vi.fn()
const mockPut = vi.fn()

vi.mock('../api/client', () => ({
  default: {
    GET: (...args: unknown[]) => mockGet(...args),
    POST: (...args: unknown[]) => mockPost(...args),
    PUT: (...args: unknown[]) => mockPut(...args),
    PATCH: vi.fn(),
    DELETE: vi.fn(),
  },
  ApiError: class ApiError extends Error {
    status: number
    body: unknown
    constructor(status: number, body: unknown) {
      super(`API error ${status}`)
      this.name = 'ApiError'
      this.status = status
      this.body = body
    }
  },
  registerLoginRedirect: vi.fn(),
}))

// ---------------------------------------------------------------------------
// Fixtures
// ---------------------------------------------------------------------------

const CONFIG_WITH_TIBBER = {
  sections: [
    {
      name: 'Tibber',
      fields: [
        {
          env_name: 'TIBBER_TOKEN',
          label: 'Tibber API Token',
          secret: true,
          input_type: 'text',
          configured: true,
          value: null,
        },
      ],
    },
  ],
}

// ---------------------------------------------------------------------------
// Import component
// ---------------------------------------------------------------------------

import { ConfigPage } from './ConfigPage'

// ---------------------------------------------------------------------------
// Helper to suppress TOTP and Expose Settings sub-queries
// ---------------------------------------------------------------------------

function mockConfigDependencies() {
  mockGet.mockImplementation((path: string) => {
    if (path === '/api/config') {
      return Promise.resolve({ data: CONFIG_WITH_TIBBER })
    }
    if (path === '/api/expose') {
      return Promise.resolve({
        data: {
          catalog: [],
          mqtt_status: { connected: false, broker: null },
        },
      })
    }
    if (path === '/api/auth/totp/status') {
      return Promise.resolve({ data: { enabled: false } })
    }
    return Promise.resolve({ data: null })
  })
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

describe('ConfigPage — Tibber test button', () => {
  beforeEach(() => vi.clearAllMocks())

  it('renders Tibber test button when Tibber section is present', async () => {
    mockConfigDependencies()

    renderWithProviders(<ConfigPage />)

    await waitFor(() => {
      expect(screen.getByTestId('tibber-test-button')).toBeInTheDocument()
    })
  })

  it('shows success alert on successful Tibber test', async () => {
    const user = userEvent.setup()
    mockConfigDependencies()

    mockPost.mockImplementation((path: string) => {
      if (path === '/api/energy/tibber/test') {
        return Promise.resolve({
          data: {
            result: 'success',
            message: 'Connected to Tibber API',
            price: {
              starts_at: '2026-06-22T10:00:00Z',
              total: 0.1337,
              energy: 0.08,
              tax: 0.0537,
              currency: 'EUR',
              level: 'NORMAL',
            },
          },
        })
      }
      return Promise.resolve({ data: null })
    })

    renderWithProviders(<ConfigPage />)

    await waitFor(() => {
      expect(screen.getByTestId('tibber-test-button')).toBeInTheDocument()
    })

    await user.click(screen.getByTestId('tibber-test-button'))

    await waitFor(() => {
      expect(screen.getByTestId('tibber-result-success')).toBeInTheDocument()
    })

    expect(screen.getByTestId('tibber-result-success')).toHaveTextContent(
      'Tibber connection successful',
    )
  })

  it('shows config-error alert when Tibber is misconfigured', async () => {
    const user = userEvent.setup()
    mockConfigDependencies()

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const ApiErrorClass = (await import('../api/client')).ApiError as any
    mockPost.mockImplementation((path: string) => {
      if (path === '/api/energy/tibber/test') {
        throw new ApiErrorClass(400, {
          result: 'config-error',
          message: 'Tibber token not configured',
        })
      }
      return Promise.resolve({ data: null })
    })

    renderWithProviders(<ConfigPage />)

    await waitFor(() => {
      expect(screen.getByTestId('tibber-test-button')).toBeInTheDocument()
    })

    await user.click(screen.getByTestId('tibber-test-button'))

    await waitFor(() => {
      expect(screen.getByTestId('tibber-result-config-error')).toBeInTheDocument()
    })
  })

  it('shows failed alert when Tibber test fails', async () => {
    const user = userEvent.setup()
    mockConfigDependencies()

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const ApiErrorClass = (await import('../api/client')).ApiError as any
    mockPost.mockImplementation((path: string) => {
      if (path === '/api/energy/tibber/test') {
        throw new ApiErrorClass(500, {
          result: 'failed',
          message: 'Connection refused',
        })
      }
      return Promise.resolve({ data: null })
    })

    renderWithProviders(<ConfigPage />)

    await waitFor(() => {
      expect(screen.getByTestId('tibber-test-button')).toBeInTheDocument()
    })

    await user.click(screen.getByTestId('tibber-test-button'))

    await waitFor(() => {
      expect(screen.getByTestId('tibber-result-failed')).toBeInTheDocument()
    })
  })
})
