/**
 * DeviceForm — create / edit a Modbus device.
 *
 * Used for both new-device creation (no `device` prop) and editing an
 * existing device (pass `device` prop with current values).
 *
 * Profile list is fetched from GET /api/modbus/profiles and rendered as a
 * Select dropdown.  All other fields are inline inputs.
 */

import { useState } from 'react'
import {
  Modal,
  Stack,
  TextInput,
  NumberInput,
  Select,
  Switch,
  Button,
  Group,
  Alert,
  Loader,
  Center,
  Text,
} from '@mantine/core'
import { useProfiles, useCreateDevice, useUpdateDevice } from './hooks'
import type { ModbusDevice, ModbusDeviceCreate, ModbusDeviceUpdate } from './hooks'

// ---------------------------------------------------------------------------
// Props
// ---------------------------------------------------------------------------

interface DeviceFormProps {
  /** When provided, the form is in edit mode; otherwise create mode. */
  device?: ModbusDevice
  onClose: () => void
  onSaved: () => void
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

export function DeviceForm({ device, onClose, onSaved }: DeviceFormProps) {
  const isEdit = !!device

  // Form state — initialise from device if editing.
  const [friendlyName, setFriendlyName] = useState(device?.friendly_name ?? '')
  const [host, setHost] = useState(device?.host ?? '')
  const [port, setPort] = useState<number | string>(device?.port ?? 502)
  const [unitId, setUnitId] = useState<number | string>(device?.unit_id ?? 1)
  const [profile, setProfile] = useState<string | null>(device?.profile ?? null)
  const [pollIntervalS, setPollIntervalS] = useState<number | string>(device?.poll_interval_s ?? 5)
  const [enabled, setEnabled] = useState(device?.enabled ?? true)
  const [error, setError] = useState<string | null>(null)

  const profilesQuery = useProfiles()
  const createMutation = useCreateDevice()
  const updateMutation = useUpdateDevice()

  const isBusy = createMutation.isPending || updateMutation.isPending

  // Build select options from profiles response.
  const profileOptions =
    profilesQuery.data?.profiles.map((p) => ({
      value: p.name,
      label: `${p.name} — ${p.description}`,
    })) ?? []

  // In create mode, if no explicit selection has been made and profiles are loaded,
  // derive a default from the first available profile.  We avoid useEffect+setState
  // (causes cascading renders) by computing the effective value here instead.
  const effectiveProfile: string | null =
    profile !== null
      ? profile
      : !isEdit && profileOptions.length > 0
        ? profileOptions[0].value
        : null

  // ---------------------------------------------------------------------------
  // Validation
  // ---------------------------------------------------------------------------

  function validate(): string | null {
    if (!friendlyName.trim()) return 'Friendly name is required.'
    if (!host.trim()) return 'Host is required.'
    const portNum = Number(port)
    if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535)
      return 'Port must be an integer between 1 and 65535.'
    const unitNum = Number(unitId)
    if (!Number.isInteger(unitNum) || unitNum < 1 || unitNum > 247)
      return 'Unit ID must be an integer between 1 and 247.'
    if (!effectiveProfile) return 'Profile is required.'
    const pollNum = Number(pollIntervalS)
    if (!Number.isInteger(pollNum) || pollNum < 1)
      return 'Poll interval must be a positive integer (seconds).'
    return null
  }

  // ---------------------------------------------------------------------------
  // Submit
  // ---------------------------------------------------------------------------

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    setError(null)

    const validationError = validate()
    if (validationError) {
      setError(validationError)
      return
    }

    try {
      if (isEdit && device) {
        const body: ModbusDeviceUpdate = {
          friendly_name: friendlyName.trim(),
          host: host.trim(),
          port: Number(port),
          unit_id: Number(unitId),
          profile: effectiveProfile!,
          poll_interval_s: Number(pollIntervalS),
          enabled,
        }
        await updateMutation.mutateAsync({ uuid: device.uuid, body })
      } else {
        const body: ModbusDeviceCreate = {
          friendly_name: friendlyName.trim(),
          transport: 'tcp',
          host: host.trim(),
          port: Number(port),
          unit_id: Number(unitId),
          profile: effectiveProfile!,
          poll_interval_s: Number(pollIntervalS),
          enabled,
        }
        await createMutation.mutateAsync(body)
      }
      onSaved()
      onClose()
    } catch {
      setError('Failed to save device. Please try again.')
    }
  }

  // ---------------------------------------------------------------------------
  // Render
  // ---------------------------------------------------------------------------

  return (
    <Modal
      opened
      onClose={onClose}
      title={isEdit ? 'Edit Device' : 'New Device'}
      size="md"
      data-testid="device-form-modal"
    >
      {profilesQuery.isLoading && (
        <Center py="md">
          <Loader size="sm" />
        </Center>
      )}

      {profilesQuery.isError && (
        <Alert color="red" mb="sm" data-testid="profiles-load-error">
          Failed to load profiles. Cannot create device.
        </Alert>
      )}

      {!profilesQuery.isLoading && (
        <form onSubmit={handleSubmit} data-testid="device-form">
          <Stack gap="sm">
            {isEdit && (
              <Text size="xs" c="dimmed" data-testid="device-uuid-display">
                UUID: {device!.uuid}
              </Text>
            )}

            <TextInput
              label="Friendly name"
              required
              value={friendlyName}
              onChange={(e) => setFriendlyName(e.currentTarget.value)}
              data-testid="device-friendly-name"
            />

            <TextInput
              label="Host"
              description="Gateway IP address"
              required
              value={host}
              onChange={(e) => setHost(e.currentTarget.value)}
              data-testid="device-host"
            />

            <NumberInput
              label="Port"
              required
              min={1}
              max={65535}
              value={port}
              onChange={(val) => setPort(val)}
              data-testid="device-port"
            />

            <NumberInput
              label="Unit ID"
              description="Modbus slave address (Meter ID on device panel)"
              required
              min={1}
              max={247}
              value={unitId}
              onChange={(val) => setUnitId(val)}
              data-testid="device-unit-id"
            />

            <Select
              label="Profile"
              description="YAML device profile"
              required
              data={profileOptions}
              value={effectiveProfile}
              onChange={setProfile}
              data-testid="device-profile"
            />

            <NumberInput
              label="Poll interval (seconds)"
              required
              min={1}
              value={pollIntervalS}
              onChange={(val) => setPollIntervalS(val)}
              data-testid="device-poll-interval"
            />

            <Switch
              label="Enabled"
              description="Whether this device is polled"
              checked={enabled}
              onChange={(e) => setEnabled(e.currentTarget.checked)}
              data-testid="device-enabled"
            />

            {error && (
              <Alert color="red" data-testid="device-form-error">
                {error}
              </Alert>
            )}

            <Group justify="flex-end" gap="sm">
              <Button variant="default" onClick={onClose} data-testid="device-form-cancel">
                Cancel
              </Button>
              <Button type="submit" loading={isBusy} data-testid="device-form-submit">
                {isEdit ? 'Save' : 'Create'}
              </Button>
            </Group>
          </Stack>
        </form>
      )}
    </Modal>
  )
}
