/**
 * EnergyPage — device management UI for the Energy (Modbus) domain.
 *
 * Features:
 * - Device list with status indicators (enabled, last poll).
 * - Create / edit via DeviceForm modal.
 * - Delete with二次确认; 409 (has readings) → friendly prompt to disable instead.
 * - "Test read" button per device — calls POST /devices/{uuid}/test, shows
 *   decoded payload or error without persisting to the database.
 *
 * Out of scope (T07): readings cards, trend charts, Recharts import.
 */

import { useState } from 'react'
import {
  Container,
  Title,
  Table,
  Button,
  Group,
  Text,
  Loader,
  Center,
  Alert,
  Stack,
  Badge,
  ScrollArea,
  Modal,
  Code,
  Tooltip,
} from '@mantine/core'
import { useDevices, useDeleteDevice, useTestReadDevice } from '../energy/hooks'
import { DeviceForm } from '../energy/DeviceForm'
import type { ModbusDevice, ModbusTestReadResponse } from '../energy/hooks'
import { ApiError } from '../api/client'

// ---------------------------------------------------------------------------
// Delete confirmation modal (with 409 "disable instead" hint)
// ---------------------------------------------------------------------------

interface ConfirmDeleteProps {
  device: ModbusDevice
  onConfirm: () => void
  onCancel: () => void
  loading: boolean
  /** Set when the delete failed with 409. */
  has409Error: boolean
}

function ConfirmDeleteModal({ device, onConfirm, onCancel, loading, has409Error }: ConfirmDeleteProps) {
  return (
    <Modal
      opened
      onClose={onCancel}
      title="Confirm Delete"
      size="sm"
      data-testid="device-delete-modal"
    >
      <Stack gap="md">
        <Text data-testid="device-delete-message">
          Delete device <strong>{device.friendly_name}</strong>?
        </Text>

        {has409Error && (
          <Alert color="orange" data-testid="device-delete-409-hint">
            This device has existing readings and cannot be deleted. Consider{' '}
            <strong>disabling</strong> it instead (click Edit → uncheck Enabled).
          </Alert>
        )}

        <Group justify="flex-end" gap="sm">
          <Button variant="default" onClick={onCancel} data-testid="device-delete-cancel">
            Cancel
          </Button>
          <Button
            color="red"
            loading={loading}
            onClick={onConfirm}
            data-testid="device-delete-confirm"
          >
            Delete
          </Button>
        </Group>
      </Stack>
    </Modal>
  )
}

// ---------------------------------------------------------------------------
// Test-read result modal
// ---------------------------------------------------------------------------

interface TestResultModalProps {
  result: ModbusTestReadResponse
  deviceName: string
  onClose: () => void
}

function TestResultModal({ result, deviceName, onClose }: TestResultModalProps) {
  return (
    <Modal
      opened
      onClose={onClose}
      title={`Test read — ${deviceName}`}
      size="md"
      data-testid="test-read-modal"
    >
      {result.ok ? (
        <Stack gap="sm">
          <Badge color="green" data-testid="test-read-ok">Success</Badge>
          <Code block data-testid="test-read-payload">
            {JSON.stringify(result.payload, null, 2)}
          </Code>
        </Stack>
      ) : (
        <Stack gap="sm">
          <Badge color="red" data-testid="test-read-error-badge">Failed</Badge>
          <Text c="red" data-testid="test-read-error">
            {result.error ?? 'Unknown error'}
          </Text>
        </Stack>
      )}
      <Group justify="flex-end" mt="md">
        <Button variant="default" onClick={onClose}>
          Close
        </Button>
      </Group>
    </Modal>
  )
}

// ---------------------------------------------------------------------------
// Device row action: test-read button (self-contained per row)
// ---------------------------------------------------------------------------

interface TestReadButtonProps {
  device: ModbusDevice
}

function TestReadButton({ device }: TestReadButtonProps) {
  const testMutation = useTestReadDevice()
  const [result, setResult] = useState<ModbusTestReadResponse | null>(null)

  async function handleTest() {
    setResult(null)
    const res = await testMutation.mutateAsync(device.uuid)
    if (res.data) {
      setResult(res.data)
    }
  }

  return (
    <>
      <Tooltip label="Immediately read device (not saved)" position="top">
        <Button
          size="xs"
          variant="outline"
          color="blue"
          loading={testMutation.isPending}
          onClick={handleTest}
          data-testid={`device-test-${device.uuid}`}
        >
          Test read
        </Button>
      </Tooltip>

      {result && (
        <TestResultModal
          result={result}
          deviceName={device.friendly_name}
          onClose={() => setResult(null)}
        />
      )}
    </>
  )
}

// ---------------------------------------------------------------------------
// Device list table
// ---------------------------------------------------------------------------

interface DeviceTableProps {
  devices: ModbusDevice[]
  onEdit: (device: ModbusDevice) => void
  onDelete: (device: ModbusDevice) => void
}

