import 'package:flutter/material.dart';
import '../../../core/api/api_exception.dart';
import '../../../core/ui/category_then_product_picker.dart';
import '../../../core/ui/product_picker_field.dart';
import '../../../core/utils/global_error_handler.dart';
import '../../admin/domain/admin_category_node.dart';
import '../data/receipt_import_session.dart';
import '../domain/parsed_receipt_item.dart';
import '../utils/receipt_import_utils.dart';

enum ImportProductEntryMode { existing, create }

typedef _Destination = ImportDestination;

class EditDialog extends StatefulWidget {
  final ParsedReceiptItem item;
  final ItemEdit current;
  final List<ProductOption> products;
  final List<AdminCategoryNode> categoryTree;
  final Future<ProductOption?> Function(String name, int? categoryId)? onCreate;
  final ImportProductEntryMode? initialEntryMode;

  const EditDialog({
    super.key,
    required this.item,
    required this.current,
    required this.products,
    required this.categoryTree,
    this.onCreate,
    this.initialEntryMode,
  });

  @override
  State<EditDialog> createState() => _EditDialogState();
}

class _EditDialogState extends State<EditDialog> {
  late final TextEditingController _quantityCtrl;
  late final TextEditingController _unitCtrl;
  late final TextEditingController _packageCountCtrl;
  late final TextEditingController _newProductNameCtrl;

  int? _productId;
  String? _productName;
  int? _productCategoryId;
  String? _productCategoryPath;
  CategorySelectionSource? _productCategorySource;

  int? _newCategoryId;
  String? _newCategoryPath;
  CategorySelectionSource? _newCategorySource;

  _Destination _destination = _Destination.inventory;
  ImportProductEntryMode _entryMode = ImportProductEntryMode.existing;
  bool _isCreatingProduct = false;

  // Lokal lista — utökas om nya produkter skapas under dialogen
  late List<ProductOption> _localProducts;
  late CategoryLookup _lookup;

  @override
  void initState() {
    super.initState();
    _lookup = CategoryLookup.fromTree(widget.categoryTree);
    _localProducts = List.of(widget.products);

    _productId = widget.current.productId;
    _productName = widget.current.productName == null
        ? null
        : normalizeProductName(widget.current.productName!);
    _destination = widget.current.destination;
    _entryMode = widget.initialEntryMode ??
        (_productId == null
            ? ImportProductEntryMode.create
            : ImportProductEntryMode.existing);

    _productCategoryId =
        widget.current.categoryId ?? _categoryIdForProduct(_productId);
    _productCategoryPath =
        widget.current.categoryPath ?? _lookup.pathFor(_productCategoryId);
    _productCategorySource = widget.current.categorySource;

    _newCategoryId = widget.current.categoryId ?? widget.item.categorySuggestionId;
    _newCategoryPath =
        widget.current.categoryPath ?? widget.item.categorySuggestionPath;
    _newCategorySource = widget.current.categorySource;

    final inferred = inferPackageFields(
      rawName: widget.item.rawName,
      quantity: widget.current.quantity ?? widget.item.quantity,
      unit: widget.current.unit ?? widget.item.unit,
    );

    _quantityCtrl = TextEditingController(
      text: (widget.current.packQuantity ?? inferred.packQuantity)?.toString() ?? '',
    );
    _unitCtrl = TextEditingController(
      text: widget.current.packUnit ?? inferred.packUnit ?? '',
    );
    _packageCountCtrl = TextEditingController(
      text: (widget.current.packageCount ?? inferred.packageCount).toString(),
    );
    _newProductNameCtrl = TextEditingController(
      text: normalizeProductName(widget.current.productName ?? widget.item.rawName),
    );
  }

  @override
  void dispose() {
    _quantityCtrl.dispose();
    _unitCtrl.dispose();
    _packageCountCtrl.dispose();
    _newProductNameCtrl.dispose();
    super.dispose();
  }

  // ── Hjälpmetoder ──────────────────────────────────────────────────────────

  int? _categoryIdForProduct(int? productId) {
    if (productId == null) return null;
    return _localProducts
        .cast<ProductOption?>()
        .firstWhere((p) => p?.id == productId, orElse: () => null)
        ?.categoryId;
  }

  // ── Kategoripicker ─────────────────────────────────────────────────────────

