import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/phase_bloc.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/phase_event.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/feature/delivery/model/delivery_phase.dart';
import 'package:hl_lieferservice/feature/delivery/overview/presentation/delivery_fail_page.dart';
import 'package:hl_lieferservice/model/delivery.dart';
import 'package:hl_lieferservice/model/tour.dart';
import 'package:hl_lieferservice/widget/home/presentation/home_drawer.dart';
import 'package:hl_lieferservice/widget/phase_stepper/phase_stepper.dart';

/// Page für die erste Phase bei Mehr-Auto-Teams: Auswählen der eigenen
/// Lieferungen aus dem gemeinsamen Tour-Pool.
///
/// Aufbau:
/// * Tab "Verfügbar" — alle Lieferungen, die noch keinem Fahrzeug
///   zugeordnet sind. Multiselect, Bulk-Bestätigung per BottomBar-Button.
/// * Tab "Vergeben"  — Lieferungen, die bereits zugeordnet sind. Tap auf
///   eigene Lieferung → Freigabe-Dialog; Tap auf fremde → Umlade-Dialog.
/// * Persistent untere BottomBar: "Weiter zum Sortieren" — wechselt die
///   Phase. Es gibt bewusst keinen Zwang, dass alle Lieferungen verteilt
///   sein müssen; der Fahrer entscheidet wann er weiterzieht.
class DeliverySelectionPage extends StatefulWidget {
  const DeliverySelectionPage({
    super.key,
    required this.selectedCarId,
  });

  /// ID des aktuell gewählten Fahrzeugs (Eigene Lieferungen / Ziel von
  /// Übernahmen).
  final int selectedCarId;

  @override
  State<StatefulWidget> createState() => _DeliverySelectionPageState();
}

