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

import '../../../core/api/api_error_mapper.dart';
import '../../../core/api/api_paths.dart';
import '../../../core/api/api_providers.dart';
import '../../../core/l10n/l10n.dart';
import '../../../core/ui/async_state_views.dart';
import '../../../core/utils/display_labels.dart';
import '../../auth/data/auth_providers.dart';
import '../../pantry/data/pantry_providers.dart';
import '../domain/inventory_item.dart';
import '../data/inventory_providers.dart';
import 'swipeable_inventory_tile.dart';

class InventoryScreen extends ConsumerStatefulWidget {
  const InventoryScreen({super.key});

  @override
  ConsumerState<InventoryScreen> createState() => _InventoryScreenState();
}

class _InventoryScreenState extends ConsumerState<InventoryScreen> {
  final Set<int> _selectedIds = <int>{};
  static const _sortByDisplayedCategory = 'l1CategoryAsc';
  bool _backfillTriggered = false;

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

  Future<void> _triggerCategoryBackfill() async {
    if (_backfillTriggered) return;
    _backfillTriggered = true;
    try {
      final token = await ref.read(authStateProvider.future);
      final api = ref.read(apiClientProvider);
      await api.postJson(ProductApiPaths.backfillMineCategories, token: token);
      ref.invalidate(inventoryProvider);
      ref.invalidate(pantryProvider);
    } catch (_) {
      // Ignorera fel här för att inte blockera vyn.
    }
  }

  static const _locationOptions = <String>['', 'Kyl', 'Frys', 'Skafferi'];

  static const _weightOrVolumeUnits = <String>{
    'g', 'gram', 'mg', 'milligram', 'hg', 'hektogram', 'kg', 'kilo', 'kilogram',
    'ml', 'milliliter', 'cl', 'centiliter', 'dl', 'deciliter', 'l', 'liter',
  };

  List<({String value, String label})> _sortOptions(BuildContext context) => [
    (value: '', label: context.l10n.inventorySortLatest),
    (value: 'nameAsc', label: context.l10n.inventorySortNameAsc),
    (value: 'bestBeforeAsc', label: context.l10n.inventorySortBestBeforeAsc),
    (value: 'bestBeforeDesc', label: context.l10n.inventorySortBestBeforeDesc),
    (value: _sortByDisplayedCategory, label: 'Kategori (A-O)'),
  ];

  void _startSelection(int id) {
    setState(() {
      _selectedIds.add(id);
    });
  }

  void _toggleSelection(int id) {
    setState(() {
      if (_selectedIds.contains(id)) {
        _selectedIds.remove(id);
      } else {
        _selectedIds.add(id);
      }
    });
  }

  void _clearSelection() {
    setState(() {
      _selectedIds.clear();
    });
  }

  void _selectAllVisible(List<InventoryItem> visibleItems) {
    setState(() {
      _selectedIds
        ..clear()
        ..addAll(visibleItems.map<int>((item) => item.id));
    });
  }

  bool _isWeightOrVolumeUnit(String unit) {
    return _weightOrVolumeUnits.contains(unit.trim().toLowerCase());
  }

  String _preferredUnit(List<String> units) {
    for (final unit in units) {
      if (_isWeightOrVolumeUnit(unit)) return unit;
    }
    return units.first;
  }

