import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../l10n/app_localizations.dart';
import '../models/pen_tool.dart';
import '../models/pressure_curve.dart';
import '../providers/settings_provider.dart';
import '../screens/app_shell.dart' show exportDiagnosticPack;
import '../services/badnote_server_client.dart';
import '../services/vault_service.dart';
import '../services/webdav_sync_service.dart';
import '../utils/stroke_stabilizer.dart';

/// Material 3 settings screen for BadNote.
class SettingsScreen extends ConsumerWidget {
  const SettingsScreen({super.key, this.embeddedInShell = false});

  final bool embeddedInShell;

  void _showColorPicker(
    BuildContext context,
    Color current,
    ValueChanged<Color> onPicked,
  ) {
    Color pickerColor = current;
    showDialog(
      context: context,
      builder: (context) {
        final l = AppLocalizations.of(context);
        return AlertDialog(
          title: Text(l.pickColor),
          content: SingleChildScrollView(
            child: ColorPicker(
              pickerColor: pickerColor,
              onColorChanged: (color) => pickerColor = color,
            ),
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: Text(l.cancel),
            ),
            TextButton(
              onPressed: () {
                onPicked(pickerColor);
                Navigator.of(context).pop();
              },
              child: Text(l.ok),
            ),
          ],
        );
      },
    );
  }

  void _confirmClearData(BuildContext context, WidgetRef ref) {
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: Text(AppLocalizations.of(ctx).clearSettingsTitle),
        content: Text(AppLocalizations.of(ctx).settingsClearConfirmBody),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(ctx),
            child: Text(AppLocalizations.of(ctx).cancel),
          ),
          TextButton(
            onPressed: () {
              ref.read(settingsProvider).clearAllData();
              Navigator.pop(ctx);
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(
                    content: Text(AppLocalizations.of(context).settingsReset)),
              );
            },
            child: Text(AppLocalizations.of(ctx).clear),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final settings = ref.watch(settingsProvider);
    final colorScheme = Theme.of(context).colorScheme;

    return Scaffold(
      appBar: embeddedInShell
          ? AppBar(title: Text(AppLocalizations.of(context).settings))
          : AppBar(title: Text(AppLocalizations.of(context).settings)),
      body: ListView(
        children: [
          _SectionHeader(
            title: AppLocalizations.of(context).diagnosticsSection,
            icon: Icons.bug_report_outlined,
          ),
          ListTile(
            title: Text(AppLocalizations.of(context).diagnosticsExport),
            subtitle: Text(AppLocalizations.of(context).diagnosticsExportHint),
            trailing: const Icon(Icons.ios_share),
            onTap: () => exportDiagnosticPack(context),
          ),
          const Divider(),
          _SectionHeader(
            title: AppLocalizations.of(context).settingsDefaults,
            icon: Icons.tune,
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  AppLocalizations.of(context).settingsDefaultTool,
                  style: const TextStyle(fontWeight: FontWeight.w500),
                ),
                const SizedBox(height: 4),
                DropdownButtonFormField<PenTool>(
                  initialValue: settings.defaultTool,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    isDense: true,
                  ),
                  items: PenTool.values.map((tool) {
                    return DropdownMenuItem(
                      value: tool,
                      child: Text(tool.name),
                    );
                  }).toList(),
                  onChanged: (tool) {
                    if (tool != null) settings.setDefaultTool(tool);
                  },
                ),
                const SizedBox(height: 16),
                Text(
                  AppLocalizations.of(context).settingsDefaultColor,
                  style: const TextStyle(fontWeight: FontWeight.w500),
                ),
                const SizedBox(height: 4),
                Row(
                  children: [
                    MouseRegion(
                      cursor: SystemMouseCursors.click,
                      child: InkWell(
                        borderRadius: BorderRadius.circular(8),
                        onTap: () => _showColorPicker(
                          context,
                          settings.defaultColor,
                          settings.setDefaultColor,
                        ),
                        child: Container(
                          width: 40,
                          height: 40,
                          decoration: BoxDecoration(
                            color: settings.defaultColor,
                            borderRadius: BorderRadius.circular(8),
                            border: Border.all(color: colorScheme.outline),
                          ),
                        ),
                      ),
                    ),
                    const SizedBox(width: 12),
                    Text(
                      '#${settings.defaultColor.toARGB32().toRadixString(16).padLeft(8, '0').toUpperCase()}',
                      style: const TextStyle(fontFamily: 'monospace'),
                    ),
                  ],
                ),
                const SizedBox(height: 16),
                Text(
                  AppLocalizations.of(context).settingsDefaultWidth,
                  style: const TextStyle(fontWeight: FontWeight.w500),
                ),
                Slider(
                  value: settings.defaultStrokeWidth,
                  min: 1.0,
                  max: 20.0,
                  divisions: 19,
                  label: settings.defaultStrokeWidth.toStringAsFixed(1),
                  onChanged: settings.setDefaultStrokeWidth,
                ),
                const SizedBox(height: 16),
                Text(
                  AppLocalizations.of(context).settingsPressureCurve,
                  style: const TextStyle(fontWeight: FontWeight.w500),
                ),
                const SizedBox(height: 4),
                DropdownButtonFormField<PressureCurveType>(
                  initialValue: settings.defaultPressureCurve,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    isDense: true,
                  ),
                  items: PressureCurveType.values.map((curve) {
                    return DropdownMenuItem(
                      value: curve,
                      child: Text(curve.name),
                    );
                  }).toList(),
                  onChanged: (curve) {
                    if (curve != null) {
                      settings.setDefaultPressureCurve(curve);
                    }
                  },
                ),
                const SizedBox(height: 16),
                const Text(
                  'Stabilization',
                  style: TextStyle(fontWeight: FontWeight.w500),
                ),
                const SizedBox(height: 4),
                DropdownButtonFormField<StabilizationLevel>(
                  initialValue: settings.defaultStabilization,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    isDense: true,
                  ),
                  items: StabilizationLevel.values.map((level) {
                    return DropdownMenuItem(
                      value: level,
                      child: Text(level.name),
                    );
                  }).toList(),
                  onChanged: (level) {
                    if (level != null) settings.setDefaultStabilization(level);
                  },
                ),
              ],
            ),
          ),
          const Divider(),
          _SectionHeader(
            title: AppLocalizations.of(context).settingsAppearance,
            icon: Icons.palette,
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  AppLocalizations.of(context).settingsAppearance,
                  style: const TextStyle(fontWeight: FontWeight.w500),
                ),
                const SizedBox(height: 4),
                SegmentedButton<ThemeMode>(
                  segments: [
                    ButtonSegment(
                      value: ThemeMode.system,
                      label: Text(AppLocalizations.of(context).themeSystem),
                      icon: const Icon(Icons.brightness_auto),
                    ),
                    ButtonSegment(
                      value: ThemeMode.light,
                      label: Text(AppLocalizations.of(context).themeLight),
                      icon: const Icon(Icons.light_mode),
                    ),
                    ButtonSegment(
                      value: ThemeMode.dark,
                      label: Text(AppLocalizations.of(context).themeDark),
                      icon: const Icon(Icons.dark_mode),
                    ),
                  ],
                  selected: {settings.themeMode},
                  onSelectionChanged: (modes) {
                    settings.setThemeMode(modes.first);
                  },
                ),
                const SizedBox(height: 16),
                Text(
                  AppLocalizations.of(context).seedColorDesc,
                  style: const TextStyle(fontWeight: FontWeight.w500),
                ),
                const SizedBox(height: 4),
                Row(
                  children: [
                    MouseRegion(
                      cursor: SystemMouseCursors.click,
                      child: InkWell(
                        borderRadius: BorderRadius.circular(8),
                        onTap: () => _showColorPicker(
                          context,
                          settings.colorSchemeSeed,
                          settings.setColorSchemeSeed,
                        ),
                        child: Container(
                          width: 40,
                          height: 40,
                          decoration: BoxDecoration(
                            color: settings.colorSchemeSeed,
                            borderRadius: BorderRadius.circular(8),
                            border: Border.all(color: colorScheme.outline),
                          ),
                        ),
                      ),
                    ),
                    const SizedBox(width: 12),
                    Text(AppLocalizations.of(context).seedColorDesc),
                  ],
                ),
              ],
            ),
          ),
          const Divider(),
          _SectionHeader(
            title: AppLocalizations.of(context).vaultSection,
            icon: Icons.folder_special,
          ),
          const Padding(
            padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: _VaultSettings(),
          ),
          const Divider(),
          _SectionHeader(
            title: AppLocalizations.of(context).syncSection,
            icon: Icons.cloud_sync,
          ),
          const Padding(
            padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: _SyncSettings(),
          ),
          const Divider(),
          _SectionHeader(
            title: AppLocalizations.of(context).serverSection,
            icon: Icons.dns_outlined,
          ),
          const Padding(
            padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: _ServerSettings(),
          ),
          const Divider(),
          _SectionHeader(
            title: AppLocalizations.of(context).settingsAbout,
            icon: Icons.info,
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text(
                  'BadNote v0.1.0',
                  style: TextStyle(fontWeight: FontWeight.w500),
                ),
                const SizedBox(height: 4),
                Text(
                  'Local-first Surface Pen note-taking with PDF/PPT annotation. '
                  'OCR and search run entirely on your device.',
                  style: TextStyle(
                    fontSize: 13,
                    color: colorScheme.onSurfaceVariant,
                  ),
                ),
                const SizedBox(height: 16),
                OutlinedButton.icon(
                  onPressed: () => _confirmClearData(context, ref),
                  icon: const Icon(Icons.delete_forever, color: Colors.red),
                  label: const Text(
                    'Clear All Local Settings',
                    style: TextStyle(color: Colors.red),
                  ),
                ),
              ],
            ),
          ),
          const SizedBox(height: 32),
        ],
      ),
    );
  }
}

