import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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/cars/bloc/cars_bloc.dart';
import 'package:hl_lieferservice/feature/cars/bloc/cars_event.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/phase_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/feature/delivery/model/delivery_phase.dart';
import 'package:hl_lieferservice/feature/delivery/overview/presentation/delivery_overview_page.dart';
import 'package:hl_lieferservice/feature/delivery/overview/presentation/delivery_selection_page.dart';
import 'package:hl_lieferservice/feature/delivery/overview/presentation/delivery_sort_page.dart';
import 'package:hl_lieferservice/feature/loading/presentation/loading_overview_page.dart';

/// Wurzel-Widget des authentifizierten Bereichs. Routet anhand der aktuellen
/// Phase des ausgewählten Fahrzeugs:
///
/// * Phase Sortieren / Beladen → die jeweilige Phase-Page wird direkt
///   gerendert (kein BottomNav). Navigation läuft über den Phasen-Stepper.
/// * Phase Ausliefern → klassisches Home mit BottomNavigationBar
///   (Auslieferung / Fahrzeuge / Einstellungen). Beladung als Tab entfällt,
///   da die Phase abgeschlossen ist.
class Home extends StatefulWidget {
  const Home({super.key});

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

class _HomeState extends State<Home> {
  String? _initializedCarId;

  /// Merkt, für welches Auto die automatische Lieferungs-Zuordnung bereits
  /// Auto, für das zuletzt automatisch zugewiesen wurde (Ein-Auto-Teams).
  String? _autoAssignCar;

  /// Lieferungs-Ids, für die die Auto-Zuweisung bereits ausgelöst wurde. So
  /// werden **neu gesyncte** Lieferungen (die beim Reload dazukommen) NACH-
  /// träglich zugewiesen, ohne dass eine noch laufende Zuweisung (bis der
  /// Server antwortet und `assignedCarId` gesetzt ist) bei jedem Build
  /// respammt wird. (s. [_ensureSingleCarAssignment])
  final Set<String> _autoAssignDispatched = {};

  @override
  void initState() {
    super.initState();

    // Tour beim ersten Aufbau laden. Account-Filter sitzt jetzt
    // serverseitig im JWT — kein Personalnummer-Argument mehr nötig.
    context.read<TourBloc>().add(const LoadTour());

    // CarsBloc auch hier triggern: wenn der CarSelectBloc beim App-Start
    // eine valide Tages-Auswahl aus den SharedPreferences fand, wurde die
    // CarSelectionPage übersprungen — und damit auch ihr `CarLoad`-Trigger.
    // Ohne diesen Aufruf hängen drei Stellen am leeren CarsBloc-State:
    // `PhaseStepper.carCount`, `app.carCountResolver` (Eintrittsphase) und
    // `delivery_selection_page._plateFor` (Vergeben-Tab zeigt sonst "?").
    // Der Bloc-interne `if (state is CarsLoaded && !event.force) return;`
    // macht den Aufruf idempotent.
    context.read<CarsBloc>().add(const CarLoad());
  }

  /// Stellt sicher, dass für das aktuell gewählte Auto eine Phase im
  /// [PhaseBloc] existiert. Wird im build() reaktiv aufgerufen, daher mit
  /// `_initializedCarId` gegen mehrfache Loads gesichert.
  ///
  /// Wichtig: Wir feuern den Load erst, sobald sowohl Tour als auch Cars
  /// einen geladen-Zustand haben — sonst fragt der `PhaseBloc` den
  /// `carCountResolver` ab, bekommt `null` und entscheidet für Mehr-Auto-
  /// Teams fälschlich auf `sortieren` statt `auswaehlen`.
  void _ensurePhaseLoaded(String carId) {
    if (_initializedCarId == carId) return;
    final carsState = context.read<CarsBloc>().state;
    if (carsState is! CarsLoaded) return;
    _initializedCarId = carId;
    context.read<PhaseBloc>().add(PhaseLoadForCar(carId: carId));
  }

