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/events.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_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';

/// Horizontaler Phasen-Stepper für die drei bzw. vier Schritte
/// (Auswählen) → Sortieren → Beladen → Ausliefern.
///
/// Ersetzt während aller Pre-Lieferungs-Phasen die [BottomNavigationBar]
/// und dient zugleich als globaler Header oberhalb der Phase-Inhalts-Page.
///
/// Sichtbare Phasen:
/// * Ein-Auto-Teams: Sortieren, Beladen, Ausliefern (3 Schritte).
/// * Mehr-Auto-Teams: Auswählen, Sortieren, Beladen, Ausliefern (4 Schritte).
///
/// Die Sichtbarkeitsliste wird intern aus dem [CarsBloc] abgeleitet
/// (Anzahl Fahrzeuge im Account). So müssen Aufrufer den Stepper nicht
/// mit Routing-Wissen versorgen — er bleibt eine reine Anzeige-Komponente,
/// die auf den globalen State reagiert.
///
/// Verhalten:
/// * Aktuelle Phase ist visuell hervorgehoben.
/// * Bereits besuchte Phasen (Phasen, die der Fahrer heute schon erreicht
///   hatte — verfolgt über `maxPhase` im [PhaseBloc]) lassen sich antippen,
///   auch wenn man aktuell auf einer früheren Phase steht. Damit kann der
///   Fahrer beliebig zwischen besuchten Schritten hin- und herspringen.
/// * Noch nicht besuchte Phasen sind sperren (SnackBar-Hinweis).
/// * Über das Menü-Icon links wird der Drawer geöffnet (Fahrzeuge/Settings).
/// * Daneben sitzt ein Reload-Button, der über `RefreshTour` einen
///   Backend-Refresh anstößt (z. B. wenn ein Disponent eine Lieferung
///   nachgetragen oder umverteilt hat). Während ein Refresh läuft,
///   ersetzt ein kleiner Spinner das Icon und der Button ist gesperrt.
/// * Rechts steht das Plate des aktiv gewählten Fahrzeugs.
class PhaseStepper extends StatelessWidget {
  const PhaseStepper({
    super.key,
    required this.currentPhase,
    required this.carId,
    this.visiblePhases,
  });

  /// Die aktuell aktive Phase des Fahrzeugs.
  final DeliveryPhase currentPhase;

  /// Auto-ID, an der die Phase im [PhaseBloc] gespeichert wird.
  final String carId;

  /// Optionaler Override für Tests / Sonderfälle. Default: aus CarsBloc
  /// abgeleitet (Anzahl cars im Account).
  final List<DeliveryPhase>? visiblePhases;

  IconData _iconFor(DeliveryPhase phase) {
    return switch (phase) {
      DeliveryPhase.auswaehlen => Icons.checklist_outlined,
      DeliveryPhase.sortieren => Icons.reorder,
      DeliveryPhase.beladen => Icons.inventory_2_outlined,
      DeliveryPhase.ausliefern => Icons.local_shipping_outlined,
    };
  }

  /// Stellt sicher, dass auch die [currentPhase] in der angezeigten Liste
  /// enthalten ist. Falls z. B. ein persistierter `auswaehlen`-State noch
  /// aus einem Mehr-Auto-Team stammt, das Team aber inzwischen nur noch
  /// ein Auto hat, würde die Phase sonst unsichtbar — wir nehmen sie dann
  /// vorne mit auf, damit der Stepper konsistent bleibt.
  List<DeliveryPhase> _effectivePhases(int carCount) {
    final base = DeliveryPhaseExtension.visiblePhasesForCarCount(carCount);
    if (base.contains(currentPhase)) return base;
    return [currentPhase, ...base];
  }

