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

import 'package:hl_lieferservice/domain/entity/delivery.dart';
import 'package:hl_lieferservice/domain/entity/delivery_item.dart';
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
import 'package:hl_lieferservice/feature/car_selection/bloc/bloc.dart';
import 'package:hl_lieferservice/feature/car_selection/bloc/state.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart';
import 'package:hl_lieferservice/widget/scanner/article_scanner_stripe.dart';
import 'package:hl_lieferservice/widget/scanner/item_matcher.dart';
import 'package:hl_lieferservice/widget/scanner/manual_entry_dialog.dart';
import 'package:hl_lieferservice/widget/scanner/scan_code_parser.dart';

/// Scan-Screen für die Filial-Abholung in der Auslieferungs-Phase.
///
/// Der Fahrer hat in der Beladen-Phase das Standardlager beladen. Artikel
/// aus einer Filiale waren noch offen — bevor er ausliefert, muss er zur
/// Filiale, die Ware holen und hier abscannen. Diese Page wird beim Tap auf
/// eine Lieferung mit offenen Filial-Artikeln geöffnet (siehe
/// `DeliveryOverview`).
///
/// Fokus auf **eine** Lieferung + **nur** deren Filial-Items. Gleiche
/// QR-Validierung (`Artikelnr;Kundennr;Belegnr`) und derselbe `ScanItem`-
/// Pfad wie die Beladen-Phase — über die geteilten Scanner-Module.
///
/// Nach vollständigem Scan: Erfolgs-Zustand + Button „zurück zur Übersicht".
/// Der Fahrer fährt dann zum Kunden; dort öffnet ein erneuter Tap die
/// eigentliche Auslieferung (`DeliveryDetail`).
class FilialePickupScanPage extends StatefulWidget {
  const FilialePickupScanPage({super.key, required this.deliveryId});

  final String deliveryId;

  @override
  State<FilialePickupScanPage> createState() => _FilialePickupScanPageState();
}

class _FilialePickupScanPageState extends State<FilialePickupScanPage> {
  static const String _notIntendedMessage =
      'Dieser Artikel gehört nicht zu dieser Filial-Abholung';

  String _carId(BuildContext context) {
    final state = context.read<CarSelectBloc>().state;
    if (state is CarSelectComplete) return state.selectedCar.id;
    return '00000000-0000-0000-0000-000000000000';
  }