  Future<String?> _askMergeTargetUnit(BuildContext context, List<String> units) async {
    if (units.isEmpty) return null;
    if (units.length == 1) return units.first;

    var selected = _preferredUnit(units);

    return showDialog<String>(
      context: context,
      builder: (dialogContext) => StatefulBuilder(
        builder: (dialogContext, setDialogState) => AlertDialog(
          title: const Text('Välj enhet för merge'),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Text(
                'Poster har olika enhet. Välj vilken enhet den sammanslagna posten ska använda.',
              ),
              const SizedBox(height: 12),
              DropdownButtonFormField<String>(
                initialValue: selected,
                decoration: const InputDecoration(
                  labelText: 'Enhet',
                  border: OutlineInputBorder(),
                ),
                items: units
                    .map(
                      (unit) => DropdownMenuItem<String>(
                        value: unit,
                        child: Text(unit),
                      ),
                    )
                    .toList(),
                onChanged: (value) {
                  if (value == null) return;
                  setDialogState(() => selected = value);
                },
              ),
            ],
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(dialogContext),
              child: Text(context.l10n.cancelAction),
            ),
            FilledButton(
              onPressed: () => Navigator.pop(dialogContext, selected),
              child: const Text('Merge'),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _mergeSelected(BuildContext context, List<InventoryItem> allItems) async {
    final selectedItems = allItems
        .where((item) => _selectedIds.contains(item.id))
        .toList();

    if (selectedItems.length < 2) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Välj minst två poster för merge.')),
      );
      return;
    }

    final productIds = selectedItems.map((item) => item.productId).toSet();
    if (productIds.length > 1) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Valda poster måste ha samma produkt för merge.')),
      );
      return;
    }

    final units = <String>[];
    final seenUnits = <String>{};
    for (final item in selectedItems) {
      final unit = item.unit.trim();
      final key = unit.toLowerCase();
      if (seenUnits.add(key)) {
        units.add(unit);
      }
    }

    final targetUnit = await _askMergeTargetUnit(context, units);
    if (!context.mounted || targetUnit == null) return;

