/// Adress-Rolle eines Beleg-Kontakts. Spiegelt die fünf Adress-FKs am
/// ERP-`Belegkopf` (bzw. den Umweg über `Kunden.AdressId`). Die App nutzt
/// das primär als Gruppierungs-Label in der Detail-Ansicht.
enum ContactRole {
  /// `Belegkopf.AdressId` — die „eigentliche" Belegadresse.
  header,

  /// `Belegkopf.LieferAdressId` — kann von der Belegadresse abweichen.
  delivery,

  /// `Belegkopf.RechnungsAdressId`.
  billing,

  /// `Belegkopf.AnsprechpartnerId` — verlinkt eine Person, nicht eine Firma.
  contactPerson,

  /// `Kunden.AdressId` (über `Belegkopf.KundenId`). Die Stammadresse des
  /// Kunden — dient als Fallback, wenn die belegspezifischen Adressen leer
  /// sind.
  customerMaster;

  /// Wire-Repräsentation aus dem Backend (serde `snake_case`).
  static ContactRole fromWire(String value) {
    switch (value) {
      case 'header':
        return ContactRole.header;
      case 'delivery':
        return ContactRole.delivery;
      case 'billing':
        return ContactRole.billing;
      case 'contact_person':
        return ContactRole.contactPerson;
      case 'customer_master':
        return ContactRole.customerMaster;
      default:
        throw StateError('Unbekannte ContactRole vom Backend: $value');
    }
  }

  /// Deutscher Label-Text für die UI.
  String get label {
    switch (this) {
      case ContactRole.header:
        return 'Belegadresse';
      case ContactRole.delivery:
        return 'Lieferadresse';
      case ContactRole.billing:
        return 'Rechnungsadresse';
      case ContactRole.contactPerson:
        return 'Ansprechpartner';
      case ContactRole.customerMaster:
        return 'Kundenstamm';
    }
  }
}

/// Art eines Kommunikationskanals. `fax` wird vom Backend bewusst nicht
/// mitgeführt — die App braucht es nicht.
enum ContactKind {
  phone,
  mobile,
  email,
  web;

  static ContactKind fromWire(String value) {
    switch (value) {
      case 'phone':
        return ContactKind.phone;
      case 'mobile':
        return ContactKind.mobile;
      case 'email':
        return ContactKind.email;
      case 'web':
        return ContactKind.web;
      default:
        throw StateError('Unbekannter ContactKind vom Backend: $value');
    }
  }
}

/// Eine Adress-Quelle, die am Beleg hängt — z. B. Lieferadresse oder
/// Ansprechpartner. Der Namensblock kommt direkt aus ERP-`Adressen`
/// (`Anrede`/`Titel`/`Name1..3`/`Abteilung`/`Funktion`); die eigentlichen
/// Telefonnummern, E-Mails etc. liegen verteilt in zugehörigen
/// [ContactChannel]s und werden in [TourDetails.channelsOf] zusammengeführt.
class ContactSource {
  const ContactSource({
    required this.id,
    required this.deliveryId,
    required this.role,
    this.anrede,
    this.titel,
    this.name1,
    this.name2,
    this.name3,
    this.abteilung,
    this.funktion,
  });

  final String id;
  final String deliveryId;
  final ContactRole role;

  final String? anrede;
  final String? titel;
  final String? name1;
  final String? name2;
  final String? name3;
  final String? abteilung;
  final String? funktion;

  /// Zusammengesetzte Anzeige des Namens — Anrede + Titel + Name1..3 in
  /// dieser Reihenfolge, leere Felder werden übersprungen. Gibt `null`
  /// zurück, wenn die Quelle gar keinen Namen trägt (kann vorkommen, wenn
  /// nur Telefonnummern hinterlegt sind).
  String? get displayName {
    final parts = <String>[
      if (anrede != null && anrede!.isNotEmpty) anrede!,
      if (titel != null && titel!.isNotEmpty) titel!,
      if (name1 != null && name1!.isNotEmpty) name1!,
      if (name2 != null && name2!.isNotEmpty) name2!,
      if (name3 != null && name3!.isNotEmpty) name3!,
    ];
    if (parts.isEmpty) return null;
    return parts.join(' ');
  }

