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/utils/formatters.dart';
import '../../../core/forms/form_options.dart';
import '../../../core/l10n/l10n.dart';
import '../../../core/ui/async_state_views.dart';
import '../../../core/ui/category_then_product_picker.dart';
import '../../../core/ui/product_picker_field.dart' show ProductOption;
import '../../../core/ui/searchable_category_field.dart' show CategorySelectOption;
import '../../auth/data/auth_providers.dart';
import '../../admin/domain/admin_category_node.dart';
import '../data/inventory_providers.dart';
import '../domain/inventory_item.dart';
import 'inventory_category_helpers.dart';
import 'inventory_category_product_section.dart';
import 'inventory_product_mutations.dart';

class InventoryEditScreen extends ConsumerStatefulWidget {
  final int itemId;

  const InventoryEditScreen({super.key, required this.itemId});

  @override
  ConsumerState<InventoryEditScreen> createState() =>
      _InventoryEditScreenState();
}

class _InventoryEditScreenState extends ConsumerState<InventoryEditScreen> {
  final _formKey = GlobalKey<FormState>();
  final _quantityController = TextEditingController();
  final _unitController = TextEditingController();
  final _locationController = TextEditingController();
  final _brandController = TextEditingController();
  final _commentController = TextEditingController();

  bool _initialized = false;
  bool _loadingProducts = false;
  bool _opened = false;
  DateTime? _purchaseDate;
  DateTime? _bestBeforeDate;
  bool _saving = false;
  int? _selectedProductId;
  int? _selectedCategoryId;
  List<Map<String, dynamic>> _products = [];
  List<AdminCategoryNode> _categoryTree = [];
  List<CategorySelectOption> _categoryOptions = [];
  InventoryCategoryBranchIndex? _categoryBranchIndex;
  final _sortedProductsCache = InventorySortedProductsCache();

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

  void _initControllers(InventoryItem item) {
    _initialized = true;
    _selectedProductId = item.productId;
    _quantityController.text = item.quantity.toString();
    _unitController.text = item.unit;
    _locationController.text = item.location ?? '';
    _brandController.text = item.brand ?? '';
    _commentController.text = item.comment ?? '';
    _opened = item.opened;
    _purchaseDate =
        item.purchaseDate != null ? DateTime.tryParse(item.purchaseDate!) : null;
    _bestBeforeDate = item.bestBeforeDate != null
        ? DateTime.tryParse(item.bestBeforeDate!)
        : null;
  }

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