    try {
      final token = await ref.read(authStateProvider.future);
      final ids = selectedItems.map<int>((item) => item.id).toList();
      await ref.read(inventoryRepositoryProvider).mergeInventoryItems(
            ids,
            targetUnit: units.length > 1 ? targetUnit : null,
            token: token,
          );
      ref.invalidate(inventoryProvider);
      if (!mounted) return;
      setState(() => _selectedIds.clear());
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Poster sammanslagna.')),
      );
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)),
      );
    }
  }

  Future<void> _deleteSelected(BuildContext context, List<InventoryItem> allItems) async {
    final ids = allItems
        .where((item) => _selectedIds.contains(item.id))
        .map<int>((item) => item.id)
        .toList();
    if (ids.isEmpty) return;

    final confirmed = await showDialog<bool>(
      context: context,
      builder: (dialogContext) => AlertDialog(
        title: const Text('Ta bort markerade poster'),
        content: Text('Vill du verkligen ta bort ${ids.length} markerade poster?'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(dialogContext, false),
            child: Text(context.l10n.cancelAction),
          ),
          FilledButton(
            onPressed: () => Navigator.pop(dialogContext, true),
            child: Text(context.l10n.deleteAction),
          ),
        ],
      ),
    );

    if (confirmed != true || !context.mounted) return;

    try {
      final token = await ref.read(authStateProvider.future);
      await ref.read(inventoryRepositoryProvider).bulkDeleteInventoryItems(ids, token: token);
      ref.invalidate(inventoryProvider);
      if (!mounted) return;
      setState(() => _selectedIds.clear());
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('${ids.length} poster borttagna.')),
      );
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)),
      );
    }
  }

  Future<void> _openBulkActions(BuildContext context, List<InventoryItem> allItems) async {
    if (_selectedIds.isEmpty) return;
    final action = await showDialog<String>(
      context: context,
      builder: (dialogContext) => AlertDialog(
        title: const Text('Hantera markerade poster'),
        content: Text('Du har markerat ${_selectedIds.length} poster. Välj åtgärd.'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(dialogContext),
            child: Text(context.l10n.cancelAction),
          ),
          OutlinedButton(
            onPressed: () => Navigator.pop(dialogContext, 'delete'),
            child: Text(context.l10n.deleteAction),
          ),
          FilledButton(
            onPressed: () => Navigator.pop(dialogContext, 'merge'),
            child: const Text('Merge'),
          ),
        ],
      ),
    );

    if (action == 'merge') {
      await _mergeSelected(context, allItems);
    } else if (action == 'delete') {
      await _deleteSelected(context, allItems);
    }
  }

  List<InventoryItem> _sortedVisibleItems(List<InventoryItem> items, String sort) {
    final visibleItems = [...items];
    if (sort == _sortByDisplayedCategory) {
      final displayedCategoryById = {
        for (final item in visibleItems)
          item.id: categoryChipText(
            categoryPath: item.categoryPath,
            fallbackL1: item.l1Category,
          ).label.toLowerCase(),
      };
      visibleItems.sort((a, b) {
        final aCategory = displayedCategoryById[a.id] ?? '';
        final bCategory = displayedCategoryById[b.id] ?? '';
        final byCategory = aCategory.compareTo(bCategory);
        if (byCategory != 0) return byCategory;
        return a.displayName.toLowerCase().compareTo(b.displayName.toLowerCase());
      });
    }
    return visibleItems;
  }

  Widget _buildFilterSection(BuildContext context, String location, String sort) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(12, 12, 12, 4),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            context.l10n.inventoryFilterAndSort,
            style: const TextStyle(fontWeight: FontWeight.w600),
          ),
          const SizedBox(height: 8),
          Wrap(
            spacing: 8,
            runSpacing: 8,
            children: _locationOptions
                .map(
                  (option) => ChoiceChip(
                    label: Text(option.isEmpty ? context.l10n.inventoryAllFilter : option),
                    selected: location == option,
                    onSelected: (_) => ref
                        .read(inventoryLocationFilterProvider.notifier)
                        .setValue(option),
                  ),
                )
                .toList(),
          ),
          const SizedBox(height: 8),
          DropdownButtonFormField<String>(
            initialValue: sort,
            isExpanded: true,
            decoration: InputDecoration(
              labelText: context.l10n.inventorySortLabel,
              border: const OutlineInputBorder(),
            ),
            items: _sortOptions(context)
                .map(
                  (option) => DropdownMenuItem<String>(
                    value: option.value,
                    child: Text(option.label),
                  ),
                )
                .toList(),
            onChanged: (value) {
              ref.read(inventorySortFilterProvider.notifier).setValue(value ?? '');
            },
          ),
        ],
      ),
    );
  }

  Widget _buildHeaderSection(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(12, 12, 12, 4),
      child: Card(
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(context.l10n.profileInventoryTab, style: Theme.of(context).textTheme.titleMedium),
              const SizedBox(height: 8),
              Text(
                'Din personliga inventarie. Här ser du sådant du faktiskt äger, kan sortera på plats och bäst före, och flytta vidare till recept eller baslager.',
                style: Theme.of(context).textTheme.bodyMedium,
              ),
              const SizedBox(height: 8),
              const Wrap(
                spacing: 8,
                runSpacing: 8,
                children: [
                  Chip(label: Text('User-scope')),
                  Chip(label: Text('Bäst före')),
                  Chip(label: Text('Swipa för +/-')),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildSelectedSection(
    BuildContext context,
    List<InventoryItem> visibleItems,
    List<InventoryItem> allItems,
  ) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(12, 4, 12, 4),
      child: Card(
        child: Padding(
          padding: const EdgeInsets.all(12),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                '${_selectedIds.length} markerade poster',
                style: Theme.of(context).textTheme.titleSmall,
              ),
              const SizedBox(height: 8),
              Wrap(
                spacing: 8,
                runSpacing: 8,
                children: [
                  FilledButton.icon(
                    onPressed: () => _openBulkActions(context, allItems),
                    icon: const Icon(Icons.playlist_add_check),
                    label: const Text('Hantera markerade'),
                  ),
                  OutlinedButton.icon(
                    onPressed: () => _selectAllVisible(visibleItems),
                    icon: const Icon(Icons.select_all),
                    label: const Text('Markera alla synliga'),
                  ),
                  OutlinedButton.icon(
                    onPressed: _clearSelection,
                    icon: const Icon(Icons.deselect),
                    label: const Text('Avmarkera'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildEmptyState(BuildContext context) {
    return EmptyStateView(title: context.l10n.inventoryEmpty);
  }

  @override
  Widget build(BuildContext context) {
    final location = ref.watch(inventoryLocationFilterProvider);
    final sort = ref.watch(inventorySortFilterProvider);
    final inventoryAsync = ref.watch(inventoryProvider);

    return inventoryAsync.when(
      loading: () => LoadingStateView(label: context.l10n.inventoryLoading),
      error: (e, _) => ErrorStateView(
        message: mapErrorToUserMessage(e, context),
        onRetry: () => ref.invalidate(inventoryProvider),
      ),
      data: (items) {
        final itemIds = items.map((item) => item.id).toSet();
        final staleIds = _selectedIds.where((id) => !itemIds.contains(id)).toList();
        if (staleIds.isNotEmpty) {
          WidgetsBinding.instance.addPostFrameCallback((_) {
            if (!mounted) return;
            setState(() {
              _selectedIds.removeWhere((id) => !itemIds.contains(id));
            });
          });
        }

        final visibleItems = _sortedVisibleItems(items, sort);

        if (visibleItems.isEmpty) {
          return Stack(
            children: [
              ListView(
                key: const PageStorageKey<String>('inventory-empty-list'),
                padding: const EdgeInsets.only(bottom: 88),
                children: [
                  _buildHeaderSection(context),
                  if (_selectedIds.isNotEmpty) _buildSelectedSection(context, visibleItems, items),
                  _buildFilterSection(context, location, sort),
                  _buildEmptyState(context),
                ],
              ),
              Positioned(
                right: 16,
                bottom: 16,
                child: FloatingActionButton.extended(
                  heroTag: 'inventory_add_empty',
                  onPressed: () => context.push('/inventory/create'),
                  icon: const Icon(Icons.add),
                  label: Text(context.l10n.addAction),
                ),
              ),
            ],
          );
        }
        return Stack(
          children: [
            ListView.separated(
              key: const PageStorageKey<String>('inventory-main-list'),
              padding: const EdgeInsets.only(bottom: 88),
              itemCount: visibleItems.length + (_selectedIds.isEmpty ? 2 : 3),
              separatorBuilder: (_, __) => const Divider(height: 1),
              itemBuilder: (context, index) {
                if (index == 0) return _buildFilterSection(context, location, sort);
                if (index == 1) return _buildHeaderSection(context);
                if (_selectedIds.isNotEmpty && index == 2) {
                  return _buildSelectedSection(context, visibleItems, items);
                }
                final item = visibleItems[index - (_selectedIds.isEmpty ? 2 : 3)];
                return SwipeableInventoryTile(
                  item: item,
                  selectableMode: _selectedIds.isNotEmpty,
                  selected: _selectedIds.contains(item.id),
                  onToggleSelected: () => _toggleSelection(item.id),
                  onLongPress: () {
                    if (_selectedIds.isEmpty) {
                      _startSelection(item.id);
                    } else {
                      _toggleSelection(item.id);
                    }
                  },
                );
              },
            ),
            Positioned(
              right: 16,
              bottom: 16,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  FloatingActionButton.extended(
                    heroTag: 'inventory_add',
                    onPressed: () => context.push('/inventory/create'),
                    icon: const Icon(Icons.add),
                    label: Text(context.l10n.addAction),
                  ),
                  const SizedBox(height: 8),
                  FloatingActionButton.extended(
                    heroTag: 'inventory_go_recipes',
                    onPressed: () => context.go('/recipes'),
                    icon: const Icon(Icons.restaurant_menu),
                    label: Text(context.l10n.inventoryRecipesAction),
                  ),
                ],
              ),
            ),
          ],
        );
      },
    );
  }
}