  /// Funktionale Zusatzinfo (z. B. „Buchhaltung · Leitung"). Leere
  /// Komponenten werden ausgeblendet.
  String? get subtitle {
    final parts = <String>[
      if (abteilung != null && abteilung!.isNotEmpty) abteilung!,
      if (funktion != null && funktion!.isNotEmpty) funktion!,
    ];
    if (parts.isEmpty) return null;
    return parts.join(' · ');
  }
}

/// Ein einzelner Kommunikationskanal (Telefon, Mobil, E-Mail, Web). Mehrere
/// pro [ContactSource] möglich; die [position] (1-basiert) erhält die
/// ERP-Reihenfolge — Position 1 ist der primäre Kanal, Position 2 das
/// erste Zusatzfeld usw.
class ContactChannel {
  const ContactChannel({
    required this.id,
    required this.sourceId,
    required this.kind,
    required this.position,
    required this.value,
  });

  final String id;
  final String sourceId;
  final ContactKind kind;
  final int position;
  final String value;
}

/// Zusammengeführte Sicht auf 1..n [ContactSource]s, die fachlich denselben
/// Kontakt darstellen — gleicher Namensblock UND gleiche Channel-Liste
/// (also exakt dieselbe Adresse im ERP, nur über verschiedene FKs am
/// `Belegkopf` referenziert: typischerweise `AdressId` und `Kunden.AdressId`,
/// die in den allermeisten Belegen identisch sind).
///
/// Die App rendert pro Lieferung eine Karte je Eintrag; `roles` listet
/// alle Rollen auf, die zu diesem Eintrag beitragen (z. B. „Belegadresse ·
/// Kundenstamm"). Die Channels werden 1:1 von der ersten Quelle übernommen
/// — alle Quellen in einer Gruppe haben dieselben.
class MergedContactSource {
  const MergedContactSource({
    required this.roles,
    required this.anrede,
    required this.titel,
    required this.name1,
    required this.name2,
    required this.name3,
    required this.abteilung,
    required this.funktion,
    required this.channels,
  });

  /// Alle Rollen, die diesen zusammengeführten Kontakt liefern.
  /// Reihenfolge wie in der enum-Definition: header → delivery → billing
  /// → contactPerson → customerMaster, damit das Label stabil bleibt.
  final List<ContactRole> roles;

  final String? anrede;
  final String? titel;
  final String? name1;
  final String? name2;
  final String? name3;
  final String? abteilung;
  final String? funktion;

  /// Channels in der gleichen Reihenfolge, wie das Backend sie pro Quelle
  /// liefert (kind + ERP-Position).
  final List<ContactChannel> channels;

  /// Zusammengesetzter Anzeigename — identisch zu [ContactSource.displayName].
  String? get displayName {
    final parts = <String>[
      if (anrede != null && anrede!.isNotEmpty) anrede!,
      if (titel != null && titel!.isNotEmpty) titel!,
      if (name1 != null && name1!.isNotEmpty) name1!,
      if (name2 != null && name2!.isNotEmpty) name2!,
      if (name3 != null && name3!.isNotEmpty) name3!,
    ];
    if (parts.isEmpty) return null;
    return parts.join(' ');
  }

  String? get subtitle {
    final parts = <String>[
      if (abteilung != null && abteilung!.isNotEmpty) abteilung!,
      if (funktion != null && funktion!.isNotEmpty) funktion!,
    ];
    if (parts.isEmpty) return null;
    return parts.join(' · ');
  }

  /// Header-Label für die UI — alle Rollen mit `·` getrennt, in
  /// Enum-Reihenfolge.
  String get rolesLabel => roles.map((r) => r.label).join(' · ');
}