  Future<void> _loadProductsAndCategories() async {
    setState(() => _loadingProducts = true);
    try {
      final token = await ref.read(authStateProvider.future);
      final api = ref.read(apiClientProvider);
      final results = await Future.wait<dynamic>([
        api.getJson(ProductApiPaths.mine, token: token),
        api.getJson(CategoryApiPaths.tree, token: token),
      ]);

      final productData = results[0];
      final categoryData = results[1];
      final productList = productData is List<dynamic>
          ? productData
          : (productData is Map<String, dynamic> && productData['items'] is List<dynamic>)
              ? productData['items'] as List<dynamic>
              : const <dynamic>[];
      final categoryList = categoryData is List<dynamic>
          ? categoryData
          : (categoryData is Map<String, dynamic> && categoryData['items'] is List<dynamic>)
              ? categoryData['items'] as List<dynamic>
              : const <dynamic>[];

      final products = productList.map((e) => e as Map<String, dynamic>).toList();
      final categoryTree = categoryList
          .map((e) => AdminCategoryNode.fromJson(Map<String, dynamic>.from(e as Map)))
          .toList();
      final categoryOptions = _flattenCategoryOptions(categoryTree);

      if (!mounted) return;
      setState(() {
        _products = products;
        _categoryTree = categoryTree;
        _categoryOptions = categoryOptions;
        _categoryBranchIndex = InventoryCategoryBranchIndex.fromTree(categoryTree);

        final selected = _selectedProduct();
        if (selected != null) {
          _selectedCategoryId = (selected['categoryId'] as num?)?.toInt();
        }
      });
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)),
        );
      }
    } finally {
      if (mounted) setState(() => _loadingProducts = false);
    }
  }

  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;
  }

  Map<String, dynamic>? _selectedProduct() {
    if (_selectedProductId == null) return null;
    for (final product in _products) {
      if (tryParseDynamicInt(product['id']) == _selectedProductId) {
        return product;
      }
    }
    return null;
  }

  Set<int>? _selectedCategoryBranchIds() {
    final selectedId = _selectedCategoryId;
    if (selectedId == null) return null;
    return _categoryBranchIndex?.branchIdsFor(selectedId) ?? {selectedId};
  }

  List<ProductOption> _productOptions() {
    final selectedCategoryIds = _selectedCategoryBranchIds();
    final source = _selectedCategoryId == null
        ? _products
        : _products
            .where(
              (p) => productInSelectedBranch(
                productCategoryId: tryParseDynamicInt(p['categoryId']),
                selectedCategoryIds: selectedCategoryIds,
              ),
            )
            .toList();

    final selected = _selectedProduct();
    final withSelected = [...source];
    if (selected != null && !withSelected.any((p) => (p['id'] as num).toInt() == _selectedProductId)) {
      withSelected.add(selected);
    }

    final sorted = _sortedProductsCache.sort(withSelected);
    return sorted
        .where((p) => tryParseDynamicInt(p['id']) != null)
        .map(
          (p) => (
            id: tryParseDynamicInt(p['id'])!,
            name: (p['canonicalName'] ?? p['name'] ?? '').toString(),
            categoryId: tryParseDynamicInt(p['categoryId']),
          ),
        )
        .toList();
  }

  Future<void> _pickCategory() async {
    final selected = await CategoryThenProductPicker.showCategorySheet(
      context,
      categoryTree: _categoryTree,
      preselectedCategoryId: _selectedCategoryId,
    );
    if (selected == null || !mounted) return;
    setState(() {
      _selectedCategoryId = selected.id;
    });
  }

  Future<void> _syncSelectedProductCategory(String? token) async {
    await syncSelectedProductCategory(
      ref: ref,
      token: token,
      selectedProductId: _selectedProductId,
      selectedCategoryId: _selectedCategoryId,
      products: _products,
      tryParseDynamicInt: tryParseDynamicInt,
      setProducts: (updated) {
        if (!mounted) return;
        setState(() => _products = updated);
      },
    );
  }

  Future<void> _pickDate(bool isBestBefore) async {
    final picked = await showDatePicker(
      context: context,
      initialDate: DateTime.now(),
      firstDate: DateTime(2000),
      lastDate: DateTime(2100),
    );
    if (picked != null) {
      setState(() {
        if (isBestBefore) {
          _bestBeforeDate = picked;
        } else {
          _purchaseDate = picked;
        }
      });
    }
  }

  Future<ProductOption?> _createProductInSelectedCategory(String rawName) async {
    return createProductInSelectedCategory(
      ref: ref,
      context: context,
      rawName: rawName,
      selectedCategoryId: _selectedCategoryId,
      products: _products,
      tryParseDynamicInt: tryParseDynamicInt,
      setProducts: (updated) {
        if (!mounted) return;
        setState(() => _products = updated);
      },
    );
  }

  Future<void> _save() async {
    if (_selectedProductId == null) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(context.l10n.inventorySelectProduct)),
      );
      return;
    }

    if (!_formKey.currentState!.validate()) return;
    setState(() => _saving = true);
    try {
      final token = await ref.read(authStateProvider.future);
      await _syncSelectedProductCategory(token);
      final body = <String, dynamic>{
        'productId': _selectedProductId,
        'quantity':
            double.parse(_quantityController.text.trim().replaceAll(',', '.')),
        'unit': _unitController.text.trim(),
        'location': _locationController.text.trim().isEmpty
            ? null
            : _locationController.text.trim(),
        'brand': _brandController.text.trim().isEmpty
            ? null
            : _brandController.text.trim(),
        if (_purchaseDate != null)
          'purchaseDate': _purchaseDate!.toIso8601String(),
        if (_bestBeforeDate != null)
          'bestBeforeDate': _bestBeforeDate!.toIso8601String(),
        'opened': _opened,
        'comment': _commentController.text.trim().isEmpty
            ? null
            : _commentController.text.trim(),
      };
      await ref
          .read(inventoryRepositoryProvider)
          .updateInventoryItem(widget.itemId, body, token: token);
      ref.invalidate(inventoryDetailProvider(widget.itemId));
      ref.invalidate(inventoryProvider);
      if (mounted) context.pop();
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context)
            .showSnackBar(buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)));
      }
    } finally {
      if (mounted) setState(() => _saving = false);
    }
  }

  String _formatDate(DateTime? dt) => formatDate(dt, fallback: context.l10n.selectDateLabel);

  @override
  Widget build(BuildContext context) {
    final itemAsync = ref.watch(inventoryDetailProvider(widget.itemId));

    return Scaffold(
      appBar: AppBar(title: Text(context.l10n.inventoryEditTitle)),
      body: itemAsync.when(
        loading: () => LoadingStateView(label: context.l10n.loadingLabel),
        error: (e, _) => ErrorStateView(
          message: mapErrorToUserMessage(e, context),
          onRetry: () => ref.invalidate(inventoryDetailProvider(widget.itemId)),
        ),
        data: (item) {
          if (!_initialized) _initControllers(item);
          return Form(
            key: _formKey,
            child: ListView(
              padding: const EdgeInsets.all(16),
              children: [
                Text(item.displayName, style: Theme.of(context).textTheme.titleMedium),
                if (item.categoryPath != null && item.categoryPath!.trim().isNotEmpty) ...[
                  const SizedBox(height: 4),
                  Text(item.categoryPath!, style: Theme.of(context).textTheme.bodySmall),
                ],
                const SizedBox(height: 16),
                InventoryCategoryProductSection(
                  categoryOptions: _categoryOptions,
                  selectedCategoryId: _selectedCategoryId,
                  categorySearchLabel: 'Kategori (sökbar)',
                  onCategoryChanged: (value) {
                    if (value == null) return;
                    setState(() {
                      _selectedCategoryId = int.tryParse(value);
                      final selectedCategoryIds = _selectedCategoryBranchIds();
                      final current = _selectedProduct();
                      final currentCategoryId = tryParseDynamicInt(current?['categoryId']);
                      if (!productInSelectedBranch(
                        productCategoryId: currentCategoryId,
                        selectedCategoryIds: selectedCategoryIds,
                      )) {
                        _selectedProductId = null;
                      }
                    });
                  },
                  onPickCategory: _pickCategory,
                  pickCategoryLabel: 'Välj kategori',
                  onClearCategory: () {
                    setState(() {
                      _selectedCategoryId = null;
                    });
                  },
                  clearCategoryLabel: 'Rensa kategori',
                  canPickCategory: !_loadingProducts && !_saving && _categoryTree.isNotEmpty,
                  canClearCategory: !_saving,
                  productOptions: _productOptions(),
                  selectedProductId: _selectedProductId,
                  onProductChanged: (value) => setState(() => _selectedProductId = value),
                  onCreateProduct: _selectedCategoryId == null ? null : _createProductInSelectedCategory,
                  isLoadingProducts: _loadingProducts,
                  productEnabled: !_saving,
                  productLabel: context.l10n.inventoryProductLabel,
                ),
                Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Expanded(
                      flex: 2,
                      child: TextFormField(
                        controller: _quantityController,
                        decoration: const InputDecoration(
                          labelText: 'Mängd *',
                          border: OutlineInputBorder(),
                        ),
                        keyboardType: const TextInputType.numberWithOptions(
                            decimal: true),
                        enabled: !_saving,
                        validator: (v) {
                          if (v == null || v.trim().isEmpty) {
                            return 'Ange mängd';
                          }
                          if (double.tryParse(
                                  v.trim().replaceAll(',', '.')) ==
                              null) {
                            return 'Ogiltigt tal';
                          }
                          return null;
                        },
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      child: DropdownButtonFormField<String>(
                        initialValue: _unitController.text.trim().isEmpty
                            ? null
                            : _unitController.text.trim(),
                        isExpanded: true,
                        decoration: InputDecoration(
                          labelText: context.l10n.unitLabel,
                          border: const OutlineInputBorder(),
                        ),
                        items: unitOptions
                            .map(
                              (option) => DropdownMenuItem<String>(
                                value: option.value,
                                child: Text(option.label, overflow: TextOverflow.ellipsis),
                              ),
                            )
                            .toList(),
                        onChanged: _saving
                            ? null
                            : (value) =>
                                setState(() => _unitController.text = value ?? ''),
                        validator: (v) => (v == null || v.trim().isEmpty)
                            ? context.l10n.quantityHint
                            : null,
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 12),
                DropdownButtonFormField<String>(
                  initialValue: _locationController.text.trim().isEmpty
                      ? null
                      : _locationController.text.trim(),
                  isExpanded: true,
                  decoration: InputDecoration(
                    labelText: context.l10n.locationLabel,
                    border: const OutlineInputBorder(),
                  ),
                  items: inventoryLocationOptions
                      .map(
                        (location) => DropdownMenuItem<String>(
                          value: location,
                          child: Text(location),
                        ),
                      )
                      .toList(),
                  onChanged: _saving
                      ? null
                      : (value) =>
                          setState(() => _locationController.text = value ?? ''),
                ),
                const SizedBox(height: 12),
                TextFormField(
                  controller: _brandController,
                decoration: InputDecoration(
                  labelText: context.l10n.brandLabel,
                  border: const OutlineInputBorder(),
                ),
                enabled: !_saving,
              ),
                const SizedBox(height: 12),
                Row(
                  children: [
                    Expanded(
                      child: OutlinedButton.icon(
                        onPressed: _saving ? null : () => _pickDate(false),
                        icon: const Icon(Icons.calendar_today, size: 16),
                        label: Text(
                          '${context.l10n.inventoryPurchaseDatePrefix}${_formatDate(_purchaseDate)}',
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      child: OutlinedButton.icon(
                        onPressed: _saving ? null : () => _pickDate(true),
                        icon: const Icon(Icons.event_available, size: 16),
                        label: Text(
                          '${context.l10n.inventoryBestBeforeDatePrefix}${_formatDate(_bestBeforeDate)}',
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                    ),
                  ],
                ),
                CheckboxListTile(
                  title: Text(context.l10n.openedLabel),
                  value: _opened,
                  onChanged: _saving
                      ? null
                      : (v) => setState(() => _opened = v ?? false),
                  controlAffinity: ListTileControlAffinity.leading,
                  contentPadding: EdgeInsets.zero,
                ),
                TextFormField(
                  controller: _commentController,
                  decoration: InputDecoration(
                    labelText: context.l10n.commentLabel,
                    border: const OutlineInputBorder(),
                  ),
                  maxLines: 2,
                  enabled: !_saving,
                ),
                const SizedBox(height: 24),
                FilledButton(
                  onPressed: _saving ? null : _save,
                  child: _saving
                      ? const SizedBox(
                          height: 20,
                          width: 20,
                          child: CircularProgressIndicator(
                              strokeWidth: 2, color: Colors.white),
                        )
                      : Text(context.l10n.saveAction),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