  /// Ein-Auto-Teams überspringen die „Auswählen"-Phase (s. [PhaseBloc]),
  /// in der Lieferungen normalerweise einem Fahrzeug zugeordnet werden.
  /// Ohne Zuordnung (`assignedCarId`) blieben sie in „Ausliefern" unsichtbar.
  /// Daher hier einmalig: ist genau EIN Fahrzeug im Team, werden alle noch
  /// nicht zugeordneten Lieferungen automatisch diesem Fahrzeug zugewiesen.
  ///
  /// Reaktiv (im build) aufgerufen, aber per [_autoAssignedForCar] gegen
  /// Mehrfachausführung gesichert. Greift erst, wenn Tour UND Cars geladen
  /// sind (sonst Abbruch ohne Flag → erneuter Versuch beim nächsten Build).
  void _ensureSingleCarAssignment(String carId) {
    final carsState = context.read<CarsBloc>().state;
    final tourState = context.read<TourBloc>().state;
    if (carsState is! CarsLoaded || tourState is! TourLoaded) return;

    // Nur Ein-Auto-Teams: bei ≥2 Fahrzeugen entscheidet der Fahrer aktiv in
    // der „Auswählen"-Phase, hier wird bewusst nichts automatisch zugewiesen.
    if (carsState.cars.length != 1) return;

    // Fahrzeugwechsel → Tracking zurücksetzen.
    if (_autoAssignCar != carId) {
      _autoAssignCar = carId;
      _autoAssignDispatched.clear();
    }

    final tourBloc = context.read<TourBloc>();
    for (final delivery in tourState.details.deliveries) {
      // Jede (auch NEU gesyncte) noch nicht zugeordnete Lieferung genau einmal
      // zuweisen. `Set.add` liefert `false`, wenn schon dispatcht → kein Respam
      // in den Builds, bis der Server `assignedCarId` gesetzt hat.
      if (delivery.assignedCarId != carId &&
          _autoAssignDispatched.add(delivery.id)) {
        tourBloc.add(
          AssignCarToDelivery(deliveryId: delivery.id, carId: carId),
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<CarSelectBloc, CarSelectState>(
      builder: (context, carState) {
        // Ohne ausgewähltes Auto bleibt Home leer — der CarSelectionEnforcer
        // legt die Selection-Page als Overlay darüber.
        if (carState is! CarSelectComplete) {
          return const Scaffold(body: SizedBox.shrink());
        }

        final carId = carState.selectedCar.id.toString();

        // Nachzieh-Trigger: wenn Cars erst NACH dem Tour-Build fertig
        // werden, würde `_ensurePhaseLoaded` beim Tour-Build noch
        // skippen. Dieser Listener feuert sobald `CarsLoaded` da ist.
        return BlocListener<CarsBloc, CarsState>(
          listenWhen: (prev, curr) =>
              prev is! CarsLoaded && curr is CarsLoaded,
          listener: (context, _) {
            _ensurePhaseLoaded(carId);
            _ensureSingleCarAssignment(carId);
          },
          child: BlocBuilder<TourBloc, TourState>(
            builder: (context, tourState) {
              if (tourState is TourLoaded || tourState is TourEmpty) {
                _ensurePhaseLoaded(carId);
              }
              if (tourState is TourLoaded) {
                _ensureSingleCarAssignment(carId);
              }

              return BlocBuilder<PhaseBloc, PhaseState>(
                builder: (context, phaseState) {
                  final phase = phaseState is PhaseReady
                      ? phaseState.phaseFor(carId)
                      : null;

                  // Solange Tour, Cars oder Phase noch laden, kurzen
                  // Spinner zeigen — das dauert in der Praxis maximal
                  // ein paar Frames.
                  if (phase == null) {
                    return const Scaffold(
                      body: Center(child: CircularProgressIndicator()),
                    );
                  }

                  return _buildForPhase(
                    context,
                    phase,
                    carState.selectedCar.id,
                  );
                },
              );
            },
          ),
        );
      },
    );
  }

  Widget _buildForPhase(
    BuildContext context,
    DeliveryPhase phase,
    String selectedCarId,
  ) {
    switch (phase) {
      case DeliveryPhase.auswaehlen:
        // Auswahl-Page nur sichtbar bei Teams mit ≥2 Fahrzeugen — der
        // PhaseBloc setzt diese Phase nicht für Ein-Auto-Teams.
        return DeliverySelectionPage(selectedCarId: selectedCarId);
      case DeliveryPhase.sortieren:
        // Sort-Page baut eigenen Scaffold inkl. Stepper-Header.
        return DeliverySortPage(selectedCarId: selectedCarId);
      case DeliveryPhase.beladen:
        // Beladen-Phase: Einstieg über die Übersicht. Der Fahrer wählt selbst
        // aus, mit welchem Kunden er starten möchte — das Kunden-Vollbild
        // wird per Tap auf eine Karte geöffnet (siehe LoadingOverviewPage).
        return const LoadingOverviewPage();
      case DeliveryPhase.ausliefern:
        return const _DeliveryHome();
    }
  }
}

/// Home für die Auslieferungs-Phase. Reine Hülle um die Übersicht — es gibt
/// keine BottomNavigationBar mehr: Fahrzeug-Verwaltung und Einstellungen
/// sind über den Drawer erreichbar, der Fahrzeug-Wechsel direkt aus dem
/// PhaseStepper (Icon neben dem Plate).
class _DeliveryHome extends StatelessWidget {
  const _DeliveryHome();

  @override
  Widget build(BuildContext context) {
    return const DeliveryOverviewPage();
  }
}
