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

/// Schmaler Kamera-Stripe mit Torch- und Manual-Entry-Button sowie
/// Zoom-Steuerung. Geteilt zwischen Beladen-Phase und Filial-Abholung.
///
/// Wichtig: sollte **einmal** und außerhalb eines `PageView` gemountet
/// werden, damit der Kamera-Stream beim Wischen nicht abreißt (eine einzige
/// Kamera-Instanz pro Page-Lebenszyklus).
class ArticleScannerStripe extends StatefulWidget {
  const ArticleScannerStripe({
    super.key,
    required this.onBarcode,
    required this.onManualEntry,
  });

  /// Roh-Wert eines erkannten Barcodes (bereits getrimmt, dedupliziert).
  final void Function(String code) onBarcode;

  /// Tap auf das Tastatur-Icon → Aufrufer öffnet den Manual-Entry-Dialog.
  final VoidCallback onManualEntry;

  @override
  State<ArticleScannerStripe> createState() => _ArticleScannerStripeState();
}

class _ArticleScannerStripeState extends State<ArticleScannerStripe> {
  late final MobileScannerController _scanner = MobileScannerController(
    detectionSpeed: DetectionSpeed.normal,
    formats: const [
      BarcodeFormat.ean13,
      BarcodeFormat.ean8,
      BarcodeFormat.code128,
      BarcodeFormat.code39,
      BarcodeFormat.qrCode,
    ],
  );

  /// Dedupliziert Detections derselben Tastendruck-Geste: der Scanner liest
  /// dasselbe Code-Bild viele Frames lang. Nur wenn der Code für
  /// `_minRepeatGap` lang nicht gesehen wurde, lassen wir ihn erneut zu.
  String? _lastCode;
  DateTime _lastEmit = DateTime.fromMillisecondsSinceEpoch(0);
  static const Duration _minRepeatGap = Duration(milliseconds: 1200);

  /// Schrittweite der `-` / `+`-Buttons im normalisierten Zoom-Bereich
  /// [0.0, 1.0]. 5% pro Tastendruck — fühlt sich auf einem 6"-Display
  /// natürlich an, ohne dass der Fahrer zehnmal tappen muss.
  static const double _zoomStep = 0.05;

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

  void _onDetect(BarcodeCapture capture) {
    if (capture.barcodes.isEmpty) return;
    final raw = capture.barcodes.first.rawValue?.trim();
    if (raw == null || raw.isEmpty) return;
    final now = DateTime.now();
    if (raw == _lastCode && now.difference(_lastEmit) < _minRepeatGap) {
      return;
    }
    _lastCode = raw;
    _lastEmit = now;
    widget.onBarcode(raw);
  }

  Future<void> _setZoom(double normalized) async {
    final clamped = normalized.clamp(0.0, 1.0);
    await _scanner.setZoomScale(clamped);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(
          height: 140,
          child: Stack(
            children: [
              Positioned.fill(
                child: MobileScanner(
                  controller: _scanner,
                  onDetect: _onDetect,
                  errorBuilder: (context, error) {
                    return Container(
                      color: Colors.black,
                      child: Center(
                        child: Padding(
                          padding: const EdgeInsets.all(12),
                          child: Text(
                            'Kamera nicht verfügbar: ${error.errorCode.name}',
                            style: const TextStyle(color: Colors.white),
                            textAlign: TextAlign.center,
                          ),
                        ),
                      ),
                    );
                  },
                ),
              ),
              Positioned(
                right: 8,
                top: 8,
                child: Material(
                  color: Colors.black54,
                  borderRadius: BorderRadius.circular(20),
                  child: IconButton(
                    tooltip: 'Manuelle Eingabe',
                    icon: const Icon(Icons.keyboard, color: Colors.white),
                    onPressed: widget.onManualEntry,
                  ),
                ),
              ),
              Positioned(
                left: 8,
                top: 8,
                child: Material(
                  color: Colors.black54,
                  borderRadius: BorderRadius.circular(20),
                  child: IconButton(
                    tooltip: 'Taschenlampe',
                    icon: const Icon(Icons.flash_on, color: Colors.white),
                    onPressed: () => _scanner.toggleTorch(),
                  ),
                ),
              ),
            ],
          ),
        ),
        _ZoomBar(controller: _scanner, onChange: _setZoom, step: _zoomStep),
      ],
    );
  }
}

/// Zoom-Steuerung: `-` Button links, Slider in der Mitte, `+` rechts.
/// Bindet an `MobileScannerController.value.zoomScale` via
/// ValueListenableBuilder — damit reagiert der Slider sofort, wenn das
/// Plugin den Zoom selbst clampt (z. B. bei Geräten, die nicht den vollen
/// Bereich unterstützen).
class _ZoomBar extends StatelessWidget {
  const _ZoomBar({
    required this.controller,
    required this.onChange,
    required this.step,
  });

  final MobileScannerController controller;
  final Future<void> Function(double normalized) onChange;
  final double step;

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<MobileScannerState>(
      valueListenable: controller,
      builder: (context, state, _) {
        final zoom = state.zoomScale;
        return Material(
          color: Colors.black87,
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
            child: Row(
              children: [
                IconButton(
                  tooltip: 'Auszoomen',
                  icon: const Icon(Icons.remove, color: Colors.white),
                  onPressed: zoom <= 0.0 ? null : () => onChange(zoom - step),
                ),
                Expanded(
                  child: SliderTheme(
                    data: SliderTheme.of(context).copyWith(
                      activeTrackColor: Colors.white,
                      inactiveTrackColor: Colors.white24,
                      thumbColor: Colors.white,
                      overlayColor: Colors.white24,
                      trackHeight: 3,
                    ),
                    child: Slider(
                      min: 0.0,
                      max: 1.0,
                      value: zoom.clamp(0.0, 1.0),
                      onChanged: (v) => onChange(v),
                    ),
                  ),
                ),
                IconButton(
                  tooltip: 'Reinzoomen',
                  icon: const Icon(Icons.add, color: Colors.white),
                  onPressed: zoom >= 1.0 ? null : () => onChange(zoom + step),
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}