  void _onTap(
    BuildContext context,
    DeliveryPhase target,
    DeliveryPhase maxReached,
  ) {
    // Vergleich über die natürliche Enum-Reihenfolge, weil "höchste erreichte
    // Phase" cross-Team konsistent ist (1- vs. Mehr-Auto-Teams).
    if (target.index > maxReached.index) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(
            "Schritt \"${target.displayName}\" ist noch nicht erreicht.",
          ),
          duration: const Duration(seconds: 2),
        ),
      );
      return;
    }
    if (target == currentPhase) return;

    // Vor dem Phasen-Wechsel alle gepushten Routen entfernen (z. B. die
    // LoadingOverviewPage). Sonst rendert home.dart die neue Phase nur im
    // Hintergrund, während die alte Page mit ihrem Scanner-State sichtbar
    // bleibt — was zu einer toten Kamera-View führt.
    Navigator.of(context).popUntil((route) => route.isFirst);

    context.read<PhaseBloc>().add(
          PhaseSet(carId: carId, phase: target),
        );
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final onPrimary = theme.colorScheme.onPrimary;

    return BlocBuilder<CarsBloc, CarsState>(
      // Stepper reagiert auf cars.length-Änderungen — sonst praktisch statisch.
      buildWhen: (prev, curr) {
        if (visiblePhases != null) return prev != curr; // override aktiv
        final prevCars = prev is CarsLoaded ? prev.cars.length : 0;
        final currCars = curr is CarsLoaded ? curr.cars.length : 0;
        return prevCars != currCars || prev.runtimeType != curr.runtimeType;
      },
      builder: (context, carsState) {
        final carCount = carsState is CarsLoaded ? carsState.cars.length : 0;
        final phases = visiblePhases ?? _effectivePhases(carCount);

        // Höchste erreichte Phase aus dem PhaseBloc — bestimmt, welche
        // Vorwärts-Sprünge erlaubt sind.
        final phaseBlocState = context.watch<PhaseBloc>().state;
        final maxReached = phaseBlocState is PhaseReady
            ? (phaseBlocState.maxPhaseFor(carId) ?? currentPhase)
            : currentPhase;

        return Material(
          color: theme.primaryColor,
          child: SafeArea(
            bottom: false,
            child: Padding(
              padding: const EdgeInsets.fromLTRB(4, 4, 8, 30),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Row(
                    children: [
                      // Menü-Button — öffnet den Drawer des umgebenden Scaffolds.
                      IconButton(
                        icon: Icon(Icons.menu, color: onPrimary),
                        tooltip: "Menü",
                        onPressed: () => Scaffold.of(context).openDrawer(),
                      ),
                      _ReloadButton(onPrimary: onPrimary),
                      const Spacer(),
                      BlocBuilder<CarSelectBloc, CarSelectState>(
                        builder: (context, state) {
                          if (state is! CarSelectComplete) {
                            return const SizedBox.shrink();
                          }
                          return _SelectedCarPill(
                            plate: state.selectedCar.plate,
                            onPrimary: onPrimary,
                          );
                        },
                      ),
                    ],
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 4),
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        for (int i = 0; i < phases.length; i++) ...[
                          Expanded(
                            child: _StepperItem(
                              phase: phases[i],
                              currentPhase: currentPhase,
                              maxReached: maxReached,
                              visiblePhases: phases,
                              icon: _iconFor(phases[i]),
                              onTap: () =>
                                  _onTap(context, phases[i], maxReached),
                            ),
                          ),
                          if (i < phases.length - 1)
                            _Connector(
                              // Verbindung gilt als "abgehakt", wenn die rechte
                              // Phase bereits besucht wurde.
                              isPassed:
                                  phases[i + 1].index <= maxReached.index,
                            ),
                        ],
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      },
    );
  }
}

class _StepperItem extends StatelessWidget {
  const _StepperItem({
    required this.phase,
    required this.currentPhase,
    required this.maxReached,
    required this.visiblePhases,
    required this.icon,
    required this.onTap,
  });

  final DeliveryPhase phase;
  final DeliveryPhase currentPhase;
  final DeliveryPhase maxReached;
  final List<DeliveryPhase> visiblePhases;
  final IconData icon;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final onPrimary = theme.colorScheme.onPrimary;

    final int myStep = phase.stepNumberIn(visiblePhases);

    final bool isCurrent = phase == currentPhase;
    // "Besucht" = irgendwann heute schon erreicht (über Enum-Index), aber
    // nicht die aktuelle Phase. Erlaubt sowohl Rück- als auch Vorwärts-Tap.
    final bool isPassed =
        !isCurrent && phase.index <= maxReached.index;

    final Color circleColor;
    final Color iconColor;
    final Color labelColor;
    final FontWeight labelWeight;

    if (isCurrent) {
      circleColor = onPrimary;
      iconColor = theme.primaryColor;
      labelColor = onPrimary;
      labelWeight = FontWeight.w700;
    } else if (isPassed) {
      circleColor = onPrimary.withValues(alpha: 0.85);
      iconColor = theme.primaryColor;
      labelColor = onPrimary;
      labelWeight = FontWeight.w600;
    } else {
      circleColor = onPrimary.withValues(alpha: 0.25);
      iconColor = onPrimary.withValues(alpha: 0.65);
      labelColor = onPrimary.withValues(alpha: 0.65);
      labelWeight = FontWeight.w500;
    }

    final child = Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Stack(
          alignment: Alignment.center,
          children: [
            Container(
              width: 32,
              height: 32,
              decoration: BoxDecoration(
                color: circleColor,
                shape: BoxShape.circle,
                border: isCurrent
                    ? Border.all(color: onPrimary, width: 2)
                    : null,
              ),
              child: Icon(icon, color: iconColor, size: 18),
            ),
            if (isPassed)
              Positioned(
                right: 0,
                bottom: 0,
                child: Container(
                  width: 13,
                  height: 13,
                  decoration: BoxDecoration(
                    color: Colors.green.shade600,
                    shape: BoxShape.circle,
                    border: Border.all(color: theme.primaryColor, width: 1.5),
                  ),
                  child: const Icon(
                    Icons.check,
                    color: Colors.white,
                    size: 8,
                  ),
                ),
              ),
          ],
        ),
        const SizedBox(height: 3),
        Text(
          phase.displayName,
          maxLines: 1,
          overflow: TextOverflow.ellipsis,
          style: TextStyle(
            color: labelColor,
            fontSize: 12,
            fontWeight: labelWeight,
          ),
        ),
      ],
    );

    return Semantics(
      button: true,
      selected: isCurrent,
      label:
          "${phase.displayName}, Schritt $myStep von ${visiblePhases.length}",
      child: InkWell(
        onTap: onTap,
        borderRadius: BorderRadius.circular(8),
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 2),
          child: child,
        ),
      ),
    );
  }
}

