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

import '../../../core/api/api_error_mapper.dart';
import '../../../core/ui/category_then_product_picker.dart';
import '../../../core/ui/searchable_category_field.dart';
import '../../../core/ui/product_picker_field.dart';
import 'admin_form_shared.dart';
import '../data/admin_repository.dart';
import '../domain/admin_category_node.dart';
import '../domain/admin_inventory_item.dart';
import '../domain/admin_product.dart';
import '../domain/user_admin.dart';

enum _InventorySort {
  newest,
  nameAsc,
  nameDesc,
  quantityAsc,
  quantityDesc,
}

class AdminInventoryPanel extends ConsumerStatefulWidget {
  final bool embedded;

  const AdminInventoryPanel({super.key, this.embedded = false});

  @override
  ConsumerState<AdminInventoryPanel> createState() =>
      _AdminInventoryPanelState();
}

class _AdminInventoryPanelState extends ConsumerState<AdminInventoryPanel> {
  bool _isLoading = true;
  String? _error;
  String _search = '';
  int? _selectedUserId;
  _InventorySort _sort = _InventorySort.newest;
  List<AdminInventoryItem> _items = [];
  List<AdminProduct> _products = [];
  List<AdminCategoryNode> _categories = [];
  List<UserAdmin> _users = [];

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

  Future<void> _load() async {
    setState(() {
      _isLoading = true;
      _error = null;
    });

    try {
      final results = await Future.wait<dynamic>([
        ref.read(adminRepositoryProvider).listAdminInventory(
              userId: _selectedUserId,
              sort: _sortParam,
            ),
        ref.read(adminRepositoryProvider).listSelectableProductsForAdmin(),
        ref.read(adminRepositoryProvider).listCategoryTree(),
        ref.read(adminRepositoryProvider).listUsers(),
      ]);
      if (!mounted) return;
      setState(() {
        _items = results[0] as List<AdminInventoryItem>;
        _products = results[1] as List<AdminProduct>;
        _categories = results[2] as List<AdminCategoryNode>;
        _users = results[3] as List<UserAdmin>;
      });
    } catch (e) {
      if (!mounted) return;
      setState(() => _error = mapErrorToUserMessage(e, context));
    } finally {
      if (mounted) setState(() => _isLoading = false);
    }
  }

  String get _sortParam => switch (_sort) {
    _InventorySort.newest => '',
    _InventorySort.nameAsc => 'nameAsc',
    _InventorySort.nameDesc => 'nameDesc',
    _InventorySort.quantityAsc => 'quantityAsc',
    _InventorySort.quantityDesc => 'quantityDesc',
  };

  String _sortLabel(_InventorySort sort) => switch (sort) {
    _InventorySort.newest => 'Nyast',
    _InventorySort.nameAsc => 'Namn A-Ö',
    _InventorySort.nameDesc => 'Namn Ö-A',
    _InventorySort.quantityAsc => 'Mängd stigande',
    _InventorySort.quantityDesc => 'Mängd fallande',
  };

  List<AdminInventoryItem> get _filtered {
    final q = _search.trim().toLowerCase();
    if (q.isEmpty) return _items;
    return _items.where((item) {
      return item.displayName.toLowerCase().contains(q) ||
          item.username.toLowerCase().contains(q) ||
          item.userEmail.toLowerCase().contains(q) ||
          (item.location ?? '').toLowerCase().contains(q) ||
          (item.categoryPath ?? '').toLowerCase().contains(q);
    }).toList();
  }

  List<String> get _locationOptions {
    return buildLocationOptionsFromValues(_items.map((item) => item.location));
  }