/// Shows the current vault folder path and lets the user re-pick it. Re-uses
/// the same `getDirectoryPath` flow as the first-run [VaultSetupScreen],
/// persisting the choice through [VaultService.setVaultRoot].
class _VaultSettings extends StatefulWidget {
  const _VaultSettings();

  @override
  State<_VaultSettings> createState() => _VaultSettingsState();
}

class _VaultSettingsState extends State<_VaultSettings> {
  VaultService? _vault;
  String? _path;
  bool _busy = false;

  @override
  void initState() {
    super.initState();
    _load();
  }

  Future<void> _load() async {
    final vault = await VaultService.getInstance();
    if (!mounted) return;
    setState(() {
      _vault = vault;
      _path = vault.vaultRoot;
    });
  }

  Future<void> _changeFolder() async {
    final vault = _vault;
    if (vault == null) return;
    final l = AppLocalizations.of(context);
    final messenger = ScaffoldMessenger.of(context);
    setState(() => _busy = true);
    try {
      final path = await FilePicker.platform.getDirectoryPath(
        dialogTitle: l.vaultSetupTitle,
        lockParentWindow: true,
      );
      if (path != null) {
        await vault.setVaultRoot(path);
        if (!mounted) return;
        setState(() => _path = path);
        messenger.showSnackBar(SnackBar(content: Text(l.vaultUpdated)));
      }
    } catch (e) {
      if (!mounted) return;
      messenger.showSnackBar(
        SnackBar(content: Text(l.vaultPickFailed(e.toString()))),
      );
    } finally {
      if (mounted) setState(() => _busy = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    final l = AppLocalizations.of(context);
    final colorScheme = Theme.of(context).colorScheme;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          l.vaultFolderLabel,
          style: const TextStyle(fontWeight: FontWeight.w500),
        ),
        const SizedBox(height: 4),
        Text(
          (_path == null || _path!.isEmpty) ? l.vaultNoneSelected : _path!,
          style: TextStyle(
            fontSize: 13,
            color: colorScheme.onSurfaceVariant,
          ),
        ),
        const SizedBox(height: 12),
        OutlinedButton.icon(
          onPressed: _busy ? null : _changeFolder,
          icon: const Icon(Icons.drive_folder_upload),
          label: Text(l.vaultChangeFolder),
        ),
      ],
    );
  }
}