class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
  /// Lokale Multi-Selektion im Tab "Verfügbar". Wird nach erfolgreichem
  /// Bulk-Assign geleert.
  final Set<String> _selectedIds = <String>{};

  /// True während sequentieller Assign-Calls — schaltet den
  /// Bestätigungs-Button auf Spinner und disabled.
  bool _isAssigning = false;

  String get _carIdString => widget.selectedCarId.toString();

  /// Sucht das Plate eines Autos in der Tour-Driver-Liste. Liefert "?" als
  /// Fallback, falls die Zuordnung nicht (mehr) im Team enthalten ist —
  /// z. B. nach Personalwechsel zwischen Tour-Synchronisationen.
  String _plateFor(int? carId, Tour tour) {
    if (carId == null) return "?";
    final car = tour.driver.cars.firstWhereOrNull((c) => c.id == carId);
    return car?.plate ?? "?";
  }

  /// Bulk-Assign der aktuell selektierten Lieferungen an das eigene Auto.
  /// Sequentiell, damit der lokale Tour-Stream nach jedem Schritt
  /// konsistent ist und die Listen-Filter live mitwandern. Bei Fehlern
  /// wird eine SnackBar gezeigt und die Selektion bleibt erhalten.
  Future<void> _confirmSelection() async {
    if (_selectedIds.isEmpty || _isAssigning) return;

    setState(() => _isAssigning = true);
    final tourBloc = context.read<TourBloc>();
    final ids = List<String>.from(_selectedIds);

    try {
      for (final id in ids) {
        tourBloc.add(
          AssignCarEvent(deliveryId: id, carId: _carIdString),
        );
      }
      // Hinweis: TourBloc verarbeitet die Events asynchron; lokale
      // Tour-Updates erfolgen über den Stream. Wir leeren die Selektion
      // optimistisch, damit der Fahrer ein klares Feedback bekommt.
      if (!mounted) return;
      setState(_selectedIds.clear);
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text("Fehler beim Übernehmen: $e")),
      );
    } finally {
      if (mounted) setState(() => _isAssigning = false);
    }
  }

  /// Wechselt in die nächste Phase (Sortieren). Der Fahrer kann jederzeit
  /// zurückspringen — die persistierte Phase wird über den Stepper-Tap
  /// zurückgesetzt.
  void _goToSorting() {
    context.read<PhaseBloc>().add(
          PhaseSet(
            carId: _carIdString,
            phase: DeliveryPhase.sortieren,
          ),
        );
  }

  Future<void> _showReleaseDialog(Delivery delivery) async {
    final result = await showDialog<bool>(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text("Lieferung freigeben"),
        content: Text(
          "${delivery.customer.name} wurde Ihrem Fahrzeug zugeordnet. "
          "Möchten Sie diese Lieferung wieder freigeben?",
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(ctx).pop(false),
            child: const Text("Abbrechen"),
          ),
          FilledButton(
            onPressed: () => Navigator.of(ctx).pop(true),
            child: const Text("Freigeben"),
          ),
        ],
      ),
    );

    if (result != true || !mounted) return;
    context.read<TourBloc>().add(
          UnassignDeliveryEvent(deliveryId: delivery.id),
        );
  }

  Future<void> _showTakeoverDialog(Delivery delivery, Tour tour) async {
    final foreignPlate = _plateFor(delivery.carId, tour);
    final ownPlate = _plateFor(widget.selectedCarId, tour);
    final theme = Theme.of(context);

    final result = await showDialog<bool>(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text("Lieferung umladen"),
        content: RichText(
          text: TextSpan(
            style: theme.textTheme.bodyMedium,
            children: [
              TextSpan(text: "${delivery.customer.name} ist aktuell "),
              TextSpan(
                text: foreignPlate,
                style: const TextStyle(fontWeight: FontWeight.bold),
              ),
              const TextSpan(text: " zugeordnet. Möchten Sie diese "
                  "Lieferung auf "),
              TextSpan(
                text: ownPlate,
                style: const TextStyle(fontWeight: FontWeight.bold),
              ),
              const TextSpan(text: " umladen?"),
            ],
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(ctx).pop(false),
            child: const Text("Abbrechen"),
          ),
          FilledButton(
            // Warnfarbe, da das Umladen eine bestehende Zuordnung
            // überschreibt — last write wins. `colorScheme.error` ist
            // bewusst hart gewählt, damit der Fahrer den Eingriff in
            // fremde Disposition bewusst bestätigt.
            style: FilledButton.styleFrom(
              backgroundColor: theme.colorScheme.error,
              foregroundColor: theme.colorScheme.onError,
            ),
            onPressed: () => Navigator.of(ctx).pop(true),
            child: const Text("Übernehmen"),
          ),
        ],
      ),
    );

    if (result != true || !mounted) return;
    context.read<TourBloc>().add(
          AssignCarEvent(
            deliveryId: delivery.id,
            carId: _carIdString,
          ),
        );
  }

  // ---------------------------------------------------------------------------
  // Widgets
  // ---------------------------------------------------------------------------

  Widget _plateBadge(BuildContext context, String plate, {bool own = false}) {
    final theme = Theme.of(context);
    final bg = own
        ? theme.colorScheme.primary
        : theme.colorScheme.surfaceContainerHighest;
    final fg = own
        ? theme.colorScheme.onPrimary
        : theme.colorScheme.onSurfaceVariant;
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
      decoration: BoxDecoration(
        color: bg,
        borderRadius: BorderRadius.circular(6),
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.local_shipping_outlined, size: 12, color: fg),
          const SizedBox(width: 4),
          Text(
            plate,
            style: TextStyle(
              fontSize: 11,
              fontWeight: FontWeight.bold,
              color: fg,
            ),
          ),
        ],
      ),
    );
  }

  Widget _emptyState({
    required IconData icon,
    required String title,
    String? subtitle,
  }) {
    final theme = Theme.of(context);
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(32),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(icon, size: 64, color: theme.colorScheme.outline),
            const SizedBox(height: 12),
            Text(
              title,
              style: theme.textTheme.titleMedium,
              textAlign: TextAlign.center,
            ),
            if (subtitle != null) ...[
              const SizedBox(height: 6),
              Text(
                subtitle,
                style: theme.textTheme.bodySmall,
                textAlign: TextAlign.center,
              ),
            ],
          ],
        ),
      ),
    );
  }

  Widget _availableTab(List<Delivery> available) {
    if (available.isEmpty) {
      return _emptyState(
        icon: Icons.inbox_outlined,
        title: "Alle Lieferungen sind verteilt.",
        subtitle: "Im Tab \"Vergeben\" können Sie eigene Lieferungen "
            "freigeben oder fremde übernehmen.",
      );
    }

    return ListView.builder(
      padding: const EdgeInsets.symmetric(vertical: 4),
      itemCount: available.length,
      itemBuilder: (context, index) {
        final delivery = available[index];
        final isSelected = _selectedIds.contains(delivery.id);
        return CheckboxListTile(
          key: ValueKey("available-${delivery.id}"),
          value: isSelected,
          onChanged: _isAssigning
              ? null
              : (checked) {
                  setState(() {
                    if (checked == true) {
                      _selectedIds.add(delivery.id);
                    } else {
                      _selectedIds.remove(delivery.id);
                    }
                  });
                },
          title: Text(
            delivery.customer.name,
            style: const TextStyle(fontWeight: FontWeight.w600),
          ),
          subtitle: Text(
            delivery.customer.address.toString(),
            style: const TextStyle(fontSize: 12),
          ),
          controlAffinity: ListTileControlAffinity.leading,
        );
      },
    );
  }

  Widget _assignedTab(List<Delivery> assigned, Tour tour) {
    if (assigned.isEmpty) {
      return _emptyState(
        icon: Icons.local_shipping_outlined,
        title: "Noch keine Lieferungen verteilt.",
      );
    }

    final theme = Theme.of(context);

    return ListView.builder(
      padding: const EdgeInsets.symmetric(vertical: 4),
      itemCount: assigned.length,
      itemBuilder: (context, index) {
        final delivery = assigned[index];
        final isOwn = delivery.carId == widget.selectedCarId;
        final plate = _plateFor(delivery.carId, tour);

        return Material(
          color: isOwn
              ? theme.colorScheme.primaryContainer.withValues(alpha: 0.35)
              : null,
          child: ListTile(
            key: ValueKey("assigned-${delivery.id}"),
            onTap: () {
              if (isOwn) {
                _showReleaseDialog(delivery);
              } else {
                _showTakeoverDialog(delivery, tour);
              }
            },
            leading: Icon(
              isOwn ? Icons.check_circle : Icons.person_outline,
              color: isOwn
                  ? theme.colorScheme.primary
                  : theme.colorScheme.onSurfaceVariant,
            ),
            title: Text(
              delivery.customer.name,
              style: TextStyle(
                fontWeight: FontWeight.w600,
                color: isOwn ? theme.colorScheme.primary : null,
              ),
            ),
            subtitle: Text(
              delivery.customer.address.toString(),
              style: const TextStyle(fontSize: 12),
            ),
            trailing: _plateBadge(context, plate, own: isOwn),
          ),
        );
      },
    );
  }

  /// BottomBar mit Bulk-Confirm (kontextabhängig) + Phasen-Wechsel.
  /// Confirm-Button ist nur sichtbar, wenn etwas selektiert ist —
  /// "Weiter zum Sortieren" bleibt immer sichtbar.
  Widget _buildBottomBar() {
    final theme = Theme.of(context);
    final hasSelection = _selectedIds.isNotEmpty;

    return SafeArea(
      child: Padding(
        padding: const EdgeInsets.all(12),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            if (hasSelection)
              SizedBox(
                width: double.infinity,
                child: FilledButton.icon(
                  onPressed:
                      _isAssigning ? null : _confirmSelection,
                  icon: _isAssigning
                      ? SizedBox(
                          width: 16,
                          height: 16,
                          child: CircularProgressIndicator(
                            strokeWidth: 2,
                            color: theme.colorScheme.onPrimary,
                          ),
                        )
                      : const Icon(Icons.check),
                  label: Text(
                    "Auswahl bestätigen (${_selectedIds.length})",
                  ),
                ),
              ),
            if (hasSelection) const SizedBox(height: 8),
            SizedBox(
              width: double.infinity,
              child: OutlinedButton.icon(
                onPressed: _isAssigning ? null : _goToSorting,
                icon: const Icon(Icons.arrow_forward),
                label: const Text("Weiter zum Sortieren"),
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<TourBloc, TourState>(
      builder: (context, state) {
        if (state is TourLoadingFailed) {
          return const DeliveryLoadingFailedPage();
        }
        if (state is! TourLoaded) {
          return const Scaffold(
            body: Center(child: CircularProgressIndicator()),
          );
        }

        final available = state.tour.deliveries
            .where((d) => d.carId == null)
            .toList();
        final assigned = state.tour.deliveries
            .where((d) => d.carId != null)
            .toList();

        // Falls eine selektierte Lieferung in der Zwischenzeit zugeordnet
        // wurde (z. B. durch einen parallelen Vorgang), Selektion bereinigen.
        _selectedIds.removeWhere(
          (id) => !available.any((d) => d.id == id),
        );

        return DefaultTabController(
          length: 2,
          child: Scaffold(
            drawer: const HomeAppDrawer(),
            appBar: PreferredSize(
              preferredSize: const Size.fromHeight(140 + kTextTabBarHeight),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  PhaseStepper(
                    currentPhase: DeliveryPhase.auswaehlen,
                    carId: _carIdString,
                  ),
                  Material(
                    color: Theme.of(context).primaryColor,
                    child: TabBar(
                      labelColor:
                          Theme.of(context).colorScheme.onPrimary,
                      unselectedLabelColor: Theme.of(context)
                          .colorScheme
                          .onPrimary
                          .withValues(alpha: 0.6),
                      indicatorColor:
                          Theme.of(context).colorScheme.onPrimary,
                      tabs: [
                        Tab(text: "Verfügbar (${available.length})"),
                        Tab(text: "Vergeben (${assigned.length})"),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            body: TabBarView(
              children: [
                _availableTab(available),
                _assignedTab(assigned, state.tour),
              ],
            ),
            bottomNavigationBar: _buildBottomBar(),
          ),
        );
      },
    );
  }
}