  Future<void> _openCreateCategoryPicker({int? preselectedCategoryId}) async {
    final selected = await CategoryThenProductPicker.showCategorySheet(
      context,
      categoryTree: widget.categoryTree,
      preselectedCategoryId:
          preselectedCategoryId ?? _newCategoryId ?? widget.item.categorySuggestionId,
    );
    if (selected == null || !mounted) return;
    setState(() {
      _newCategoryId = selected.id;
      _newCategoryPath = selected.path;
      _newCategorySource = CategorySelectionSource.manual;
    });
  }

  Future<void> _openExistingCategoryPicker({int? preselectedCategoryId}) async {
    Future<ProductOption?> Function(String, int)? onCreateWrapped;
    if (widget.onCreate != null) {
      onCreateWrapped = (name, categoryId) async {
        final newProduct = await widget.onCreate!(name, categoryId);
        if (newProduct != null && mounted) {
          setState(() => _localProducts = [..._localProducts, newProduct]);
        }
        return newProduct;
      };
    }

    final id = await CategoryThenProductPicker.show(
      context,
      categoryTree: widget.categoryTree,
      products: _localProducts,
      currentProductId: _productId,
      preselectedCategoryId: preselectedCategoryId,
      initialQuery: widget.item.rawName,
      onCreate: onCreateWrapped,
    );
    if (id == null || !mounted) return;
    setState(() {
      _productId = id;
      final selectedProduct = _localProducts
          .cast<ProductOption?>()
          .firstWhere((p) => p?.id == id, orElse: () => null);
      _productName =
          selectedProduct?.name == null ? null : normalizeProductName(selectedProduct!.name);
      _productCategoryId = _categoryIdForProduct(id);
      _productCategoryPath = _lookup.pathFor(_productCategoryId);
      _productCategorySource = CategorySelectionSource.manual;
    });
  }

  /// Applicerar AI-förslag och öppnar kategoriträdet för bekräftelse.
  void _applyAiSuggestion() {
    int? preselectedCategoryId = widget.item.categorySuggestionId;
    final suggestedId = widget.item.suggestedProductId;
    if (suggestedId != null) {
      setState(() {
        _productId = suggestedId;
        _productName = widget.item.suggestedProductName == null
            ? null
            : normalizeProductName(widget.item.suggestedProductName!);
        _productCategoryId =
            _categoryIdForProduct(suggestedId) ?? widget.item.categorySuggestionId;
        _productCategoryPath =
            _lookup.pathFor(_productCategoryId) ?? widget.item.categorySuggestionPath;
        _productCategorySource = CategorySelectionSource.ai;
      });
      preselectedCategoryId = _productCategoryId;
    }
    _openExistingCategoryPicker(preselectedCategoryId: preselectedCategoryId);
  }

  // ── Spara ──────────────────────────────────────────────────────────────────

  bool get _canConfirm {
    if (_isCreatingProduct) return false;
    if (_entryMode == ImportProductEntryMode.create) return true;
    return _productId != null;
  }

  Future<void> _confirm() async {
    final originalUnit = widget.current.unit ?? widget.item.unit;
    final newUnit = _unitCtrl.text.trim().isEmpty ? originalUnit : _unitCtrl.text.trim();

    await _confirmUnitChange(originalUnit!, newUnit!);

    if (_entryMode == ImportProductEntryMode.create) {
      final trimmedName = _newProductNameCtrl.text.trim();
      if (trimmedName.isEmpty) {
        showGlobalErrorDialog(context, 'Ange ett produktnamn först.');
        return;
      }
      if (widget.onCreate == null) {
        showGlobalErrorDialog(context, 'Produktskapande är inte tillgängligt i den här vyn.');
        return;
      }

      setState(() => _isCreatingProduct = true);
      try {
        final newProduct = await widget.onCreate!(trimmedName, _newCategoryId);
        if (newProduct == null || !mounted) {
          if (mounted) {
            showGlobalErrorDialog(context, 'Kunde inte skapa produkten. Försök igen.');
          }
          return;
        }
        if (!_localProducts.any((p) => p.id == newProduct.id)) {
          _localProducts = [..._localProducts, newProduct];
        }
        _productId = newProduct.id;
        _productName = newProduct.name;
        _productCategoryId = _newCategoryId;
        _productCategoryPath = _newCategoryPath;
        _productCategorySource = _newCategorySource ?? CategorySelectionSource.manual;
      } on ApiException catch (e) {
        if (mounted) {
          showGlobalErrorDialog(
            context,
            e.message.trim().isEmpty ? 'Kunde inte skapa produkten. Försök igen.' : e.message,
          );
        }
        return;
      } catch (_) {
        if (mounted) {
          showGlobalErrorDialog(context, 'Kunde inte skapa produkten. Försök igen.');
        }
        return;
      } finally {
        if (mounted) setState(() => _isCreatingProduct = false);
      }
      if (!mounted || _productId == null) return;
    }

    final packQuantity =
        double.tryParse(_quantityCtrl.text.replaceAll(',', '.'));
    final packageCount =
        double.tryParse(_packageCountCtrl.text.replaceAll(',', '.')) ?? 1.0;
    final packUnit = _unitCtrl.text.trim().isEmpty
        ? (widget.current.packUnit ?? widget.current.unit ?? widget.item.unit)
        : _unitCtrl.text.trim();
    final totalQuantity =
        packQuantity != null ? packQuantity * packageCount : widget.item.quantity;

    Navigator.pop(
      context,
      ItemEdit(
        productId: _productId,
        productName: _productName,
        categoryId: _productCategoryId,
        categoryPath: _productCategoryPath,
        categorySource: _productCategorySource,
        quantity: totalQuantity,
        unit: packUnit,
        packQuantity: packQuantity,
        packUnit: packUnit,
        packageCount: packageCount,
        destination: _destination,
      ),
    );
  }

