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/tour_details.dart';
import 'package:hl_lieferservice/feature/cars/bloc/cars_bloc.dart';
import 'package:hl_lieferservice/feature/cars/bloc/cars_state.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/widget/sortable_delivery_list.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 zweite Phase des Lieferprozesses (Sortieren). Der Fahrer
/// legt per Drag&Drop die Reihenfolge fest, ändert lokal so oft er möchte
/// und bestätigt am Ende mit einem expliziten Klick. Dann wird die
/// Reihenfolge ans Backend übertragen und in Phase [DeliveryPhase.beladen]
/// gewechselt.
///
/// Hinweis zum Backend-Endpoint:
/// `PUT /tours/{id}/delivery-order` erwartet die **vollständige** Reihenfolge
/// aller Lieferungen der Tour. Bei Mehr-Auto-Teams sortiert der Fahrer
/// trotzdem nur „seine" Lieferungen — die Reihenfolge der fremden Lieferungen
/// wird unverändert anhand der aktuellen `sortOrder` mitgeschickt.
class DeliverySortPage extends StatefulWidget {
  const DeliverySortPage({
    super.key,
    required this.selectedCarId,
    this.onPhaseAdvanced,
  });

  final String selectedCarId;
  final VoidCallback? onPhaseAdvanced;

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

class _DeliverySortPageState extends State<DeliverySortPage> {
  final SortableDeliveryListController _listController =
      SortableDeliveryListController();

  /// Verhindert mehrfache SnackBars für denselben Fehler-State.
  String? _lastShownErrorSignature;

  /// True, sobald `_confirm` gefeuert wurde — wir nutzen das, um den
  /// Übergang persisting → fertig zuverlässig zu erkennen.
  bool _isAwaitingConfirm = false;

  bool _multiCarTeam(BuildContext context) {
    final carsState = context.read<CarsBloc>().state;
    return carsState is CarsLoaded && carsState.cars.length >= 2;
  }

  List<Delivery> _ownDeliveries(TourDetails details) {
    if (_multiCarTeam(context)) {
      return details.deliveriesSorted
          .where((d) => d.assignedCarId == widget.selectedCarId)
          .toList();
    }
    return details.deliveriesSorted;
  }

  /// Baut die vollständige Tour-Reihenfolge: die fremden Lieferungen bleiben
  /// in ihrer aktuellen `sortOrder`, die eigenen werden in der vom Fahrer
  /// gewählten Reihenfolge eingefügt — an den Positionen, an denen sie
  /// vorher waren. Beispiel: hat der Fahrer „eigene" Plätze 1, 3, 5
  /// belegt und sortiert lokal um, dann landen seine neuen Reihen-Ids
  /// in derselben Reihenfolge auf den Positionen 1, 3, 5; fremde Items
  /// behalten ihre Plätze 2, 4.
  List<String> _buildFullTourOrder(
    TourDetails details,
    List<String> ownOrderedIds,
  ) {
    final sorted = details.deliveriesSorted;
    if (!_multiCarTeam(context)) return ownOrderedIds;

    final ownSlotsByPosition = <int, String>{};
    final foreignByPosition = <int, String>{};
    for (var i = 0; i < sorted.length; i++) {
      final d = sorted[i];
      if (d.assignedCarId == widget.selectedCarId) {
        ownSlotsByPosition[i] = d.id;
      } else {
        foreignByPosition[i] = d.id;
      }
    }
    final ownPositions = ownSlotsByPosition.keys.toList()..sort();

    final result = List<String?>.filled(sorted.length, null);
    for (final entry in foreignByPosition.entries) {
      result[entry.key] = entry.value;
    }
    for (var i = 0; i < ownPositions.length && i < ownOrderedIds.length; i++) {
      result[ownPositions[i]] = ownOrderedIds[i];
    }
    // Schließe verbleibende Lücken auf — sollte normalerweise leer sein.
    return result.whereType<String>().toList();
  }

  void _advanceToLoading() {
    context.read<PhaseBloc>().add(
          PhaseSet(
            carId: widget.selectedCarId,
            phase: DeliveryPhase.beladen,
          ),
        );
    widget.onPhaseAdvanced?.call();
  }