  Future<void> _addItem() async {
    final values = await _showInventoryFormDialog(initialOwnerUserId: _selectedUserId);
    if (values == null) return;

    try {
      await ref.read(adminRepositoryProvider).createAdminInventory(
            userId: values.ownerUserId,
            productId: values.productId,
            quantity: values.quantity,
            unit: values.unit,
            location: values.location,
            brand: values.brand,
            receiptName: values.receiptName,
            suitableFor: values.suitableFor,
            comment: values.comment,
          );
      if (!mounted) return;
      await _load();
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Inventory-post skapad.')),
      );
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)),
      );
    }
  }

  Future<void> _editItem(AdminInventoryItem item) async {
    final values = await _showInventoryFormDialog(initial: item);
    if (values == null) return;

    try {
      await ref.read(adminRepositoryProvider).updateAdminInventory(
            item.id,
            productId: values.productId,
            quantity: values.quantity,
            unit: values.unit,
            location: values.location,
            brand: values.brand,
            receiptName: values.receiptName,
            suitableFor: values.suitableFor,
            comment: values.comment,
          );
      if (!mounted) return;
      await _load();
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Inventory-post uppdaterad.')),
      );
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)),
      );
    }
  }

  Future<void> _deleteItem(AdminInventoryItem item) async {
    final confirm = await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Ta bort inventory-post'),
        content: Text('Ta bort "${item.displayName}" för ${item.username}?'),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(false),
            child: const Text('Avbryt'),
          ),
          FilledButton(
            onPressed: () => Navigator.of(context).pop(true),
            child: const Text('Ta bort'),
          ),
        ],
      ),
    );

    if (confirm != true) return;

    try {
      await ref.read(adminRepositoryProvider).removeAdminInventory(item.id);
      if (!mounted) return;
      await _load();
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Inventory-post borttagen.')),
      );
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)),
      );
    }
  }

  Future<void> _mergeItems() async {
    if (_items.length < 2) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Minst två inventory-poster krävs för merge.')),
      );
      return;
    }

    int? sourceId;
    int? targetId;
    int? previewSourceId;
    int? previewTargetId;
    Future<Map<String, dynamic>?>? previewFuture;

    AdminInventoryItem? byId(int? id) {
      if (id == null) return null;
      for (final item in _items) {
        if (item.id == id) return item;
      }
      return null;
    }

    String? mergeValidation(AdminInventoryItem? source, AdminInventoryItem? target) {
      if (source == null || target == null) {
        return 'Välj både source och target för merge.';
      }
      if (source.id == target.id) {
        return 'Source och target kan inte vara samma post.';
      }
      if (source.userId != target.userId) {
        return 'Merge kräver samma användare på båda posterna.';
      }
      if (source.productId != target.productId) {
        return 'Merge kräver samma produkt på båda posterna.';
      }
      if (source.unit.trim().toLowerCase() != target.unit.trim().toLowerCase()) {
        return 'Merge kräver samma enhet på båda posterna.';
      }
      return null;
    }

    Future<Map<String, dynamic>?> fetchPreview(int? sourceId, int? targetId) async {
      if (sourceId == null || targetId == null) return null;
      try {
        return await ref.read(adminRepositoryProvider).previewAdminInventoryMerge(
              sourceInventoryId: sourceId,
              targetInventoryId: targetId,
            );
      } catch (_) {
        return null;
      }
    }

    Future<Map<String, dynamic>?>? resolvePreviewFuture(int? sourceId, int? targetId) {
      if (sourceId == null || targetId == null) return null;
      if (previewFuture == null ||
          previewSourceId != sourceId ||
          previewTargetId != targetId) {
        previewSourceId = sourceId;
        previewTargetId = targetId;
        previewFuture = fetchPreview(sourceId, targetId);
      }
      return previewFuture;
    }

    final ok = await showDialog<bool>(
      context: context,
      builder: (context) {
        return StatefulBuilder(
          builder: (context, setDialogState) {
            final source = byId(sourceId);
            final target = byId(targetId);
            final validationMessage = mergeValidation(source, target);
            final canMerge = validationMessage == null;
            final localMergedQuantity = canMerge && source != null && target != null
                ? source.quantity + target.quantity
                : null;

            return AlertDialog(
              title: const Text('Merge inventory-poster'),
              content: SizedBox(
                width: 460,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Välj två poster för samma användare, produkt och enhet. Source tas bort och target behålls.',
                      style: Theme.of(context).textTheme.bodyMedium,
                    ),
                    const SizedBox(height: 12),
                    DropdownButtonFormField<int>(
                      initialValue: sourceId,
                      items: _items
                          .map((e) => DropdownMenuItem<int>(
                                value: e.id,
                                child: Text(
                                  '${e.displayName} (${e.quantity} ${e.unit}) · ${e.username}',
                                  overflow: TextOverflow.ellipsis,
                                ),
                              ))
                          .toList(),
                      onChanged: (v) => setDialogState(() => sourceId = v),
                      decoration: const InputDecoration(labelText: 'Source (tas bort)'),
                    ),
                    const SizedBox(height: 12),
                    DropdownButtonFormField<int>(
                      initialValue: targetId,
                      items: _items
                          .map((e) => DropdownMenuItem<int>(
                                value: e.id,
                                child: Text(
                                  '${e.displayName} (${e.quantity} ${e.unit}) · ${e.username}',
                                  overflow: TextOverflow.ellipsis,
                                ),
                              ))
                          .toList(),
                      onChanged: (v) => setDialogState(() => targetId = v),
                      decoration: const InputDecoration(labelText: 'Target (behålls)'),
                    ),
                    const SizedBox(height: 12),
                    if (sourceId != null && targetId != null)
                      FutureBuilder<Map<String, dynamic>?>(
                        future: resolvePreviewFuture(sourceId, targetId),
                        builder: (context, snapshot) {
                          if (snapshot.connectionState == ConnectionState.waiting) {
                            return const Align(
                              alignment: Alignment.centerLeft,
                              child: Text('Hämtar server-preview...'),
                            );
                          }
                          final data = snapshot.data;
                          if (data == null) {
                            return const SizedBox.shrink();
                          }
                          final canMergeServer = data['canMerge'] == true;
                          final reason = data['reason']?.toString();
                          final outcome = data['outcome'] as Map<String, dynamic>?;
                          final mergedQuantity = outcome?['mergedQuantity'];
                          final mergedUnit = outcome?['mergedUnit']?.toString() ?? '';

                          if (!canMergeServer && reason != null && reason.isNotEmpty) {
                            return Container(
                              width: double.infinity,
                              padding: const EdgeInsets.all(10),
                              decoration: BoxDecoration(
                                color: Theme.of(context).colorScheme.errorContainer,
                                borderRadius: BorderRadius.circular(8),
                              ),
                              child: Text(
                                'Server-preview: $reason',
                                style: TextStyle(
                                  color: Theme.of(context).colorScheme.onErrorContainer,
                                ),
                              ),
                            );
                          }

                          if (canMergeServer && mergedQuantity != null) {
                            return Container(
                              width: double.infinity,
                              padding: const EdgeInsets.all(10),
                              decoration: BoxDecoration(
                                color: Theme.of(context).colorScheme.primaryContainer,
                                borderRadius: BorderRadius.circular(8),
                              ),
                              child: Text(
                                'Server-preview: target blir $mergedQuantity $mergedUnit.',
                                style: TextStyle(
                                  color: Theme.of(context).colorScheme.onPrimaryContainer,
                                ),
                              ),
                            );
                          }

                          return const SizedBox.shrink();
                        },
                      ),
                    if (sourceId != null && targetId != null) const SizedBox(height: 12),
                    if (validationMessage != null)
                      Container(
                        width: double.infinity,
                        padding: const EdgeInsets.all(10),
                        decoration: BoxDecoration(
                          color: Theme.of(context).colorScheme.errorContainer,
                          borderRadius: BorderRadius.circular(8),
                        ),
                        child: Text(
                          validationMessage,
                          style: TextStyle(
                            color: Theme.of(context).colorScheme.onErrorContainer,
                          ),
                        ),
                      )
                    else if (localMergedQuantity != null)
                      Container(
                        width: double.infinity,
                        padding: const EdgeInsets.all(10),
                        decoration: BoxDecoration(
                          color: Theme.of(context).colorScheme.primaryContainer,
                          borderRadius: BorderRadius.circular(8),
                        ),
                        child: Text(
                          'Lokal förhandsvisning: target blir ${localMergedQuantity.toStringAsFixed(2)} ${target?.unit ?? ''}.',
                          style: TextStyle(
                            color: Theme.of(context).colorScheme.onPrimaryContainer,
                          ),
                        ),
                      ),
                  ],
                ),
              ),
              actions: [
                TextButton(
                  onPressed: () => Navigator.of(context).pop(false),
                  child: const Text('Avbryt'),
                ),
                FilledButton(
                  onPressed: canMerge ? () => Navigator.of(context).pop(true) : null,
                  child: const Text('Merge'),
                ),
              ],
            );
          },
        );
      },
    );

    if (ok != true || sourceId == null || targetId == null) return;

    try {
      await ref.read(adminRepositoryProvider).mergeAdminInventory(
            sourceInventoryId: sourceId!,
            targetInventoryId: targetId!,
          );
      if (!mounted) return;
      await _load();
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Inventory merge genomförd.')),
      );
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)),
      );
    }
  }

  Future<_InventoryFormValues?> _showInventoryFormDialog({
    AdminInventoryItem? initial,
    int? initialOwnerUserId,
  }) {
    return showDialog<_InventoryFormValues>(
      context: context,
      builder: (context) => _InventoryFormDialog(
        users: _users,
        products: _products,
        categories: _categories,
        locationOptions: _locationOptions,
        initial: initial,
        initialOwnerUserId: initialOwnerUserId,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    if (_isLoading) {
      return const Center(child: CircularProgressIndicator());
    }

    if (_error != null) {
      final message = _error!;
      return Center(
        child: ConstrainedBox(
          constraints: const BoxConstraints(maxWidth: 720),
          child: Card(
            margin: const EdgeInsets.all(16),
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    'Kunde inte läsa inventory-data',
                    style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
                  ),
                  const SizedBox(height: 8),
                  SelectableText(message),
                  const SizedBox(height: 12),
                  Wrap(
                    spacing: 8,
                    runSpacing: 8,
                    children: [
                      FilledButton.icon(
                        onPressed: _load,
                        icon: const Icon(Icons.refresh),
                        label: const Text('Försök igen'),
                      ),
                      OutlinedButton.icon(
                        onPressed: () {
                          Clipboard.setData(ClipboardData(text: message));
                          ScaffoldMessenger.of(context).showSnackBar(
                            const SnackBar(content: Text('Felmeddelande kopierat.')),
                          );
                        },
                        icon: const Icon(Icons.copy_all),
                        label: const Text('Kopiera fel'),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ),
      );
    }

    final filtered = _filtered;

    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Card(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('Inventory', style: theme.textTheme.titleMedium),
                const SizedBox(height: 8),
                Text(
                  'Här arbetar du på användarnas inventory-poster. Du kan filtrera per användare, justera mängder, flytta poster till baslager och slå ihop duplicerade rader.',
                  style: theme.textTheme.bodyMedium,
                ),
                const SizedBox(height: 8),
                const Wrap(
                  spacing: 8,
                  runSpacing: 8,
                  children: [
                    Chip(label: Text('User-scope')),
                    Chip(label: Text('Merge')),
                    Chip(label: Text('Flytta till baslager')),
                  ],
                ),
              ],
            ),
          ),
        ),
        const SizedBox(height: 12),
        Row(
          children: [
            SizedBox(
              width: 300,
              child: DropdownButtonFormField<int>(
                initialValue: _selectedUserId,
                decoration: const InputDecoration(labelText: 'Filtrera användare'),
                items: [
                  const DropdownMenuItem<int>(
                    value: null,
                    child: Text('Alla användare'),
                  ),
                  ..._users.map(
                    (u) => DropdownMenuItem<int>(
                      value: u.id,
                      child: Text(
                        '${u.displayName} (${u.username})',
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                  ),
                ],
                onChanged: (value) {
                  setState(() => _selectedUserId = value);
                  _load();
                },
              ),
            ),
            const SizedBox(width: 8),
            SizedBox(
              width: 220,
              child: DropdownButtonFormField<_InventorySort>(
                initialValue: _sort,
                decoration: const InputDecoration(labelText: 'Sortering'),
                items: _InventorySort.values
                    .map(
                      (s) => DropdownMenuItem<_InventorySort>(
                        value: s,
                        child: Text(_sortLabel(s)),
                      ),
                    )
                    .toList(),
                onChanged: (value) {
                  if (value == null) return;
                  setState(() => _sort = value);
                  _load();
                },
              ),
            ),
            const SizedBox(width: 8),
            Expanded(
              child: TextField(
                decoration: const InputDecoration(
                  prefixIcon: Icon(Icons.search),
                  hintText: 'Sök produkt, användare eller plats',
                ),
                onChanged: (value) => setState(() => _search = value),
              ),
            ),
            const SizedBox(width: 8),
            OutlinedButton.icon(
              onPressed: _load,
              icon: const Icon(Icons.refresh),
              label: const Text('Uppdatera'),
            ),
            const SizedBox(width: 8),
            OutlinedButton.icon(
              onPressed: _mergeItems,
              icon: const Icon(Icons.merge_type),
              label: const Text('Merge'),
            ),
            const SizedBox(width: 8),
            FilledButton.icon(
              onPressed: _addItem,
              icon: const Icon(Icons.add),
              label: const Text('Lägg till'),
            ),
          ],
        ),
        const SizedBox(height: 8),
        Text('Visar ${filtered.length} av ${_items.length} inventory-poster'),
        const SizedBox(height: 8),
        Expanded(
          child: Card(
            child: filtered.isEmpty
                ? Padding(
                    padding: const EdgeInsets.all(16),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Text('Inventory', style: theme.textTheme.titleMedium),
                        const SizedBox(height: 8),
                        Text(
                          'Inga inventory-poster hittades med nuvarande filter.',
                          style: theme.textTheme.bodyMedium,
                        ),
                      ],
                    ),
                  )
                : ListView.separated(
                    itemCount: filtered.length,
                    separatorBuilder: (_, __) => const Divider(height: 1),
                    itemBuilder: (context, index) {
                      final item = filtered[index];
                      return ListTile(
                        title: Row(
                          children: [
                            Expanded(child: Text(item.displayName)),
                            buildCategoryPathChip(item.categoryPath),
                          ],
                        ),
                        subtitle: Text(
                          '${item.quantity} ${item.unit} · ${item.username} (${item.userEmail})'
                          '${item.location == null || item.location!.isEmpty ? '' : ' · ${item.location}'}',
                        ),
                        trailing: Row(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            IconButton(
                              tooltip: 'Flytta till baslager',
                              onPressed: () async {
                                try {
                                  await ref.read(adminRepositoryProvider).moveAdminInventoryToPantry(item.id);
                                  if (!mounted) return;
                                  await _load();
                                  if (!mounted) return;
                                  ScaffoldMessenger.of(context).showSnackBar(
                                    SnackBar(content: Text('Flyttade "${item.displayName}" till baslager.')),
                                  );
                                } catch (e) {
                                  if (!mounted) return;
                                  ScaffoldMessenger.of(context).showSnackBar(
                                    buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)),
                                  );
                                }
                              },
                              icon: const Icon(Icons.storefront_outlined),
                            ),
                            IconButton(
                              tooltip: 'Ändra',
                              onPressed: () => _editItem(item),
                              icon: const Icon(Icons.edit_outlined),
                            ),
                            IconButton(
                              tooltip: 'Ta bort',
                              onPressed: () => _deleteItem(item),
                              icon: const Icon(Icons.delete_outline),
                            ),
                          ],
                        ),
                      );
                    },
                  ),
          ),
        ),
      ],
    );
  }
}

