/**
 * DsmrPanel — shows the latest parsed DSMR telegram (the source of our metering data).
 *
 * This is the "ground truth" view: it fetches GET /api/energy/dsmr/latest and
 * renders the full parsed frame as a key/value table, so you can confirm at a
 * glance whether DSMR ingest is actually landing data (without reading the DB).
 *
 * - Auto-refresh toggle (default on) so new telegrams appear without a manual reload.
 * - Loading / error / empty states; "empty" explains the likely cause.
 * - Null phase values are shown as "—" (kept verbatim in the payload).
 */

import { useState } from 'react'
import {
  Stack,
  Group,
  Text,
  Loader,
  Center,
  Alert,
  Paper,
  Table,
  ScrollArea,
  Switch,
  Divider,
  Badge,
} from '@mantine/core'
import { useDsmrLatest } from './hooks'
import { formatLocalDateTime } from '../utils/datetime'

/** Default auto-refresh interval (ms) — DSMR ingest stores ~one row per 10 s. */
const AUTO_REFRESH_INTERVAL_MS = 10_000

function formatValue(value: unknown): string {
  if (value === null || value === undefined) return '—'
  if (typeof value === 'object') return JSON.stringify(value)
  return String(value)
}

export function DsmrPanel() {
  const [autoRefresh, setAutoRefresh] = useState(true)
  const latestQuery = useDsmrLatest(
    autoRefresh ? { refetchIntervalMs: AUTO_REFRESH_INTERVAL_MS } : undefined,
  )

  return (
    <Stack gap="md" data-testid="dsmr-panel">
      <Group justify="space-between" align="center">
        <div>
          <Text fw={600}>Latest DSMR reading</Text>
          <Text size="xs" c="dimmed">
            The most recent parsed telegram persisted to <code>dsmr_reading</code>.
          </Text>
        </div>
        <Switch
          label="Auto-refresh"
          checked={autoRefresh}
          onChange={(e) => setAutoRefresh(e.currentTarget.checked)}
          size="sm"
          data-testid="dsmr-auto-refresh-switch"
        />
      </Group>

      <Divider />

      <DsmrContent
        isLoading={latestQuery.isLoading}
        isError={latestQuery.isError}
        data={latestQuery.data}
      />
    </Stack>
  )
}

interface DsmrContentProps {
  isLoading: boolean
  isError: boolean
  data:
    | { found: boolean; recorded_at?: string | null; payload?: Record<string, unknown> | null }
    | undefined
}

function DsmrContent({ isLoading, isError, data }: DsmrContentProps) {
  if (isLoading) {
    return (
      <Center py="xl" data-testid="dsmr-loading">
        <Loader />
      </Center>
    )
  }

  if (isError || !data) {
    return (
      <Alert color="red" data-testid="dsmr-error">
        Failed to load the latest DSMR reading.
      </Alert>
    )
  }

  if (!data.found || !data.payload) {
    return (
      <Alert color="gray" data-testid="dsmr-empty">
        No DSMR data yet. Enable <strong>DSMR ingest</strong> in Config, make sure MQTT
        is connected, and confirm the DSMR Reader is publishing to the configured topic
        (default <code>dsmr/json</code>). Rows are stored about once every 10 seconds.
      </Alert>
    )
  }

  const payload = data.payload
  const keys = Object.keys(payload).sort()

  return (
    <Stack gap="sm" data-testid="dsmr-data">
      <Group gap="xs">
        <Badge color="teal" variant="light">
          {keys.length} fields
        </Badge>
        {data.recorded_at && (
          <Text size="sm" c="dimmed" data-testid="dsmr-recorded-at">
            recorded at {formatLocalDateTime(data.recorded_at)}
          </Text>
        )}
      </Group>

      <Paper withBorder>
        <ScrollArea.Autosize mah={480}>
          <Table striped highlightOnHover withColumnBorders data-testid="dsmr-table">
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Field</Table.Th>
                <Table.Th>Value</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {keys.map((key) => (
                <Table.Tr key={key} data-testid={`dsmr-row-${key}`}>
                  <Table.Td>
                    <Text size="sm" ff="monospace">
                      {key}
                    </Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm">{formatValue(payload[key])}</Text>
                  </Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        </ScrollArea.Autosize>
      </Paper>
    </Stack>
  )
}