function DeviceTable({ devices, onEdit, onDelete }: DeviceTableProps) {
  if (devices.length === 0) {
    return (
      <Text c="dimmed" ta="center" size="sm" data-testid="devices-empty">
        No devices configured yet. Click "New Device" to add one.
      </Text>
    )
  }

  return (
    <ScrollArea>
      <Table striped highlightOnHover withTableBorder data-testid="devices-table">
        <Table.Thead>
          <Table.Tr>
            <Table.Th>Name</Table.Th>
            <Table.Th>Host</Table.Th>
            <Table.Th>Port</Table.Th>
            <Table.Th>Unit ID</Table.Th>
            <Table.Th>Profile</Table.Th>
            <Table.Th>Poll (s)</Table.Th>
            <Table.Th>Status</Table.Th>
            <Table.Th style={{ textAlign: 'right' }}>Actions</Table.Th>
          </Table.Tr>
        </Table.Thead>
        <Table.Tbody>
          {devices.map((device) => (
            <Table.Tr key={device.uuid} data-testid={`device-row-${device.uuid}`}>
              <Table.Td>
                <Text fw={500} size="sm">
                  {device.friendly_name}
                </Text>
              </Table.Td>
              <Table.Td>{device.host}</Table.Td>
              <Table.Td>{device.port}</Table.Td>
              <Table.Td>{device.unit_id}</Table.Td>
              <Table.Td>
                <Badge variant="outline" size="sm">
                  {device.profile}
                </Badge>
              </Table.Td>
              <Table.Td>{device.poll_interval_s}</Table.Td>
              <Table.Td>
                <Group gap="xs">
                  <Badge color={device.enabled ? 'green' : 'gray'} variant="light" size="sm">
                    {device.enabled ? 'enabled' : 'disabled'}
                  </Badge>
                  {device.last_poll_ok !== null && (
                    <Badge
                      color={device.last_poll_ok ? 'teal' : 'red'}
                      variant="dot"
                      size="sm"
                    >
                      {device.last_poll_ok ? 'online' : 'offline'}
                    </Badge>
                  )}
                </Group>
              </Table.Td>
              <Table.Td>
                <Group justify="flex-end" gap="xs">
                  <TestReadButton device={device} />
                  <Button
                    size="xs"
                    variant="outline"
                    onClick={() => onEdit(device)}
                    data-testid={`device-edit-${device.uuid}`}
                  >
                    Edit
                  </Button>
                  <Button
                    size="xs"
                    variant="outline"
                    color="red"
                    onClick={() => onDelete(device)}
                    data-testid={`device-delete-${device.uuid}`}
                  >
                    Delete
                  </Button>
                </Group>
              </Table.Td>
            </Table.Tr>
          ))}
        </Table.Tbody>
      </Table>
    </ScrollArea>
  )
}

// ---------------------------------------------------------------------------
// EnergyPage — top-level
// ---------------------------------------------------------------------------

export function EnergyPage() {
  const devicesQuery = useDevices()
  const deleteMutation = useDeleteDevice()

  const [editDevice, setEditDevice] = useState<ModbusDevice | null>(null)
  const [showCreateForm, setShowCreateForm] = useState(false)
  const [deleteDevice, setDeleteDevice] = useState<ModbusDevice | null>(null)
  const [delete409, setDelete409] = useState(false)

  function openCreate() {
    setEditDevice(null)
    setShowCreateForm(true)
  }

  function openEdit(device: ModbusDevice) {
    setShowCreateForm(false)
    setEditDevice(device)
  }

  function openDelete(device: ModbusDevice) {
    setDeleteDevice(device)
    setDelete409(false)
  }

  function closeDelete() {
    setDeleteDevice(null)
    setDelete409(false)
  }

  async function handleDeleteConfirm() {
    if (!deleteDevice) return
    setDelete409(false)
    try {
      await deleteMutation.mutateAsync(deleteDevice.uuid)
      closeDelete()
    } catch (err) {
      if (err instanceof ApiError && err.status === 409) {
        setDelete409(true)
      }
      // Leave modal open so user sees the hint.
    }
  }

  // ---------------------------------------------------------------------------
  // Loading / error states
  // ---------------------------------------------------------------------------

  if (devicesQuery.isLoading) {
    return (
      <Center pt="xl" data-testid="energy-loading">
        <Loader />
      </Center>
    )
  }

  if (devicesQuery.isError || !devicesQuery.data) {
    return (
      <Container size="xl" pt="xl">
        <Alert color="red" data-testid="energy-load-error">
          Failed to load devices. Please refresh.
        </Alert>
      </Container>
    )
  }

  const devices = devicesQuery.data.items

  // ---------------------------------------------------------------------------
  // Main render
  // ---------------------------------------------------------------------------

  return (
    <Container size="xl" pt="xl" pb="xl" data-testid="energy-page">
      <Stack gap="lg">
        <Group justify="space-between" align="center">
          <Title order={2}>Energy — Devices</Title>
          <Button onClick={openCreate} data-testid="device-new-button">
            New Device
          </Button>
        </Group>

        <DeviceTable
          devices={devices}
          onEdit={openEdit}
          onDelete={openDelete}
        />
      </Stack>

      {/* Create form */}
      {showCreateForm && (
        <DeviceForm
          onClose={() => setShowCreateForm(false)}
          onSaved={() => setShowCreateForm(false)}
        />
      )}

      {/* Edit form */}
      {editDevice && (
        <DeviceForm
          device={editDevice}
          onClose={() => setEditDevice(null)}
          onSaved={() => setEditDevice(null)}
        />
      )}

      {/* Delete confirmation */}
      {deleteDevice && (
        <ConfirmDeleteModal
          device={deleteDevice}
          onConfirm={handleDeleteConfirm}
          onCancel={closeDelete}
          loading={deleteMutation.isPending}
          has409Error={delete409}
        />
      )}
    </Container>
  )
}
