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

import 'package:hl_lieferservice/domain/entity/payment_method.dart';
import 'package:hl_lieferservice/domain/repository/payment_methods_repository.dart';

/// Cubit-State der Zahlungsmethoden-Stammdaten.
sealed class PaymentMethodsState {
  const PaymentMethodsState();
}

class PaymentMethodsInitial extends PaymentMethodsState {
  const PaymentMethodsInitial();
}

class PaymentMethodsLoading extends PaymentMethodsState {
  const PaymentMethodsLoading();
}

class PaymentMethodsLoaded extends PaymentMethodsState {
  const PaymentMethodsLoaded(this.methods);

  /// Alle aktiven Methoden (Backend filtert standardmäßig `includeInactive=false`).
  /// Reihenfolge ist die vom Server gelieferte — der sortiert nach `createdAt`.
  final List<PaymentMethod> methods;

  /// Lookup nach `id`. Liefert `null` für historische Lieferungen, deren
  /// referenzierte Methode inzwischen deaktiviert und damit aus der Liste
  /// gefallen ist — der Aufrufer muss diesen Fall im UI abfangen.
  PaymentMethod? byId(String id) {
    for (final m in methods) {
      if (m.id == id) return m;
    }
    return null;
  }
}

class PaymentMethodsFailed extends PaymentMethodsState {
  const PaymentMethodsFailed(this.message);
  final String message;
}

/// Lädt die Zahlungsmethoden-Stammdaten einmal beim Login und stellt sie
/// als globalen Lookup zur Verfügung.
///
/// Bewusst Cubit statt Bloc: keine Events, nur Refresh — und der Lookup
/// (`PaymentMethodsLoaded.byId`) ist die zentrale UI-Konsumstelle. Cached
/// die Liste so lange, bis explizit `refresh()` aufgerufen wird, weil
/// die Stammdaten sich tagsüber praktisch nie ändern.
class PaymentMethodsCubit extends Cubit<PaymentMethodsState> {
  PaymentMethodsCubit({required this.repository})
      : super(const PaymentMethodsInitial());

  final PaymentMethodsRepository repository;

  Future<void> load() async {
    if (state is PaymentMethodsLoading) return;
    emit(const PaymentMethodsLoading());
    try {
      final methods = await repository.list();
      emit(PaymentMethodsLoaded(methods));
    } catch (e, st) {
      debugPrint('PaymentMethodsCubit.load fehlgeschlagen: $e\n$st');
      final message = e is PaymentMethodsRepositoryException
          ? e.message
          : 'Zahlungsmethoden konnten nicht geladen werden';
      emit(PaymentMethodsFailed(message));
    }
  }

  /// Explizit erneut vom Server holen — UI ruft das auf, falls die User
  /// die Stammdaten zwischendurch im Verwaltungs-Screen geändert hat.
  Future<void> refresh() => load();
}
