// ─── GSV mondatelemző ──────────────────────────────────────────────────────

import 'package:nmea/nmea.dart';
import 'package:terepi_seged/models/satellite_info.dart';

/// GSV — GNSS Satellites in View
///
/// Formátum (max 4 műhold/mondat):
/// $GPGSV,3,1,11,01,70,042,45,03,55,218,48,07,22,085,35,10,35,315,40*73
///         │ │  │   │   │   │   │
///         │ │  │   PRN El  Az  SNR (×4 max)
///         │ │  └── összes látható műhold száma
///         │ └───── ezen mondat sorszáma (1-től)
///         └─────── összes GSV mondat ebben a ciklusban
///
/// Több mondat alkotja az epochot:
///   GPGSV (GPS) + GLGSV (GLONASS) + GAGSV (Galileo) + GBGSV (BeiDou)
class Gngsv extends TalkerSentence {
  static const String id = 'GNGSV';

  Gngsv({required super.raw});

  @override
  bool get valid =>
      super.valid && fields.length >= 8; // min: típus + 3 fejléc + 1×4 műhold

  // ── Fejléc mezők ─────────────────────────────────────────────────

  /// Összes GSV mondat ezen rendszerhez ebben az epochban
  int get totalMessages => int.tryParse(fields[1]) ?? 1;

  /// Az aktuális mondat sorszáma
  int get messageNumber => int.tryParse(fields[2]) ?? 1;

  /// Összes látható műhold száma az adott stream-ben
  int get totalSatellitesInView => int.tryParse(fields[3]) ?? 0;

  /// Ez az utolsó mondat az adott rendszer GSV sorozatában?
  bool get isLastMessage => messageNumber == totalMessages;

  String get talkerId => raw.length >= 3 ? raw.substring(1, 3) : 'GN';

  GnssConstellation get constellation =>
      SatelliteInfo.constellationFromTalker(talkerId);

  String get systemName => switch (constellation) {
        GnssConstellation.gps => 'GPS',
        GnssConstellation.glonass => 'GLONASS',
        GnssConstellation.galileo => 'Galileo',
        GnssConstellation.beidou => 'BeiDou',
        GnssConstellation.qzss => 'QZSS',
        GnssConstellation.sbas => 'SBAS',
        GnssConstellation.navic => 'NavIC',
        GnssConstellation.mixed => 'Mixed',
        GnssConstellation.unknown => 'Unknown',
      };

  /// Opcionális NMEA Signal ID
  ///
  /// Header: 4 mezo
  /// Minden muhold: 4 mezo
  /// Ha marad +1 mezo, az a signalId
  int? get signalId {
    final payloadCount = fields.length - 4;
    if (payloadCount <= 0) return null;

    final hasSignalId = payloadCount % 4 == 1;
    if (!hasSignalId) return null;

    final rawSignal = fields.last.split('*').first.trim();
    if (rawSignal.isEmpty) return null;
    return int.tryParse(rawSignal);
  }

  /// Egy stream kulcsa: ugyanazon talker, ugyanazon signal
  String get streamKey => '$talkerId:${signalId ?? -1}';

  // ── Műholdak ebben a mondatban ───────────────────────────────────

  /// A mondatban szereplő műholdak listája (max 4)
  List<SatelliteInfo> get satellites {
    final sats = <SatelliteInfo>[];

    // Minden műhold 4 mezőt foglal: PRN, eleváció, azimut, SNR
    // fields[4]-től kezdődnek, fields[0] = mondattípus
    for (int i = 0; i < 4; i++) {
      final base = 4 + i * 4;

      // Ellenőrzés: van-e elég mező
      if (base + 3 >= fields.length) break;

      final prn = int.tryParse(_field(base));
      final elev = int.tryParse(_field(base + 1)) ?? 0;
      final az = int.tryParse(_field(base + 2)) ?? 0;
      final snr = int.tryParse(_field(base + 3).split('*').first) ?? 0;

      if (prn != null && prn > 0) {
        sats.add(SatelliteInfo(
          prn: prn,
          elevation: elev,
          azimuth: az,
          snr: snr,
          constellation: constellation,
          signalId: signalId,
        ));
      }
    }

    return sats;
  }

  String _field(int index) {
    if (index < 0 || index >= fields.length) return '';
    return fields[index].trim();
  }
}