class _InventoryFormValues {
  final int? ownerUserId;
  final int productId;
  final double quantity;
  final String unit;
  final String? location;
  final String? brand;
  final String? receiptName;
  final String? suitableFor;
  final String? comment;

  const _InventoryFormValues({
    this.ownerUserId,
    required this.productId,
    required this.quantity,
    required this.unit,
    this.location,
    this.brand,
    this.receiptName,
    this.suitableFor,
    this.comment,
  });
}

class _InventoryFormDialog extends StatefulWidget {
  final List<UserAdmin> users;
  final List<AdminProduct> products;
  final List<AdminCategoryNode> categories;
  final List<String> locationOptions;
  final AdminInventoryItem? initial;
  final int? initialOwnerUserId;

  const _InventoryFormDialog({
    required this.users,
    required this.products,
    required this.categories,
    required this.locationOptions,
    this.initial,
    this.initialOwnerUserId,
  });

  @override
  State<_InventoryFormDialog> createState() => _InventoryFormDialogState();
}

class _InventoryFormDialogState extends State<_InventoryFormDialog> {
  static const String _manualLocationValue = '__manual_location__';

  final _formKey = GlobalKey<FormState>();
  late final TextEditingController _quantityController;
  late final TextEditingController _unitController;
  late final TextEditingController _locationController;
  late final TextEditingController _brandController;
  late final TextEditingController _receiptNameController;
  late final TextEditingController _suitableForController;
  late final TextEditingController _commentController;
  late final TextEditingController _categorySearchController;
  late List<CategorySelectOption> _categoryOptions;