  Future<void> _confirmUnitChange(String originalUnit, String newUnit) async {
    if (originalUnit == newUnit) return;

    return showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('Bekräfta enhetsändring'),
          content: Text(
            'Du försöker ändra enheten från "$originalUnit" till "$newUnit". Vill du fortsätta med denna ändring?',
          ),
          actions: <Widget>[
            TextButton(
              child: const Text('Avbryt'),
              onPressed: () {
                _unitCtrl.text = originalUnit;
                Navigator.of(context).pop();
              },
            ),
            TextButton(
              child: const Text('Bekräfta'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  // ── Build ──────────────────────────────────────────────────────────────────

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final item = widget.item;
    final aiLabel = _resolveAiLabel(item);
    final suggestedProductLabel = _resolveSuggestedProductLabel(item);

    final currentPackQuantity =
        double.tryParse(_quantityCtrl.text.replaceAll(',', '.'));
    final currentPackageCount =
        double.tryParse(_packageCountCtrl.text.replaceAll(',', '.')) ?? 1.0;
    final currentUnit = _unitCtrl.text.trim().isEmpty
        ? (widget.current.packUnit ?? widget.current.unit ?? item.unit)
        : _unitCtrl.text.trim();
    final totalPreview = currentPackQuantity == null
        ? null
        : currentPackQuantity * currentPackageCount;

    return AlertDialog(
      title: Text(
        normalizeProductName(item.rawName),
        maxLines: 2,
        overflow: TextOverflow.ellipsis,
      ),
      content: SingleChildScrollView(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _buildDestinationPicker(theme),
            const SizedBox(height: 12),
            _buildEntryModePicker(theme),
            const SizedBox(height: 12),
            if (_entryMode == ImportProductEntryMode.existing)
              _buildExistingProductSection(theme, item, aiLabel, suggestedProductLabel)
            else
              _buildCreateProductSection(theme, aiLabel),
            const SizedBox(height: 12),
            if (_destination == _Destination.inventory)
              _buildQuantitySection(theme, totalPreview, currentUnit)
            else
              Text(
                'Baslager sparar bara produkt — ingen mängd eller enhet.',
                style: theme.textTheme.bodySmall
                    ?.copyWith(color: theme.colorScheme.onSurfaceVariant),
              ),
          ],
        ),
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('Avbryt'),
        ),
        FilledButton(
          onPressed: _canConfirm ? _confirm : null,
          child: _isCreatingProduct
              ? const SizedBox(
                  width: 18,
                  height: 18,
                  child: CircularProgressIndicator(strokeWidth: 2),
                )
              : Text(
                  _entryMode == ImportProductEntryMode.create ? 'Skapa och välj' : 'OK',
                ),
        ),
      ],
    );
  }

  // ── Byggare för delsektioner ───────────────────────────────────────────────

  Widget _buildDestinationPicker(ThemeData theme) => SegmentedButton<_Destination>(
        segments: const [
          ButtonSegment(
            value: ImportDestination.inventory,
            icon: Icon(Icons.kitchen_outlined, size: 16),
            label: Text('Inventarie'),
          ),
          ButtonSegment(
            value: ImportDestination.pantry,
            icon: Icon(Icons.inventory_2_outlined, size: 16),
            label: Text('Baslager'),
          ),
        ],
        selected: {_destination},
        onSelectionChanged: (s) => setState(() => _destination = s.first),
        style: const ButtonStyle(visualDensity: VisualDensity.compact),
      );

