import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:usb_serial/usb_serial.dart';

import '../../../core/localization/app_localizations.dart';
import '../../../core/theme/app_theme.dart';
import '../../device/models/serial_config.dart';
import '../../device/providers/serial_provider.dart';
import '../../device/services/device_message.dart';
import '../../device/services/serial_port_service.dart';

/// 串口配置面板
///
/// 展示当前连接状态、可用设备列表、串口参数，并提供
/// 「刷新设备 / 连接 / 断开 / 测试」等操作。
class SerialConfigPanel extends ConsumerStatefulWidget {
  const SerialConfigPanel({super.key});

  @override
  ConsumerState<SerialConfigPanel> createState() => _SerialConfigPanelState();
}

class _SerialConfigPanelState extends ConsumerState<SerialConfigPanel> {
  List<UsbDevice> _devices = const [];
  UsbDevice? _selectedDevice;
  bool _loadingDevices = false;
  bool _operating = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) => _refreshDevices());
  }

  Future<void> _refreshDevices() async {
    setState(() => _loadingDevices = true);
    try {
      final service = ref.read(serialPortServiceProvider);
      final list = await service.listDevices();
      if (!mounted) return;
      setState(() {
        _devices = list;
        _loadingDevices = false;
        if (_selectedDevice == null && list.isNotEmpty) {
          _selectedDevice = list.first;
        }
      });
    } catch (e) {
      if (!mounted) return;
      setState(() => _loadingDevices = false);
      _showSnack('${AppLocalizations.of(context)?.scanFailed ?? '扫描设备失败'}: $e', AppTheme.errorColor);
    }
  }

  Future<void> _connect() async {
    final device = _selectedDevice;
    if (device == null) {
      _showSnack(AppLocalizations.of(context)?.selectSerialFirst ?? '请先选择串口设备', AppTheme.warningColor);
      return;
    }
    setState(() => _operating = true);
    final service = ref.read(serialPortServiceProvider);
    final config = ref.read(serialConfigProvider);
    final ok = await service.connect(device, config);
    if (!mounted) return;
    setState(() => _operating = false);
    _showSnack(
      ok ? (AppLocalizations.of(context)?.connectSuccess ?? '连接成功') : ('${AppLocalizations.of(context)?.connectFailed ?? '连接失败'}: ${service.lastError ?? (AppLocalizations.of(context)?.unknownError ?? '未知错误')}'),
      ok ? AppTheme.successColor : AppTheme.errorColor,
    );
  }

  Future<void> _disconnect() async {
    setState(() => _operating = true);
    final service = ref.read(serialPortServiceProvider);
    await service.disconnect();
    if (!mounted) return;
    setState(() => _operating = false);
    _showSnack(AppLocalizations.of(context)?.disconnected ?? '已断开串口', AppTheme.infoColor);
  }

  Future<void> _testConnection() async {
    final service = ref.read(serialPortServiceProvider);
    if (!service.isConnected) {
      _showSnack(AppLocalizations.of(context)?.connectFirst ?? '请先连接串口', AppTheme.warningColor);
      return;
    }
    final msgService = ref.read(deviceMessageServiceProvider);
    final ok = await msgService.send(DeviceMessage.request(
      messageId: msgService.nextId(),
      type: DeviceMessageType.deviceInfo,
      data: const <String, dynamic>{},
      needAck: true,
    ));
    if (!mounted) return;
    _showSnack(
      ok ? (AppLocalizations.of(context)?.sendTestFrame ?? '已发送测试查询') : (AppLocalizations.of(context)?.connectFailed ?? '发送失败'),
      ok ? AppTheme.successColor : AppTheme.errorColor,
    );
  }

  void _showSnack(String msg, Color color) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(msg), backgroundColor: color),
    );
  }

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context);
    final config = ref.watch(serialConfigProvider);
    final state = ref.watch(serialPortServiceProvider).state;
    return ListView(
      padding: const EdgeInsets.all(0),
      children: [
        _buildStatusCard(state, l10n),
        const SizedBox(height: 16),
        _buildDeviceCard(l10n),
        const SizedBox(height: 16),
        _buildParamCard(config, l10n),
        const SizedBox(height: 16),
        _buildActionRow(l10n),
      ],
    );
  }

  // -- 状态卡 ----------------------------------------------------------

  Widget _buildStatusCard(SerialConnectionState state, AppLocalizations? l10n) {
    final color = switch (state) {
      SerialConnectionState.connected => AppTheme.successColor,
      SerialConnectionState.connecting => AppTheme.warningColor,
      SerialConnectionState.error => AppTheme.errorColor,
      SerialConnectionState.disconnected => AppTheme.idleColor,
    };
    final text = switch (state) {
      SerialConnectionState.connected => l10n?.serialConnected ?? '已连接',
      SerialConnectionState.connecting => l10n?.serialConnecting ?? '连接中...',
      SerialConnectionState.error => l10n?.serialError ?? '错误',
      SerialConnectionState.disconnected => l10n?.serialDisconnected ?? '未连接',
    };
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: AppTheme.backgroundColor,
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: color.withValues(alpha: 0.4)),
      ),
      child: Row(
        children: [
          Container(
            width: 12,
            height: 12,
            decoration: BoxDecoration(color: color, shape: BoxShape.circle),
          ),
          const SizedBox(width: 12),
          Text('${l10n?.serialStatus ?? '串口状态'}: $text',
              style: TextStyle(
                color: AppTheme.textPrimary,
                fontSize: 16,
                fontWeight: FontWeight.w600,
              )),
        ],
      ),
    );
  }

  // -- 设备列表 --------------------------------------------------------

  Widget _buildDeviceCard(AppLocalizations? l10n) {
    return _SectionCard(
      title: l10n?.availableSerialDevices ?? '可用串口设备',
      trailing: TextButton.icon(
        onPressed: _loadingDevices ? null : _refreshDevices,
        icon: const Icon(Icons.refresh, size: 18),
        label: Text(l10n?.refresh ?? '刷新'),
      ),
      child: _loadingDevices
          ? const Padding(
              padding: EdgeInsets.all(24),
              child: Center(child: CircularProgressIndicator()),
            )
          : _devices.isEmpty
              ? _buildEmptyDevice()
              : Column(
                  children: _devices
                      .map((d) => _deviceTile(d))
                      .toList(growable: false),
                ),
    );
  }

  Widget _buildEmptyDevice() {
    final l10n = AppLocalizations.of(context);
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 8),
      child: Column(
        children: [
          Icon(Icons.usb_off, size: 40, color: AppTheme.idleColor),
          const SizedBox(height: 8),
          Text(l10n?.noSerialDevice ?? '未检测到 USB 串口设备',
              style: TextStyle(color: AppTheme.textSecondary)),
          const SizedBox(height: 4),
          Text(l10n?.serialDeviceHint ?? '请确认下位机已上电并通过 USB 接入设备',
              style: TextStyle(color: AppTheme.textSecondary, fontSize: 12)),
        ],
      ),
    );
  }

  Widget _deviceTile(UsbDevice d) {
    final selected = _selectedDevice == d;
    return InkWell(
      onTap: () => setState(() => _selectedDevice = d),
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
        decoration: BoxDecoration(
          color: selected
              ? AppTheme.primaryColor.withValues(alpha: 0.08)
              : Colors.transparent,
          border: Border(
            bottom: BorderSide(color: AppTheme.borderSubtle, width: 0.5),
          ),
        ),
        child: Row(
          children: [
            Icon(
              selected ? Icons.radio_button_checked : Icons.radio_button_off,
              color: selected ? AppTheme.primaryColor : AppTheme.idleColor,
              size: 20,
            ),
            const SizedBox(width: 12),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(SerialPortService.deviceLabel(d),
                      style: TextStyle(
                        color: AppTheme.textPrimary,
                        fontWeight: FontWeight.w500,
                      )),
                  const SizedBox(height: 2),
                  Text(
                    'VID: 0x${(d.vid ?? 0).toRadixString(16).toUpperCase()}  '
                    'PID: 0x${(d.pid ?? 0).toRadixString(16).toUpperCase()}',
                    style: TextStyle(
                        color: AppTheme.textSecondary, fontSize: 12),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  // -- 参数配置 --------------------------------------------------------

  Widget _buildParamCard(SerialConfig config, AppLocalizations? l10n) {
    return _SectionCard(
      title: l10n?.serialParams ?? '串口参数',
      child: Column(
        children: [
          _baudRateRow(config, l10n),
          _dropdownRow<int>(
            label: l10n?.dataBits ?? '数据位',
            value: config.dataBits,
            options: const [5, 6, 7, 8],
            display: (v) => '$v',
            onChanged: (v) => _updateConfig((c) => c.copyWith(dataBits: v)),
          ),
          _dropdownRow<int>(
            label: l10n?.stopBits ?? '停止位',
            value: config.stopBits,
            options: const [1, 2],
            display: (v) => '$v',
            onChanged: (v) => _updateConfig((c) => c.copyWith(stopBits: v)),
          ),
          _dropdownRow<SerialParity>(
            label: l10n?.parity ?? '校验位',
            value: config.parity,
            options: SerialParity.values,
            display: (v) => switch (v) {
              SerialParity.none => l10n?.parityNone ?? '无',
              SerialParity.odd => l10n?.parityOdd ?? '奇',
              SerialParity.even => l10n?.parityEven ?? '偶',
              SerialParity.mark => l10n?.parityMark ?? '标记',
              SerialParity.space => l10n?.paritySpace ?? '空',
            },
            onChanged: (v) => _updateConfig((c) => c.copyWith(parity: v)),
          ),
          _dropdownRow<SerialFlowControl>(
            label: l10n?.flowControl ?? '流控',
            value: config.flowControl,
            options: SerialFlowControl.values,
            display: (v) => switch (v) {
              SerialFlowControl.none => l10n?.parityNone ?? '无',
              SerialFlowControl.rtsCts => 'RTS/CTS',
              SerialFlowControl.xonXoff => 'XON/XOFF',
              SerialFlowControl.dtrDsr => 'DTR/DSR',
            },
            onChanged: (v) => _updateConfig((c) => c.copyWith(flowControl: v)),
          ),
          const SizedBox(height: 8),
          Align(
            alignment: Alignment.centerRight,
            child: Text(
              l10n?.autoSaveParams ?? '参数修改后自动保存',
              style: TextStyle(color: AppTheme.textSecondary, fontSize: 12),
            ),
          ),
        ],
      ),
    );
  }

  Widget _baudRateRow(SerialConfig config, AppLocalizations? l10n) {
    final ctrl = TextEditingController(text: config.baudRate.toString());
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Row(
        children: [
          SizedBox(
              width: 80,
              child:
                  Text(l10n?.baudRate ?? '波特率', style: TextStyle(color: AppTheme.textPrimary))),
          const SizedBox(width: 12),
          SizedBox(
            width: 140,
            child: TextField(
              controller: ctrl,
              keyboardType: TextInputType.number,
              inputFormatters: [FilteringTextInputFormatter.digitsOnly],
              decoration: const InputDecoration(
                isDense: true,
                contentPadding:
                    EdgeInsets.symmetric(horizontal: 12, vertical: 10),
                border: OutlineInputBorder(),
              ),
              onSubmitted: (v) => _applyBaudRate(v, config),
              onEditingComplete: () => _applyBaudRate(ctrl.text, config),
            ),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Wrap(
              spacing: 6,
              runSpacing: 6,
              children: SerialConfig.commonBaudRates
                  .map((b) => _baudChip(b, config.baudRate))
                  .toList(),
            ),
          ),
        ],
      ),
    );
  }

  Widget _baudChip(int baud, int current) {
    final selected = baud == current;
    return ChoiceChip(
      label: Text('$baud'),
      selected: selected,
      onSelected: (_) => _updateConfig((c) => c.copyWith(baudRate: baud)),
      labelStyle: TextStyle(
        color: selected ? Colors.white : AppTheme.textPrimary,
        fontSize: 12,
      ),
      selectedColor: AppTheme.primaryColor,
      backgroundColor: AppTheme.backgroundColor,
    );
  }

  Widget _dropdownRow<T>({
    required String label,
    required T value,
    required List<T> options,
    required String Function(T) display,
    required ValueChanged<T> onChanged,
  }) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Row(
        children: [
          SizedBox(
              width: 80,
              child: Text(label, style: TextStyle(color: AppTheme.textPrimary))),
          const SizedBox(width: 12),
          Expanded(
            child: DropdownButtonFormField<T>(
              value: value,
              isDense: true,
              decoration: const InputDecoration(
                isDense: true,
                contentPadding:
                    EdgeInsets.symmetric(horizontal: 12, vertical: 10),
                border: OutlineInputBorder(),
              ),
              items: options
                  .map((o) => DropdownMenuItem(
                        value: o,
                        child: Text(display(o)),
                      ))
                  .toList(),
              onChanged: (v) {
                if (v != null) onChanged(v);
              },
            ),
          ),
        ],
      ),
    );
  }

  void _applyBaudRate(String raw, SerialConfig config) {
    final v = int.tryParse(raw.trim());
    if (v == null || v <= 0) return;
    if (v == config.baudRate) return;
    _updateConfig((c) => c.copyWith(baudRate: v));
  }

  Future<void> _updateConfig(
      SerialConfig Function(SerialConfig) mutator) async {
    await ref.read(serialConfigProvider.notifier).update(mutator);
  }

  // -- 操作按钮 --------------------------------------------------------

  Widget _buildActionRow(AppLocalizations? l10n) {
    return Wrap(
      spacing: 12,
      runSpacing: 12,
      children: [
        ElevatedButton.icon(
          onPressed: _operating ? null : _connect,
          icon: const Icon(Icons.link),
          label: Text(l10n?.connect ?? '连接'),
        ),
        ElevatedButton.icon(
          onPressed:
              _operating ? null : _disconnect,
          style: ElevatedButton.styleFrom(backgroundColor: AppTheme.errorColor),
          icon: const Icon(Icons.link_off),
          label: Text(l10n?.disconnect ?? '断开'),
        ),
        OutlinedButton.icon(
          onPressed: _operating ? null : _testConnection,
          icon: const Icon(Icons.send),
          label: Text(l10n?.sendTestFrame ?? '发送测试帧'),
        ),
      ],
    );
  }
}

class _SectionCard extends StatelessWidget {
  final String title;
  final Widget? trailing;
  final Widget child;

  const _SectionCard({
    required this.title,
    required this.child,
    this.trailing,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: AppTheme.borderSubtle),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Row(
            children: [
              Expanded(
                child: Text(
                  title,
                  style: TextStyle(
                    color: AppTheme.textPrimary,
                    fontSize: 16,
                    fontWeight: FontWeight.w600,
                  ),
                ),
              ),
              ?trailing,
            ],
          ),
          const Divider(),
          child,
        ],
      ),
    );
  }
}
