import 'package:dio/dio.dart';
import 'package:holzleitner_api/holzleitner_api.dart' as api;

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

/// Dio-Impl gegen den generierten `PaymentMethodsApi`.
///
/// Fehler-Mapping:
/// * `409 Conflict` (UNIQUE-Verletzung oder FK-RESTRICT beim Löschen)
///   → `PaymentMethodsRepositoryException` mit klarer Meldung.
/// * `404` → dito (NotFound-Hinweis im Text).
/// * `401` lassen wir ungefangen durchfliegen — globaler Auth-Handler
///   übernimmt.
class PaymentMethodsRepositoryImpl implements PaymentMethodsRepository {
  PaymentMethodsRepositoryImpl(this._api);

  final api.HolzleitnerApi _api;

  @override
  Future<List<PaymentMethod>> list({bool includeInactive = false}) async {
    try {
      final response = await _api
          .getPaymentMethodsApi()
          .listPaymentMethods(includeInactive: includeInactive);
      final methods = response.data?.methods;
      if (methods == null) return const [];
      return methods.map((m) => m.toDomain()).toList(growable: false);
    } on DioException catch (e) {
      throw PaymentMethodsRepositoryException(
        _describe(e, 'Laden der Zahlungsmethoden'),
        e,
      );
    }
  }

  @override
  Future<PaymentMethod> create({
    required String code,
    required String name,
  }) async {
    try {
      final request = api.CreatePaymentMethodRequest((b) {
        b
          ..code = code
          ..name = name;
      });
      final response = await _api
          .getPaymentMethodsApi()
          .createPaymentMethod(createPaymentMethodRequest: request);
      final method = response.data?.method;
      if (method == null) {
        throw const PaymentMethodsRepositoryException(
          'Server lieferte leere Antwort beim Anlegen',
        );
      }
      return method.toDomain();
    } on DioException catch (e) {
      throw PaymentMethodsRepositoryException(
        _describe(e, 'Anlegen einer Zahlungsmethode'),
        e,
      );
    }
  }

  @override
  Future<PaymentMethod> update({
    required String id,
    String? name,
    bool? active,
  }) async {
    try {
      final request = api.UpdatePaymentMethodRequest((b) {
        if (name != null) b.name = name;
        if (active != null) b.active = active;
      });
      final response =
          await _api.getPaymentMethodsApi().updatePaymentMethod(
                id: id,
                updatePaymentMethodRequest: request,
              );
      final method = response.data?.method;
      if (method == null) {
        throw const PaymentMethodsRepositoryException(
          'Server lieferte leere Antwort beim Aktualisieren',
        );
      }
      return method.toDomain();
    } on DioException catch (e) {
      throw PaymentMethodsRepositoryException(
        _describe(e, 'Aktualisieren einer Zahlungsmethode'),
        e,
      );
    }
  }

  @override
  Future<void> delete(String id) async {
    try {
      await _api.getPaymentMethodsApi().deletePaymentMethod(id: id);
    } on DioException catch (e) {
      throw PaymentMethodsRepositoryException(
        _describe(e, 'Löschen einer Zahlungsmethode'),
        e,
      );
    }
  }

  String _describe(DioException e, String operation) {
    final status = e.response?.statusCode;
    final body = e.response?.data;
    if ((status == 400 || status == 409) &&
        body is Map &&
        body['message'] != null) {
      return body['message'].toString();
    }
    if (status == 409) {
      return 'Zahlungsmethode wird noch von Lieferungen verwendet';
    }
    if (status == 404) return 'Zahlungsmethode nicht gefunden';
    if (status == 401) return 'Sitzung abgelaufen';
    return '$operation fehlgeschlagen (HTTP ${status ?? 'unbekannt'})';
  }
}