/// WebDAV sync configuration + actions. Persists config through
/// [WebDavSyncService] (SharedPreferences-backed), exposes Test connection /
/// Sync now buttons, the last-synced time and last result, and an
/// "auto-sync on launch" toggle (default OFF). All network ops are
/// time-bounded inside the service and surface friendly errors here.
class _SyncSettings extends StatefulWidget {
  const _SyncSettings();

  @override
  State<_SyncSettings> createState() => _SyncSettingsState();
}

class _SyncSettingsState extends State<_SyncSettings> {
  WebDavSyncService? _sync;
  final _urlCtrl = TextEditingController();
  final _userCtrl = TextEditingController();
  final _passCtrl = TextEditingController();
  final _folderCtrl = TextEditingController();
  bool _autoSync = false;
  bool _busy = false;
  bool _testing = false;
  bool _obscure = true;
  DateTime? _lastSync;
  SyncResult? _lastResult;

  @override
  void initState() {
    super.initState();
    _load();
  }

  @override
  void dispose() {
    _urlCtrl.dispose();
    _userCtrl.dispose();
    _passCtrl.dispose();
    _folderCtrl.dispose();
    super.dispose();
  }

  Future<void> _load() async {
    final prefs = await SharedPreferences.getInstance();
    final sync = WebDavSyncService(prefs);
    if (!mounted) return;
    final c = sync.config;
    setState(() {
      _sync = sync;
      _urlCtrl.text = c.baseUrl;
      _userCtrl.text = c.username;
      _passCtrl.text = c.password;
      _folderCtrl.text = c.remoteRoot;
      _autoSync = c.autoSync;
      _lastSync = sync.lastSyncTime;
    });
  }