/// Dezente Pille rechts oben im Header: Lkw-Icon, Plate, kleiner Swap-Button.
///
/// Visuell zurückhaltend gehalten: leicht durchscheinender Hintergrund auf
/// dem Primary-Header, kompakter IconButton — der Plate-Text bleibt
/// dominantes Element, der Wechseln-Knopf ist eine sekundäre Geste, die
/// erst auf Anfrage benutzt wird.
class _SelectedCarPill extends StatelessWidget {
  const _SelectedCarPill({required this.plate, required this.onPrimary});

  final String plate;
  final Color onPrimary;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.only(left: 10, right: 2),
      decoration: BoxDecoration(
        color: onPrimary.withValues(alpha: 0.12),
        borderRadius: BorderRadius.circular(20),
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.local_shipping, color: onPrimary, size: 16),
          const SizedBox(width: 6),
          Text(
            plate,
            style: TextStyle(
              color: onPrimary,
              fontWeight: FontWeight.bold,
              fontSize: 14,
            ),
          ),
          const SizedBox(width: 2),
          IconButton(
            tooltip: 'Fahrzeug wechseln',
            icon: Icon(
              Icons.swap_horiz_rounded,
              // Etwas heller als das Plate, damit der Button als sekundäre
              // Aktion gelesen wird und das Plate nicht überstrahlt.
              color: onPrimary.withValues(alpha: 0.85),
              size: 18,
            ),
            visualDensity: VisualDensity.compact,
            padding: const EdgeInsets.all(4),
            constraints: const BoxConstraints(
              minWidth: 32,
              minHeight: 32,
            ),
            splashRadius: 18,
            onPressed: () =>
                context.read<CarSelectBloc>().add(CarSelectChange()),
          ),
        ],
      ),
    );
  }
}

class _Connector extends StatelessWidget {
  const _Connector({required this.isPassed});

  final bool isPassed;

  @override
  Widget build(BuildContext context) {
    final onPrimary = Theme.of(context).colorScheme.onPrimary;
    return Padding(
      padding: const EdgeInsets.only(bottom: 18),
      child: Container(
        width: 14,
        height: 2,
        color: isPassed ? onPrimary : onPrimary.withValues(alpha: 0.35),
      ),
    );
  }
}

/// Reload-Button in der oberen Reihe des [PhaseStepper]s. Feuert
/// `RefreshTour` am [TourBloc] — refresht im Hintergrund und behält den
/// aktuellen `TourLoaded`-Snapshot sichtbar (kein Flicker zurück auf den
/// Lade-Spinner). Während des Refreshs ersetzt eine kleine
/// Fortschrittsanzeige das Icon und der Button ist gesperrt, um
/// Doppel-Triggern zu verhindern.
class _ReloadButton extends StatelessWidget {
  const _ReloadButton({required this.onPrimary});

  final Color onPrimary;

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<TourBloc, TourState>(
      // Nur neu rendern, wenn sich der Refresh-Status ändert — sonst
      // läuft der Builder bei jedem Scan-Tick mit.
      buildWhen: (prev, curr) {
        final p = prev is TourLoaded && prev.isRefreshing;
        final c = curr is TourLoaded && curr.isRefreshing;
        return p != c || prev.runtimeType != curr.runtimeType;
      },
      builder: (context, state) {
        final isRefreshing = state is TourLoaded && state.isRefreshing;
        return IconButton(
          tooltip: 'Tour aktualisieren',
          onPressed: isRefreshing
              ? null
              : () => context.read<TourBloc>().add(const RefreshTour()),
          icon: isRefreshing
              ? SizedBox(
                  width: 20,
                  height: 20,
                  child: CircularProgressIndicator(
                    strokeWidth: 2,
                    color: onPrimary,
                  ),
                )
              : Icon(Icons.refresh, color: onPrimary),
        );
      },
    );
  }
}