  int? _ownerUserId;
  int? _productId;
  int? _categoryId;
  String? _categoryPath;
  String? _productErrorText;
  bool _useManualLocation = false;
  ProductScopeFilter _productScopeFilter = ProductScopeFilter.globalOnly;

  @override
  void initState() {
    super.initState();
    final initial = widget.initial;
    _ownerUserId = initial?.userId ?? widget.initialOwnerUserId;
    _productId = initial?.productId;
    final initialProduct = _productById(_productId);
    _categoryId = initialProduct?.categoryId;
    _categoryPath = initialProduct?.categoryPath;
    _quantityController = TextEditingController(
      text: initial == null ? '' : initial.quantity.toString(),
    );
    _unitController = TextEditingController(text: initial?.unit ?? 'st');
    _locationController = TextEditingController(text: initial?.location ?? '');
    _brandController = TextEditingController(text: initial?.brand ?? '');
    _receiptNameController = TextEditingController(text: initial?.receiptName ?? '');
    _suitableForController = TextEditingController(text: initial?.suitableFor ?? '');
    _commentController = TextEditingController(text: initial?.comment ?? '');
    _categorySearchController = TextEditingController(text: _categoryPath ?? '');
    _categoryOptions = _flattenCategoryOptions(widget.categories);
    final initialLocation = _locationController.text.trim();
    _useManualLocation = initialLocation.isNotEmpty &&
      !widget.locationOptions.contains(initialLocation);
  }