  void _showSnackbar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message), duration: const Duration(seconds: 2)),
    );
  }

  /// Nur scanbare, nicht-entfernte Filial-Items dieser Lieferung,
  /// aufsteigend nach Belegzeile.
  List<DeliveryItem> _externalItems(Delivery delivery, TourDetails details) {
    final items = delivery.items.where((it) {
      if (it.isRemoved) return false;
      if (!details.isArticleScannable(it.articleId)) return false;
      final w = details.warehouseOf(it.warehouseId);
      return w != null && !w.isStandard;
    }).toList()
      // Oberartikel vor seinen Komponenten (für eingerückte Darstellung).
      ..sort((a, b) {
        final byLine = a.belegzeilenNr.compareTo(b.belegzeilenNr);
        if (byLine != 0) return byLine;
        final byParent =
            (a.isComponent ? 1 : 0).compareTo(b.isComponent ? 1 : 0);
        if (byParent != 0) return byParent;
        return (a.komponentenArtikelNr ?? '')
            .compareTo(b.komponentenArtikelNr ?? '');
      });
    return items;
  }

  void _onBarcode({
    required String code,
    required Delivery delivery,
    required TourDetails details,
  }) {
    final customer = details.customerOf(delivery);
    final parsed = parseScanCode(code);
    if (parsed == null ||
        customer?.erpCustomerId != parsed.customerErpId ||
        delivery.erpBelegnummer != parsed.beleg) {
      _showSnackbar(_notIntendedMessage);
      return;
    }

    final match = matchItem(
      delivery: delivery,
      details: details,
      articleNumber: parsed.articleNumber,
      // Nur Filial-Items zählen — ein Standardlager-Artikel hat hier nichts
      // zu suchen (der ist längst auf dem LKW).
      itemFilter: (it) {
        final w = details.warehouseOf(it.warehouseId);
        return w != null && !w.isStandard;
      },
    );
    switch (match) {
      case ItemMatchOk(:final item):
        context
            .read<TourBloc>()
            .add(ScanItem(deliveryItemId: item.id, actorCarId: _carId(context)));
      case ItemMatchNotInDelivery():
        _showSnackbar(_notIntendedMessage);
      case ItemMatchNotScannable():
        _showSnackbar('Diese Position ist nicht zum Scannen vorgesehen.');
      case ItemMatchAllDone():
        _showSnackbar('Dieser Artikel ist bereits geladen.');
      case ItemMatchAllRemoved():
        _showSnackbar('Diese Position wurde aus der Lieferung entfernt.');
      case ItemMatchNotOpen():
        _showSnackbar('Diese Position ist nicht (mehr) offen.');
    }
  }

  Future<void> _onManualEntry({
    required Delivery delivery,
    required TourDetails details,
  }) async {
    final code = await showManualEntryDialog(context);
    if (code == null || code.isEmpty || !mounted) return;
    _onBarcode(code: code, delivery: delivery, details: details);
  }

  /// Fallback ohne Barcode: die ganze Restmenge der Filial-Position manuell
  /// als geholt bestätigen. Bewusste Aussage → Bestätigungs-Dialog; das
  /// Backend protokolliert den Scan als `manual`.
  Future<void> _onManualConfirm(DeliveryItem item) async {
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text('Manuell bestätigen'),
        content: const Text(
          'Diese Position ohne Scan als aus der Filiale geholt markieren? '
          'Das wird als manuelle Bestätigung protokolliert.',
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(ctx).pop(false),
            child: const Text('Abbrechen'),
          ),
          FilledButton(
            onPressed: () => Navigator.of(ctx).pop(true),
            child: const Text('Als geholt bestätigen'),
          ),
        ],
      ),
    );
    if (confirmed != true || !mounted) return;
    context.read<TourBloc>().add(ScanItem(
          deliveryItemId: item.id,
          actorCarId: _carId(context),
          manual: true,
        ));
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<TourBloc, TourState>(
      builder: (context, state) {
        if (state is! TourLoaded) {
          return const Scaffold(
            body: Center(child: CircularProgressIndicator()),
          );
        }
        final details = state.details;
        final delivery = _findDelivery(details);
        if (delivery == null) {
          return Scaffold(
            appBar: AppBar(title: const Text('Filial-Abholung')),
            body: const Center(
              child: Text('Lieferung nicht in der Tour gefunden.'),
            ),
          );
        }

        final customer = details.customerOf(delivery);
        final externalItems = _externalItems(delivery, details);
        final doneCount = externalItems.where((it) => it.isDone).length;
        final allDone = externalItems.isNotEmpty && doneCount == externalItems.length;
        final warehouseNames = details.externalWarehouseLabels(delivery);

        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.primary,
            foregroundColor: Theme.of(context).colorScheme.onPrimary,
            title: Text(
              warehouseNames.isEmpty
                  ? 'Filial-Abholung'
                  : 'Abholung: ${warehouseNames.join(", ")}',
            ),
          ),
          body: Column(
            children: [
              ArticleScannerStripe(
                onBarcode: (code) =>
                    _onBarcode(code: code, delivery: delivery, details: details),
                onManualEntry: () =>
                    _onManualEntry(delivery: delivery, details: details),
              ),
              Expanded(
                child: ListView(
                  // Wenn alle Artikel gescannt sind, deckt die _DoneBar den
                  // Inset ab; vorher endet die Liste unten frei — daher hier
                  // die System-Navigationsleiste freihalten.
                  padding: EdgeInsets.fromLTRB(
                    16,
                    12,
                    16,
                    24 + (allDone ? 0 : MediaQuery.viewPaddingOf(context).bottom),
                  ),
                  children: [
                    _Header(
                      customerName: customer?.name ?? '⟨Unbekannter Kunde⟩',
                      belegnummer: delivery.erpBelegnummer,
                      doneCount: doneCount,
                      total: externalItems.length,
                    ),
                    const SizedBox(height: 12),
                    for (final item in externalItems)
                      _ExternalItemRow(
                        item: item,
                        details: details,
                        onManualConfirm: () => _onManualConfirm(item),
                      ),
                  ],
                ),
              ),
              if (allDone) _DoneBar(onConfirm: () => Navigator.of(context).pop()),
            ],
          ),
        );
      },
    );
  }

  Delivery? _findDelivery(TourDetails details) {
    for (final d in details.deliveries) {
      if (d.id == widget.deliveryId) return d;
    }
    return null;
  }
}

class _Header extends StatelessWidget {
  const _Header({
    required this.customerName,
    required this.belegnummer,
    required this.doneCount,
    required this.total,
  });