  WebDavConfig _currentConfig() => WebDavConfig(
        baseUrl: _urlCtrl.text,
        username: _userCtrl.text,
        password: _passCtrl.text,
        remoteRoot: _folderCtrl.text,
        autoSync: _autoSync,
      );

  Future<void> _save() async {
    final sync = _sync;
    if (sync == null) return;
    final l = AppLocalizations.of(context);
    final messenger = ScaffoldMessenger.of(context);
    await sync.saveConfig(_currentConfig());
    if (!mounted) return;
    messenger.showSnackBar(SnackBar(content: Text(l.syncSaved)));
  }

  Future<void> _testConnection() async {
    final sync = _sync;
    if (sync == null) return;
    final l = AppLocalizations.of(context);
    final messenger = ScaffoldMessenger.of(context);
    await sync.saveConfig(_currentConfig());
    setState(() => _testing = true);
    final client = sync.buildClient();
    try {
      if (client == null) {
        messenger.showSnackBar(SnackBar(content: Text(l.syncNotConfigured)));
        return;
      }
      await client.testConnection();
      if (!mounted) return;
      messenger.showSnackBar(SnackBar(content: Text(l.syncTestOk)));
    } catch (e) {
      if (!mounted) return;
      messenger
          .showSnackBar(SnackBar(content: Text(l.syncTestFailed(e.toString()))));
    } finally {
      client?.close();
      if (mounted) setState(() => _testing = false);
    }
  }