  @override
  void dispose() {
    _quantityController.dispose();
    _unitController.dispose();
    _locationController.dispose();
    _brandController.dispose();
    _receiptNameController.dispose();
    _suitableForController.dispose();
    _commentController.dispose();
    _categorySearchController.dispose();
    super.dispose();
  }

  void _applyCategorySelection(int id, String path) {
    setState(() {
      _categoryId = id;
      _categoryPath = path;
      _categorySearchController.text = path;
      if (_productId != null) {
        final current = _productById(_productId);
        if (current?.categoryId != _categoryId) {
          _productId = null;
        }
      }
    });
  }

  AdminProduct? _productById(int? id) {
    if (id == null) return null;
    for (final product in widget.products) {
      if (product.id == id) return product;
    }
    final initial = widget.initial;
    if (initial != null && initial.productId == id) {
      return AdminProduct(
        id: initial.productId,
        name: initial.productName,
        canonicalName: initial.productCanonicalName,
        ownerId: initial.userId,
        isPrivate: null,
        categoryId: initial.categoryId,
        categoryPath: initial.categoryPath,
        status: 'private',
      );
    }
    return null;
  }

  List<ProductOption> _productOptions() {
    final filtered = filterSelectableAdminProducts(
      products: widget.products,
      ownerUserId: _ownerUserId,
      categoryId: _categoryId,
      scopeFilter: _productScopeFilter,
      selectedProduct: _productById(_productId),
    );
    return toProductOptions(filtered);
  }

