import 'package:commons_core/commons_core.dart';
import 'package:flutter/material.dart';

import '../db/enums.dart';
import '../i18n/strings.g.dart';
import 'quantity_kind_l10n.dart';
import 'seed_glyph.dart';
import 'theme.dart';

/// Informal seed amounts, ascending: vibes → containers → seed/fruit forms.
/// ([QuantityKind.handful] is intentionally omitted — it overlaps with spoon.)
const seedScaleKinds = <QuantityKind>[
  QuantityKind.aFew,
  QuantityKind.teaspoon,
  QuantityKind.spoon,
  QuantityKind.packet,
  QuantityKind.cup,
  QuantityKind.jar,
  QuantityKind.sack,
  QuantityKind.cob,
  QuantityKind.pod,
  QuantityKind.ear,
  QuantityKind.head,
  QuantityKind.fruit,
  QuantityKind.bulb,
  QuantityKind.tuber,
  QuantityKind.bunch,
];

/// The amount units offered for each lot form. Living forms are counted as
/// whole individuals (their packaging is a separate [Presentation]); [bulb] also
/// allows grams. [pot]/[tray] are intentionally not offered anymore.
List<QuantityKind> kindsForType(LotType type) => switch (type) {
  LotType.seed => seedScaleKinds,
  LotType.seedling => const [QuantityKind.seedling],
  LotType.plant => const [QuantityKind.plant],
  LotType.tree => const [QuantityKind.tree],
  LotType.bulb => const [
    QuantityKind.bulb,
    QuantityKind.tuber,
    QuantityKind.grams,
  ],
  LotType.cutting => const [QuantityKind.cutting],
};

/// The human label for a lot form.
String lotTypeLabel(Translations t, LotType type) => switch (type) {
  LotType.seed => t.lotType.seed,
  LotType.seedling => t.lotType.seedling,
  LotType.plant => t.lotType.plant,
  LotType.tree => t.lotType.tree,
  LotType.bulb => t.lotType.bulb,
  LotType.cutting => t.lotType.cutting,
};

/// Living forms whose packaging ([Presentation]) is worth asking about.
bool typeHasPresentation(LotType type) =>
    type == LotType.seedling || type == LotType.plant || type == LotType.tree;

/// Form selector: a wrap of choice chips, one per [LotType].
class LotTypeSelector extends StatelessWidget {
  const LotTypeSelector({
    required this.value,
    required this.onChanged,
    super.key,
  });

  final LotType value;
  final ValueChanged<LotType> onChanged;

  @override
  Widget build(BuildContext context) {
    final t = context.t;
    return Wrap(
      spacing: 8,
      runSpacing: 8,
      children: [
        for (final type in LotType.values)
          ChoiceChip(
            key: Key('lotType.${type.name}'),
            selected: value == type,
            onSelected: (_) => onChanged(type),
            avatar: type == LotType.seed
                ? const SeedGlyph(SeedGlyphs.jars, size: 18)
                : Icon(iconForLotType(type), size: 18),
            label: Text(lotTypeLabel(t, type)),
          ),
      ],
    );
  }
}

/// Optional packaging selector for living lots. Tapping the selected chip again
/// clears it (packaging is optional).
class PresentationSelector extends StatelessWidget {
  const PresentationSelector({
    required this.value,
    required this.onChanged,
    super.key,
  });

  final Presentation? value;
  final ValueChanged<Presentation?> onChanged;

  @override
  Widget build(BuildContext context) {
    final t = context.t;
    return Wrap(
      spacing: 8,
      runSpacing: 8,
      children: [
        for (final p in Presentation.values)
          ChoiceChip(
            key: Key('presentation.${p.name}'),
            selected: value == p,
            onSelected: (sel) => onChanged(sel ? p : null),
            label: Text(presentationLabel(t, p)),
          ),
      ],
    );
  }
}

/// The human label for a packaging [Presentation].
String presentationLabel(Translations t, Presentation p) => switch (p) {
  Presentation.pot => t.presentation.pot,
  Presentation.tray => t.presentation.tray,
  Presentation.plug => t.presentation.plug,
  Presentation.bareRoot => t.presentation.bareRoot,
  Presentation.rootBall => t.presentation.rootBall,
};