  void _confirm(TourDetails details) {
    final ownOrder = _listController.readCurrentOrder();
    final fullOrder = _buildFullTourOrder(details, ownOrder);
    if (fullOrder.isEmpty) {
      _advanceToLoading();
      return;
    }
    _isAwaitingConfirm = true;
    context.read<TourBloc>().add(
          ReorderDeliveries(orderedDeliveryIds: fullOrder),
        );
  }

  Widget _hintCard({required IconData icon, required String text, Color? color}) {
    return Padding(
      padding: const EdgeInsets.all(15),
      child: Row(
        children: [
          Padding(
            padding: const EdgeInsets.only(right: 15),
            child: Icon(icon, color: color ?? Colors.blueAccent),
          ),
          Expanded(child: Text(text)),
        ],
      ),
    );
  }

  Widget _emptyState() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        const Icon(Icons.inbox_outlined, size: 64, color: Colors.grey),
        const SizedBox(height: 12),
        Text(
          'Keine Lieferungen heute',
          style: Theme.of(context).textTheme.titleMedium,
        ),
        const SizedBox(height: 6),
        const Padding(
          padding: EdgeInsets.symmetric(horizontal: 32),
          child: Text(
            'Für das ausgewählte Fahrzeug sind heute keine Lieferungen geplant.',
            textAlign: TextAlign.center,
          ),
        ),
        const SizedBox(height: 20),
        // Erneut die heutige Tour vom Backend laden. `LoadTour` zeigt
        // währenddessen den Lade-Branch (Spinner) und landet danach wieder
        // hier (TourEmpty) oder in der sortierbaren Lieferungsliste.
        FilledButton.tonalIcon(
          onPressed: () => context.read<TourBloc>().add(const LoadTour()),
          icon: const Icon(Icons.refresh),
          label: const Text('Neu laden'),
        ),
      ],
    );
  }

  Widget _singleDeliveryHint(Delivery single, TourDetails details) {
    final customer = details.customerOf(single);
    return Column(
      children: [
        _hintCard(
          icon: Icons.info_outline,
          text: 'Nur eine Lieferung — die Reihenfolge ist trivial. '
              'Tippen Sie auf "Weiter zur Beladung", um fortzufahren.',
        ),
        const Divider(),
        ListTile(
          leading: CircleAvatar(
            backgroundColor: Theme.of(context).primaryColor,
            child: Text(
              '1',
              style: TextStyle(
                color: Theme.of(context).colorScheme.onSecondary,
              ),
            ),
          ),
          title: Text(customer?.name ?? '⟨Unbekannter Kunde⟩'),
          subtitle: Text(
            single.deliveryAddressSnapshot.oneLine,
            style: const TextStyle(fontSize: 11),
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return BlocConsumer<TourBloc, TourState>(
      listenWhen: (prev, curr) {
        if (prev is! TourLoaded || curr is! TourLoaded) return false;
        final phaseEnded =
            prev.isPersistingReorder && !curr.isPersistingReorder;
        final newError = curr.reorderError != null &&
            curr.reorderError != prev.reorderError;
        return phaseEnded || newError;
      },
      listener: (context, state) {
        if (state is! TourLoaded) return;

        final err = state.reorderError;
        if (err != null && err != _lastShownErrorSignature) {
          _lastShownErrorSignature = err;
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text(err)),
          );
          _isAwaitingConfirm = false;
          return;
        }

        if (_isAwaitingConfirm &&
            !state.isPersistingReorder &&
            err == null) {
          _isAwaitingConfirm = false;
          _advanceToLoading();
        }
      },
      builder: (context, state) {
        // Drawer in jedem Branch beibehalten — sonst sitzt der Fahrer im
        // „Keine Tour heute"- oder Lade-Screen fest, ohne Zugriff auf
        // Einstellungen / Logout.
        if (state is TourEmpty) {
          // Auch im Leerzustand die Steps-AppBar (PhaseStepper, primary)
          // zeigen — nur die mittige Nachricht bleibt. So bleibt die Phasen-
          // Navigation sichtbar und die Optik konsistent zum geladenen Zustand.
          return Scaffold(
            drawer: const HomeAppDrawer(),
            appBar: PreferredSize(
              preferredSize: const Size.fromHeight(140),
              child: PhaseStepper(
                currentPhase: DeliveryPhase.sortieren,
                carId: widget.selectedCarId,
              ),
            ),
            body: _emptyState(),
          );
        }
        if (state is! TourLoaded) {
          // Lade-Zwischenzustand (auch beim 'Neu laden') mit derselben
          // PhaseStepper-AppBar — sonst flackert die Leiste kurz auf die
          // schlichte AppBar zurück.
          return Scaffold(
            drawer: const HomeAppDrawer(),
            appBar: PreferredSize(
              preferredSize: const Size.fromHeight(140),
              child: PhaseStepper(
                currentPhase: DeliveryPhase.sortieren,
                carId: widget.selectedCarId,
              ),
            ),
            body: const Center(child: CircularProgressIndicator()),
          );
        }

        final details = state.details;
        final ownDeliveries = _ownDeliveries(details);

        return Scaffold(
          drawer: const HomeAppDrawer(),
          appBar: PreferredSize(
            preferredSize: const Size.fromHeight(140),
            child: PhaseStepper(
              currentPhase: DeliveryPhase.sortieren,
              carId: widget.selectedCarId,
            ),
          ),
          body: SafeArea(child: _buildBody(state, details, ownDeliveries)),
          bottomNavigationBar:
              _buildBottomBar(state, details, ownDeliveries),
        );
      },
    );
  }

  Widget _buildBody(
    TourLoaded state,
    TourDetails details,
    List<Delivery> ownDeliveries,
  ) {
    if (ownDeliveries.isEmpty) {
      return _emptyState();
    }
    if (ownDeliveries.length == 1) {
      return _singleDeliveryHint(ownDeliveries.first, details);
    }
    return Column(
      children: [
        _hintCard(
          icon: Icons.info_outline,
          text: 'Ziehen Sie die einzelnen Lieferungen mit dem Finger in die '
              'gewünschte Position. Die Reihenfolge wird erst beim '
              'Bestätigen ans System übertragen.',
        ),
        const Divider(height: 1),
        Expanded(
          child: SortableDeliveryList(
            details: details,
            deliveries: ownDeliveries,
            controller: _listController,
          ),
        ),
      ],
    );
  }

  Widget _buildBottomBar(
    TourLoaded state,
    TourDetails details,
    List<Delivery> ownDeliveries,
  ) {
    final isLoading = state.isPersistingReorder;
    final theme = Theme.of(context);

    if (ownDeliveries.isEmpty) {
      return SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(12),
          child: SizedBox(
            width: double.infinity,
            child: FilledButton.icon(
              onPressed: isLoading ? null : _advanceToLoading,
              icon: const Icon(Icons.arrow_forward),
              label: const Text('Weiter zur Beladung'),
            ),
          ),
        ),
      );
    }

    if (ownDeliveries.length == 1) {
      return SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(12),
          child: SizedBox(
            width: double.infinity,
            child: FilledButton.icon(
              onPressed: isLoading ? null : () => _confirm(details),
              icon: isLoading
                  ? const SizedBox(
                      width: 16,
                      height: 16,
                      child: CircularProgressIndicator(
                        strokeWidth: 2,
                        color: Colors.white,
                      ),
                    )
                  : const Icon(Icons.arrow_forward),
              label: const Text('Weiter zur Beladung'),
            ),
          ),
        ),
      );
    }

    return SafeArea(
      child: Padding(
        padding: const EdgeInsets.all(12),
        child: Row(
          children: [
            Expanded(
              child: OutlinedButton.icon(
                onPressed: isLoading ? null : _listController.resetToDefault,
                icon: const Icon(Icons.restart_alt),
                label: const Text('Zurücksetzen'),
              ),
            ),
            const SizedBox(width: 12),
            Expanded(
              flex: 2,
              child: FilledButton.icon(
                onPressed: isLoading ? null : () => _confirm(details),
                icon: isLoading
                    ? SizedBox(
                        width: 16,
                        height: 16,
                        child: CircularProgressIndicator(
                          strokeWidth: 2,
                          color: theme.colorScheme.onPrimary,
                        ),
                      )
                    : const Icon(Icons.check),
                label: const Text('Reihenfolge bestätigen'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