  String? _locationDropdownValue() {
    return resolveLocationDropdownValue(
      useManualLocation: _useManualLocation,
      currentValue: _locationController.text,
      options: widget.locationOptions,
      manualLocationValue: _manualLocationValue,
    );
  }

  List<CategorySelectOption> _flattenCategoryOptions(
    List<AdminCategoryNode> nodes, [
    List<String> parents = const [],
  ]) {
    final result = <CategorySelectOption>[];
    for (final node in nodes) {
      final pathParts = [...parents, node.name];
      final path = pathParts.join(' > ');
      result.add((value: node.id.toString(), label: path));
      result.addAll(_flattenCategoryOptions(node.children, pathParts));
    }
    return result;
  }

  Future<void> _pickCategory() async {
    final selected = await CategoryThenProductPicker.showCategorySheet(
      context,
      categoryTree: widget.categories,
      preselectedCategoryId: _categoryId,
    );
    if (selected == null || !mounted) return;
    _applyCategorySelection(selected.id, selected.path);
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text(widget.initial == null ? 'Lägg till inventory-post' : 'Ändra inventory-post'),
      content: SizedBox(
        width: 480,
        child: Form(
          key: _formKey,
          child: SingleChildScrollView(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  widget.initial == null
                      ? 'Skapa en ny inventory-rad för en användare. Välj produkt, mängd, enhet och valfria metadata.'
                      : 'Ändra den valda inventory-raden. Produkt, mängd, enhet och metadata kan justeras utan att byta ägare.',
                  style: Theme.of(context).textTheme.bodyMedium,
                ),
                const SizedBox(height: 12),
                if (widget.initial == null) ...[
                  DropdownButtonFormField<int>(
                    initialValue: _ownerUserId,
                    items: widget.users
                        .map((u) => DropdownMenuItem<int>(
                              value: u.id,
                              child: Text(
                                '${u.displayName} (${u.username})',
                                overflow: TextOverflow.ellipsis,
                              ),
                            ))
                        .toList(),
                    onChanged: (value) => setState(() {
                      _ownerUserId = value;
                      if (value == null) {
                        _productScopeFilter = ProductScopeFilter.globalOnly;
                        final selected = _productById(_productId);
                        if (selected?.isPrivate == true) {
                          _productId = null;
                        }
                      }
                    }),
                    decoration: const InputDecoration(labelText: 'Ägare (användare)'),
                    validator: (value) => value == null ? 'Välj användare' : null,
                  ),
                  const SizedBox(height: 12),
                ] else ...[
                  Text(
                    'Produkt: ${widget.initial!.displayName}',
                    style: Theme.of(context).textTheme.bodyMedium,
                  ),
                  const SizedBox(height: 8),
                  Align(
                    alignment: Alignment.centerLeft,
                    child: Text(
                      'Ägare: ${widget.initial!.username} (${widget.initial!.userEmail})',
                      style: Theme.of(context).textTheme.bodyMedium,
                    ),
                  ),
                  const SizedBox(height: 12),
                ],
                SearchableCategoryField(
                  options: _categoryOptions,
                  value: _categoryId?.toString(),
                  label: 'Kategori (sökbar)',
                  onChanged: (value) {
                    if (value == null) return;
                    final label = _categoryOptions
                        .firstWhere((option) => option.value == value)
                        .label;
                    _applyCategorySelection(int.parse(value), label);
                  },
                ),
                const SizedBox(height: 12),
                Row(
                  children: [
                    OutlinedButton.icon(
                      onPressed: _pickCategory,
                      icon: const Icon(Icons.category_outlined),
                      label: const Text('Välj kategori'),
                    ),
                    const SizedBox(width: 8),
                    OutlinedButton.icon(
                      onPressed: () {
                        setState(() {
                          _categoryId = null;
                          _categoryPath = null;
                        });
                      },
                      icon: const Icon(Icons.clear),
                      label: const Text('Rensa kategori'),
                    ),
                  ],
                ),
                const SizedBox(height: 12),
                ProductPickerField(
                  products: _productOptions(),
                  value: _productId,
                  label: 'Produkt',
                  errorText: _productErrorText,
                  onChanged: (value) {
                    setState(() {
                      _productId = value;
                      _productErrorText = null;
                    });
                  },
                ),
                if (_ownerUserId != null) ...[
                  const SizedBox(height: 8),
                  SegmentedButton<ProductScopeFilter>(
                    segments: const [
                      ButtonSegment<ProductScopeFilter>(
                        value: ProductScopeFilter.all,
                        label: Text('Alla'),
                      ),
                      ButtonSegment<ProductScopeFilter>(
                        value: ProductScopeFilter.globalOnly,
                        label: Text('Globala'),
                      ),
                      ButtonSegment<ProductScopeFilter>(
                        value: ProductScopeFilter.privateOnly,
                        label: Text('Privata'),
                      ),
                    ],
                    selected: {_productScopeFilter},
                    onSelectionChanged: (selection) {
                      if (selection.isEmpty) return;
                      setState(() => _productScopeFilter = selection.first);
                    },
                  ),
                  const SizedBox(height: 12),
                ] else ...[
                  const SizedBox(height: 12),
                ],
                TextFormField(
                  controller: _quantityController,
                  keyboardType: const TextInputType.numberWithOptions(decimal: true),
                  decoration: const InputDecoration(labelText: 'Mängd'),
                  validator: (value) {
                    final parsed = double.tryParse((value ?? '').replaceAll(',', '.'));
                    if (parsed == null || parsed < 0) return 'Ange en giltig mängd';
                    return null;
                  },
                ),
                const SizedBox(height: 12),
                TextFormField(
                  controller: _unitController,
                  decoration: const InputDecoration(labelText: 'Enhet'),
                  validator: (value) =>
                      (value == null || value.trim().isEmpty) ? 'Ange enhet' : null,
                ),
                const SizedBox(height: 12),
                DropdownButtonFormField<String>(
                  initialValue: _locationDropdownValue(),
                  decoration: const InputDecoration(labelText: 'Plats (valfritt)'),
                  items: [
                    ...widget.locationOptions.map(
                      (option) => DropdownMenuItem<String>(
                        value: option,
                        child: Text(option),
                      ),
                    ),
                    const DropdownMenuItem<String>(
                      value: _manualLocationValue,
                      child: Text('Ange manuellt...'),
                    ),
                  ],
                  onChanged: (value) {
                    if (value == null) {
                      setState(() {
                        _useManualLocation = false;
                        _locationController.clear();
                      });
                      return;
                    }
                    if (value == _manualLocationValue) {
                      setState(() => _useManualLocation = true);
                      return;
                    }
                    setState(() {
                      _useManualLocation = false;
                      _locationController.text = value;
                    });
                  },
                ),
                if (_useManualLocation) ...[
                  const SizedBox(height: 12),
                  TextFormField(
                    controller: _locationController,
                    decoration: const InputDecoration(labelText: 'Plats (manuell)'),
                  ),
                ],
                const SizedBox(height: 12),
                TextFormField(
                  controller: _brandController,
                  decoration: const InputDecoration(labelText: 'Varumärke (valfritt)'),
                ),
                const SizedBox(height: 12),
                TextFormField(
                  controller: _receiptNameController,
                  decoration: const InputDecoration(labelText: 'Kvittonamn (valfritt)'),
                ),
                const SizedBox(height: 12),
                TextFormField(
                  controller: _suitableForController,
                  decoration: const InputDecoration(labelText: 'Passar till (valfritt)'),
                ),
                const SizedBox(height: 12),
                TextFormField(
                  controller: _commentController,
                  decoration: const InputDecoration(labelText: 'Kommentar (valfritt)'),
                  maxLines: 3,
                ),
              ],
            ),
          ),
        ),
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.of(context).pop(),
          child: const Text('Avbryt'),
        ),
        FilledButton(
          onPressed: () {
            if (!_formKey.currentState!.validate()) return;
            if (_productId == null) {
              setState(() => _productErrorText = 'Välj en produkt');
              return;
            }

            final quantity =
                double.parse(_quantityController.text.trim().replaceAll(',', '.'));
            Navigator.of(context).pop(
              _InventoryFormValues(
                ownerUserId: _ownerUserId,
                productId: _productId!,
                quantity: quantity,
                unit: _unitController.text.trim(),
                location: _locationController.text.trim().isEmpty
                    ? null
                    : _locationController.text.trim(),
                brand: _brandController.text.trim().isEmpty
                    ? null
                    : _brandController.text.trim(),
                receiptName: _receiptNameController.text.trim().isEmpty
                    ? null
                    : _receiptNameController.text.trim(),
                suitableFor: _suitableForController.text.trim().isEmpty
                    ? null
                    : _suitableForController.text.trim(),
                comment: _commentController.text.trim().isEmpty
                    ? null
                    : _commentController.text.trim(),
              ),
            );
          },
          child: const Text('Spara'),
        ),
      ],
    );
  }
}