  final String customerName;
  final String belegnummer;
  final int doneCount;
  final int total;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Card(
      margin: EdgeInsets.zero,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(Icons.warehouse_outlined, color: theme.colorScheme.primary),
                const SizedBox(width: 8),
                Expanded(
                  child: Text(
                    'Artikel aus der Filiale holen & scannen',
                    style: theme.textTheme.titleSmall?.copyWith(
                      fontWeight: FontWeight.w700,
                    ),
                  ),
                ),
                Text(
                  '$doneCount / $total',
                  style: theme.textTheme.titleMedium?.copyWith(
                    fontWeight: FontWeight.bold,
                    color: doneCount == total
                        ? Colors.green.shade700
                        : theme.colorScheme.primary,
                  ),
                ),
              ],
            ),
            const SizedBox(height: 8),
            Text(
              '$customerName · Beleg-Nr. $belegnummer',
              style: TextStyle(
                fontSize: 13,
                color: theme.colorScheme.onSurfaceVariant,
              ),
            ),
            const SizedBox(height: 8),
            ClipRRect(
              borderRadius: BorderRadius.circular(4),
              child: LinearProgressIndicator(
                value: total == 0 ? 0 : doneCount / total,
                minHeight: 6,
                backgroundColor: theme.colorScheme.surfaceContainerHighest,
                valueColor: AlwaysStoppedAnimation<Color>(
                  doneCount == total
                      ? Colors.green.shade600
                      : theme.colorScheme.primary,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _ExternalItemRow extends StatelessWidget {
  const _ExternalItemRow({
    required this.item,
    required this.details,
    required this.onManualConfirm,
  });

  final DeliveryItem item;
  final TourDetails details;
  final VoidCallback onManualConfirm;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final article = details.articleOf(item.articleId);
    final warehouse = details.warehouseOf(item.warehouseId);
    final done = item.isDone;
    // Manueller Fallback nur für offene Positionen. Liste ist bereits
    // scanbar + extern + nicht-entfernt gefiltert; hier nur done/held raus.
    final canManualConfirm = !done && !item.isHeld;

    return Card(
      // Komponenten eingerückt → gehören zum Oberartikel darüber.
      margin: EdgeInsets.only(top: 8, left: item.isComponent ? 24 : 0),
      elevation: 0,
      color: done
          ? Colors.green.withValues(alpha: 0.08)
          : theme.colorScheme.surfaceContainerLow,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(12),
        side: BorderSide(
          color: done
              ? Colors.green.withValues(alpha: 0.4)
              : Colors.transparent,
        ),
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          ListTile(
            leading: Icon(
              done ? Icons.check_circle : Icons.radio_button_unchecked,
              color: done
                  ? Colors.green.shade600
                  : theme.colorScheme.onSurfaceVariant,
            ),
            title: Text(
              '${item.isComponent ? '↳ ' : ''}${article?.name ?? '⟨Unbekannter Artikel⟩'}',
              style: const TextStyle(fontWeight: FontWeight.w600),
            ),
            subtitle: Text(
              [
                article?.articleNumber ?? item.articleId,
                if (warehouse != null) warehouse.name,
              ].join(' · '),
              style: TextStyle(
                fontSize: 12,
                color: theme.colorScheme.onSurfaceVariant,
              ),
            ),
            trailing: Text(
              '${item.scanProgress.scannedQuantity} / ${item.requiredQuantity}',
              style: TextStyle(
                fontWeight: FontWeight.bold,
                color: done ? Colors.green.shade700 : theme.colorScheme.onSurface,
              ),
            ),
          ),
          if (canManualConfirm)
            Padding(
              padding: const EdgeInsets.fromLTRB(12, 0, 12, 12),
              child: SizedBox(
                width: double.infinity,
                child: OutlinedButton.icon(
                  onPressed: onManualConfirm,
                  icon: const Icon(Icons.check_circle_outline, size: 18),
                  label: const Text('Manuell als geholt bestätigen'),
                ),
              ),
            ),
        ],
      ),
    );
  }
}

class _DoneBar extends StatelessWidget {
  const _DoneBar({required this.onConfirm});

  final VoidCallback onConfirm;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      top: false,
      child: Container(
        width: double.infinity,
        padding: const EdgeInsets.fromLTRB(16, 12, 16, 12),
        color: Colors.green.withValues(alpha: 0.12),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Row(
              children: [
                Icon(Icons.check_circle, color: Colors.green.shade700),
                const SizedBox(width: 8),
                Expanded(
                  child: Text(
                    'Alle Filial-Artikel geladen',
                    style: TextStyle(
                      fontWeight: FontWeight.w700,
                      color: Colors.green.shade800,
                    ),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 8),
            SizedBox(
              width: double.infinity,
              child: FilledButton.icon(
                onPressed: onConfirm,
                icon: const Icon(Icons.arrow_back),
                label: const Text('Fertig — zurück zur Übersicht'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