  Widget _buildEntryModePicker(ThemeData theme) =>
      SegmentedButton<ImportProductEntryMode>(
        segments: const [
          ButtonSegment(
            value: ImportProductEntryMode.existing,
            icon: Icon(Icons.search, size: 16),
            label: Text('Befintlig'),
          ),
          ButtonSegment(
            value: ImportProductEntryMode.create,
            icon: Icon(Icons.add_box_outlined, size: 16),
            label: Text('Ny produkt'),
          ),
        ],
        selected: {_entryMode},
        onSelectionChanged: (s) => setState(() => _entryMode = s.first),
        style: const ButtonStyle(visualDensity: VisualDensity.compact),
      );

  Widget _buildExistingProductSection(
    ThemeData theme,
    ParsedReceiptItem item,
    String? aiLabel,
    String? suggestedProductLabel,
  ) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        if (suggestedProductLabel != null) ...[
          Tooltip(
            message: 'Trolig matchning baserat på produktnamn i databasen',
            child: ActionChip(
              avatar: Icon(Icons.search, size: 14, color: Colors.blue.shade700),
              label: Text('Namnförslag: $suggestedProductLabel',
                  style: Theme.of(context).textTheme.labelSmall),
              backgroundColor: Colors.blue.shade50,
              side: BorderSide(color: Colors.blue.shade300),
              visualDensity: VisualDensity.compact,
              onPressed: _applyAiSuggestion,
            ),
          ),
          const SizedBox(height: 8),
        ],
        Row(
          children: [
            Expanded(
              child: ProductPickerField(
                products: _localProducts,
                value: _productId,
                label: 'Produkt',
                initialQuery: item.rawName,
                onChanged: (id) {
                  setState(() {
                    _productId = id;
                    final selectedName = _localProducts
                        .cast<ProductOption?>()
                        .firstWhere((p) => p?.id == id, orElse: () => null)
                        ?.name;
                    _productName = selectedName == null
                        ? null
                        : normalizeProductName(selectedName);
                    _productCategoryId = _categoryIdForProduct(id);
                    _productCategoryPath = _lookup.pathFor(_productCategoryId);
                    _productCategorySource =
                        id == null ? null : CategorySelectionSource.manual;
                  });
                },
              ),
            ),
            const SizedBox(width: 8),
            Tooltip(
              message: 'Välj via kategori',
              child: OutlinedButton(
                style: OutlinedButton.styleFrom(
                  minimumSize: const Size(44, 56),
                  padding: EdgeInsets.zero,
                ),
                onPressed: _openExistingCategoryPicker,
                child: const Icon(Icons.account_tree_outlined, size: 20),
              ),
            ),
          ],
        ),
        if (_productCategoryPath != null) ...[
          const SizedBox(height: 8),
          ActionChip(
            avatar: Icon(Icons.account_tree_outlined,
                size: 14, color: Theme.of(context).colorScheme.primary),
            label: Text('Kategori: $_productCategoryPath',
                style: Theme.of(context).textTheme.labelSmall,
                overflow: TextOverflow.ellipsis),
            side: BorderSide(color: Theme.of(context).colorScheme.outlineVariant),
            visualDensity: VisualDensity.compact,
            onPressed: () =>
                _openExistingCategoryPicker(preselectedCategoryId: _productCategoryId),
          ),
        ],
        if (aiLabel != null) ...[
          const SizedBox(height: 8),
          ActionChip(
            avatar: Icon(Icons.auto_awesome, size: 14, color: Colors.green.shade700),
            label: Text('AI-kategori: $aiLabel',
                style: Theme.of(context).textTheme.labelSmall),
            backgroundColor: Colors.green.shade50,
            side: BorderSide(color: Colors.green.shade300),
            visualDensity: VisualDensity.compact,
            onPressed: () => _openExistingCategoryPicker(
              preselectedCategoryId: item.categorySuggestionId,
            ),
          ),
        ],
      ],
    );
  }

  Widget _buildCreateProductSection(ThemeData theme, String? aiLabel) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        TextField(
          controller: _newProductNameCtrl,
          textCapitalization: TextCapitalization.sentences,
          decoration: const InputDecoration(
            labelText: 'Produktnamn',
            border: OutlineInputBorder(),
          ),
          onChanged: (_) => setState(() {}),
        ),
        const SizedBox(height: 8),
        SizedBox(
          width: double.infinity,
          child: OutlinedButton.icon(
            onPressed: _openCreateCategoryPicker,
            icon: const Icon(Icons.account_tree_outlined),
            label: Text(
              _newCategoryPath == null ? 'Välj kategori' : 'Kategori: $_newCategoryPath',
              overflow: TextOverflow.ellipsis,
            ),
          ),
        ),
        if (_newCategoryPath != null) ...[
          const SizedBox(height: 8),
          Container(
            width: double.infinity,
            padding: const EdgeInsets.all(12),
            decoration: BoxDecoration(
              color: theme.colorScheme.surfaceContainerHighest,
              borderRadius: BorderRadius.circular(12),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Vald kategori',
                  style: theme.textTheme.labelSmall
                      ?.copyWith(color: theme.colorScheme.onSurfaceVariant),
                ),
                const SizedBox(height: 4),
                Text(
                  _newCategoryPath!,
                  style:
                      theme.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w600),
                ),
              ],
            ),
          ),
          if (aiLabel != null) ...[
            const SizedBox(height: 8),
            Wrap(
              children: [
                ActionChip(
                  avatar: Icon(Icons.auto_awesome,
                      size: 14, color: Colors.green.shade700),
                  label: Text('AI-förslag: $aiLabel',
                      style: Theme.of(context).textTheme.labelSmall),
                  backgroundColor: Colors.green.shade50,
                  side: BorderSide(color: Colors.green.shade300),
                  visualDensity: VisualDensity.compact,
                  onPressed: widget.item.categorySuggestionId == null
                      ? null
                      : () => _openCreateCategoryPicker(
                            preselectedCategoryId: widget.item.categorySuggestionId,
                          ),
                ),
              ],
            ),
          ],
        ],
      ],
    );
  }

  Widget _buildQuantitySection(
    ThemeData theme,
    double? totalPreview,
    String? currentUnit,
  ) {
    return Column(
      children: [
        Row(
          children: [
            Expanded(
              child: TextField(
                controller: _quantityCtrl,
                keyboardType:
                    const TextInputType.numberWithOptions(decimal: true),
                decoration: const InputDecoration(
                  labelText: 'Mängd per förpackning',
                  border: OutlineInputBorder(),
                ),
                onChanged: (_) => setState(() {}),
              ),
            ),
            const SizedBox(width: 8),
            Expanded(
              child: TextField(
                controller: _unitCtrl,
                decoration: const InputDecoration(
                  labelText: 'Enhet',
                  border: OutlineInputBorder(),
                ),
                onChanged: (_) => setState(() {}),
              ),
            ),
          ],
        ),
        const SizedBox(height: 8),
        TextField(
          controller: _packageCountCtrl,
          keyboardType: const TextInputType.numberWithOptions(decimal: true),
          decoration: const InputDecoration(
            labelText: 'Antal förpackningar',
            border: OutlineInputBorder(),
          ),
          onChanged: (_) => setState(() {}),
        ),
        if (totalPreview != null &&
            currentUnit != null &&
            currentUnit.isNotEmpty) ...[
          const SizedBox(height: 8),
          Container(
            width: double.infinity,
            padding: const EdgeInsets.all(10),
            decoration: BoxDecoration(
              color: Colors.green.shade50,
              borderRadius: BorderRadius.circular(10),
              border: Border.all(color: Colors.green.shade200),
            ),
            child: Text(
              'Totalt: ${formatSwedishNumber(totalPreview)} $currentUnit '
              '(mängd × antal förpackningar).',
              style: theme.textTheme.bodySmall
                  ?.copyWith(color: Colors.green.shade800),
            ),
          ),
        ],
      ],
    );
  }

  // ── Statiska hjälpare ──────────────────────────────────────────────────────

  static String? _resolveAiLabel(ParsedReceiptItem item) {
    final path = item.categorySuggestionPath;
    if (path != null && path.isNotEmpty) return path;
    final name = item.categorySuggestionName;
    if (name != null && name.isNotEmpty) return name;
    return null;
  }

  static String? _resolveSuggestedProductLabel(ParsedReceiptItem item) {
    final suggested = item.suggestedProductName;
    if (suggested != null && suggested.isNotEmpty) {
      return normalizeProductName(suggested);
    }
    final matched = item.matchedProductName;
    if (matched != null && matched.isNotEmpty) {
      return normalizeProductName(matched);
    }
    return null;
  }
}