/// A horizontal scale of large unit icons + an optional number stepper. Emits a
/// [Quantity] (or null while nothing is picked) via [onChanged].
class QuantityPicker extends StatefulWidget {
  const QuantityPicker({
    required this.type,
    required this.onChanged,
    this.value,
    super.key,
  });

  final LotType type;
  final Quantity? value;
  final ValueChanged<Quantity?> onChanged;

  @override
  State<QuantityPicker> createState() => _QuantityPickerState();
}

class _QuantityPickerState extends State<QuantityPicker> {
  QuantityKind? _kind;
  final _countController = TextEditingController();

  @override
  void initState() {
    super.initState();
    _kind = widget.value?.kind;
    final c = widget.value?.count;
    if (c != null) _countController.text = _fmt(c);
  }

  @override
  void didUpdateWidget(QuantityPicker old) {
    super.didUpdateWidget(old);
    // Switching seed/plant, or the owner clearing the value, drops a stale
    // selection. We only update local fields here (no onChanged during build);
    // the owner clears its own value alongside the type change.
    if (widget.value == null && _kind != null) {
      _kind = null;
      _countController.clear();
    } else if (widget.type != old.type &&
        _kind != null &&
        !kindsForType(widget.type).contains(_kind)) {
      _kind = null;
      _countController.clear();
    }
  }

  @override
  void dispose() {
    _countController.dispose();
    super.dispose();
  }

  void _emit() {
    final kind = _kind;
    if (kind == null) {
      widget.onChanged(null);
      return;
    }
    final n = num.tryParse(_countController.text.trim().replaceAll(',', '.'));
    widget.onChanged(Quantity(kind: kind, count: kind.countable ? n : null));
  }

  void _select(QuantityKind kind) {
    setState(() => _kind = kind);
    _emit();
  }

  void _bump(int delta) {
    final current = int.tryParse(_countController.text.trim()) ?? 0;
    final next = (current + delta).clamp(0, 9999);
    _countController.text = next == 0 ? '' : '$next';
    _emit();
  }

  @override
  Widget build(BuildContext context) {
    final t = context.t;
    final kinds = kindsForType(widget.type);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // Wrap (not a horizontal scroll) so every unit stays visible.
        Wrap(
          spacing: 4,
          runSpacing: 4,
          children: [
            for (final kind in kinds)
              _ScaleItem(
                kind: kind,
                label: unitLabel(t, kind),
                selected: _kind == kind,
                onTap: () => _select(kind),
              ),
          ],
        ),
        if (_kind?.countable ?? false) ...[
          const SizedBox(height: 8),
          Row(
            children: [
              IconButton.filledTonal(
                onPressed: () => _bump(-1),
                icon: const Icon(Icons.remove),
              ),
              SizedBox(
                width: 64,
                child: TextField(
                  key: const Key('quantity.count'),
                  controller: _countController,
                  textAlign: TextAlign.center,
                  keyboardType: TextInputType.number,
                  decoration: const InputDecoration(isDense: true),
                  onChanged: (_) => _emit(),
                ),
              ),
              IconButton.filledTonal(
                onPressed: () => _bump(1),
                icon: const Icon(Icons.add),
              ),
              const SizedBox(width: 12),
              Expanded(
                child: Text(
                  unitLabel(t, _kind!),
                  style: Theme.of(context).textTheme.bodyLarge,
                ),
              ),
            ],
          ),
        ],
      ],
    );
  }
}

String _fmt(num n) =>
    n == n.roundToDouble() ? n.toInt().toString() : n.toString();

class _ScaleItem extends StatelessWidget {
  const _ScaleItem({
    required this.kind,
    required this.label,
    required this.selected,
    required this.onTap,
  });

  final QuantityKind kind;
  final String label;
  final bool selected;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) {
    final color = selected ? seedGreenDark : Colors.black54;
    return InkWell(
      onTap: onTap,
      borderRadius: BorderRadius.circular(10),
      child: Container(
        width: 68,
        padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 4),
        decoration: BoxDecoration(
          color: selected ? seedGreen.withValues(alpha: 0.15) : null,
          borderRadius: BorderRadius.circular(10),
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            QuantityKindIcon(kind, size: 30, color: color),
            const SizedBox(height: 4),
            Text(
              label,
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
              style: TextStyle(fontSize: 11, color: color),
            ),
          ],
        ),
      ),
    );
  }
}