  Future<void> _syncNow() async {
    final sync = _sync;
    if (sync == null) return;
    final l = AppLocalizations.of(context);
    final messenger = ScaffoldMessenger.of(context);
    await sync.saveConfig(_currentConfig());
    final vault = await VaultService.getInstance();
    final root = vault.vaultRoot;
    if (root == null || root.isEmpty) {
      messenger.showSnackBar(SnackBar(content: Text(l.vaultNoneSelected)));
      return;
    }
    setState(() => _busy = true);
    final client = sync.buildClient();
    try {
      if (client == null) {
        messenger.showSnackBar(SnackBar(content: Text(l.syncNotConfigured)));
        return;
      }
      final result = await sync.syncNow(vaultRoot: root, client: client);
      if (!mounted) return;
      setState(() {
        _lastResult = result;
        _lastSync = sync.lastSyncTime;
      });
      messenger.showSnackBar(SnackBar(
        content: Text(result.ok
            ? l.syncResultSummary(
                result.uploaded, result.downloaded, result.conflicts)
            : l.syncFailed(result.error ?? '')),
      ));
    } finally {
      client?.close();
      if (mounted) setState(() => _busy = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    final l = AppLocalizations.of(context);
    final colorScheme = Theme.of(context).colorScheme;
    final configured = _urlCtrl.text.trim().isNotEmpty;
    final lastResult = _lastResult;

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        TextField(
          controller: _urlCtrl,
          keyboardType: TextInputType.url,
          autocorrect: false,
          decoration: InputDecoration(
            labelText: l.syncServerUrl,
            hintText: l.syncServerUrlHint,
            border: const OutlineInputBorder(),
            isDense: true,
          ),
          onChanged: (_) => setState(() {}),
        ),
        const SizedBox(height: 12),
        TextField(
          controller: _userCtrl,
          autocorrect: false,
          decoration: InputDecoration(
            labelText: l.syncUsername,
            border: const OutlineInputBorder(),
            isDense: true,
          ),
        ),
        const SizedBox(height: 12),
        TextField(
          controller: _passCtrl,
          obscureText: _obscure,
          autocorrect: false,
          decoration: InputDecoration(
            labelText: l.syncPassword,
            border: const OutlineInputBorder(),
            isDense: true,
            suffixIcon: IconButton(
              icon: Icon(_obscure ? Icons.visibility : Icons.visibility_off),
              onPressed: () => setState(() => _obscure = !_obscure),
            ),
          ),
        ),
        const SizedBox(height: 12),
        TextField(
          controller: _folderCtrl,
          autocorrect: false,
          decoration: InputDecoration(
            labelText: l.syncRemoteFolder,
            hintText: l.syncRemoteFolderHint,
            border: const OutlineInputBorder(),
            isDense: true,
          ),
        ),
        const SizedBox(height: 8),
        Text(
          l.syncCredentialsNote,
          style: TextStyle(fontSize: 12, color: colorScheme.onSurfaceVariant),
        ),
        const SizedBox(height: 12),
        SwitchListTile(
          contentPadding: EdgeInsets.zero,
          title: Text(l.syncAuto),
          value: _autoSync,
          onChanged: (v) {
            setState(() => _autoSync = v);
            _save();
          },
        ),
        const SizedBox(height: 8),
        Wrap(
          spacing: 8,
          runSpacing: 8,
          crossAxisAlignment: WrapCrossAlignment.center,
          children: [
            OutlinedButton.icon(
              onPressed: (_busy || _testing) ? null : _save,
              icon: const Icon(Icons.save),
              label: Text(l.syncSave),
            ),
            OutlinedButton.icon(
              onPressed: (!configured || _busy || _testing)
                  ? null
                  : _testConnection,
              icon: _testing
                  ? const SizedBox(
                      width: 16,
                      height: 16,
                      child: CircularProgressIndicator(strokeWidth: 2),
                    )
                  : const Icon(Icons.wifi_tethering),
              label: Text(l.syncTestConnection),
            ),
            FilledButton.icon(
              onPressed: (!configured || _busy || _testing) ? null : _syncNow,
              icon: _busy
                  ? const SizedBox(
                      width: 16,
                      height: 16,
                      child: CircularProgressIndicator(strokeWidth: 2),
                    )
                  : const Icon(Icons.sync),
              label: Text(_busy ? l.syncRunning : l.syncNow),
            ),
          ],
        ),
        const SizedBox(height: 12),
        Text(
          _lastSync == null
              ? l.syncNeverRun
              : l.syncLastRun(_lastSync!.toLocal().toString()),
          style: TextStyle(fontSize: 13, color: colorScheme.onSurfaceVariant),
        ),
        if (lastResult != null && lastResult.ok) ...[
          const SizedBox(height: 4),
          Text(
            l.syncResultSummary(lastResult.uploaded, lastResult.downloaded,
                lastResult.conflicts),
            style: TextStyle(fontSize: 13, color: colorScheme.onSurfaceVariant),
          ),
        ],
      ],
    );
  }
}

class _ServerSettings extends StatefulWidget {
  const _ServerSettings();

  @override
  State<_ServerSettings> createState() => _ServerSettingsState();
}

class _ServerSettingsState extends State<_ServerSettings> {
  final _urlCtrl = TextEditingController();
  final _userCtrl = TextEditingController();
  final _passCtrl = TextEditingController();
  bool _busy = false;
  bool _loggedIn = false;
  String? _status;

  @override
  void initState() {
    super.initState();
    _load();
  }

  @override
  void dispose() {
    _urlCtrl.dispose();
    _userCtrl.dispose();
    _passCtrl.dispose();
    super.dispose();
  }

  Future<void> _load() async {
    final prefs = await SharedPreferences.getInstance();
    final cfg = await BadNoteServerConfig.load(prefs);
    if (!mounted) return;
    setState(() {
      _urlCtrl.text = cfg.baseUrl;
      _userCtrl.text = cfg.username;
      _passCtrl.text = cfg.password;
      _loggedIn = cfg.isLoggedIn;
    });
  }

  Future<void> _saveAndLogin() async {
    final l = AppLocalizations.of(context);
    setState(() => _busy = true);
    try {
      final prefs = await SharedPreferences.getInstance();
      var cfg = BadNoteServerConfig(
        baseUrl: _urlCtrl.text.trim(),
        username: _userCtrl.text.trim(),
        password: _passCtrl.text,
      );
      final client = BadNoteServerClient(cfg);
      cfg = await client.registerOrLogin(
        username: cfg.username,
        password: cfg.password,
      );
      await cfg.save(prefs);
      client.close();
      if (!mounted) return;
      setState(() {
        _loggedIn = true;
        _status = l.serverLoggedIn;
      });
    } catch (e) {
      if (!mounted) return;
      setState(() => _status = l.serverTestFail('$e'));
    } finally {
      if (mounted) setState(() => _busy = false);
    }
  }

  Future<void> _test() async {
    final l = AppLocalizations.of(context);
    setState(() => _busy = true);
    try {
      final cfg = BadNoteServerConfig(baseUrl: _urlCtrl.text.trim());
      final client = BadNoteServerClient(cfg);
      final health = await client.health();
      client.close();
      if (!mounted) return;
      setState(() {
        _status = l.serverTestOk('${health['version'] ?? health['api']}');
      });
    } catch (e) {
      if (!mounted) return;
      setState(() => _status = l.serverTestFail('$e'));
    } finally {
      if (mounted) setState(() => _busy = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    final l = AppLocalizations.of(context);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          l.serverHint,
          style: Theme.of(context).textTheme.bodySmall,
        ),
        const SizedBox(height: 12),
        TextField(
          controller: _urlCtrl,
          decoration: InputDecoration(
            labelText: l.serverUrl,
            hintText: l.serverUrlHint,
            border: const OutlineInputBorder(),
            isDense: true,
          ),
          keyboardType: TextInputType.url,
        ),
        const SizedBox(height: 8),
        TextField(
          controller: _userCtrl,
          decoration: InputDecoration(
            labelText: l.serverUsername,
            border: const OutlineInputBorder(),
            isDense: true,
          ),
        ),
        const SizedBox(height: 8),
        TextField(
          controller: _passCtrl,
          obscureText: true,
          decoration: InputDecoration(
            labelText: l.serverPassword,
            border: const OutlineInputBorder(),
            isDense: true,
          ),
        ),
        const SizedBox(height: 12),
        Wrap(
          spacing: 8,
          runSpacing: 8,
          children: [
            FilledButton(
              onPressed: _busy ? null : _saveAndLogin,
              child: Text(l.serverSave),
            ),
            OutlinedButton(
              onPressed: _busy ? null : _test,
              child: Text(l.serverTest),
            ),
            if (_loggedIn)
              Chip(
                avatar: const Icon(Icons.check_circle, size: 16),
                label: Text(l.serverLoggedIn),
              ),
          ],
        ),
        if (_status != null) ...[
          const SizedBox(height: 8),
          Text(_status!, style: Theme.of(context).textTheme.bodySmall),
        ],
      ],
    );
  }
}

class _SectionHeader extends StatelessWidget {
  final String title;
  final IconData icon;

  const _SectionHeader({required this.title, required this.icon});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 16, 16, 4),
      child: Row(
        children: [
          Icon(icon, size: 20, color: Theme.of(context).colorScheme.primary),
          const SizedBox(width: 8),
          Text(
            title,
            style: Theme.of(
              context,
            ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
          ),
        ],
      ),
    );
  }
}
