import 'dart:io'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart'; import '../../models/stakeout_point.dart'; /// Kitűzési jegyzőkönyv CSV-export. /// /// Két dialektus: /// * MAGYAR (Excel-barát): pontosvessző elválasztó, tizedesVESSZŐ, /// UTF-8 BOM-mal (enélkül az Excel elrontja az ékezeteket) /// * NEMZETKÖZI: vessző elválasztó, tizedespont /// /// A jegyzőkönyv a teljes dokumentációt tartalmazza: terv- ÉS mért /// koordináták, inline/crossline/dZ eltérések, fix-minőség, pontosság, /// időpont, eszköz, valamint az eltolt pontoknál az eltolás-vektor. class StakeoutExportService { StakeoutExportService._(); static Future exportAndShare({ required List points, required bool hungarian, required bool stakedOnly, String projectName = '', }) async { final rows = stakedOnly ? points.where((p) => p.status == StakeoutStatus.staked).toList() : List.of(points); if (rows.isEmpty) { throw StateError('Nincs exportálható pont.'); } rows.sort((a, b) => a.lineId != b.lineId ? a.lineId.compareTo(b.lineId) : a.station.compareTo(b.station)); final sep = hungarian ? ';' : ','; String num(double? v, [int dec = 3]) { if (v == null) return ''; final s = v.toStringAsFixed(dec); return hungarian ? s.replaceAll('.', ',') : s; } String txt(String s) => s.contains(sep) || s.contains('"') || s.contains('\n') ? '"${s.replaceAll('"', '""')}"' : s; String status(StakeoutStatus s) => switch (s) { StakeoutStatus.pending => 'varakozik', StakeoutStatus.staked => 'kituzve', StakeoutStatus.skipped => 'kihagyva', }; String fix(int? q) => switch (q) { 4 => 'RTK_FIXED', 5 => 'RTK_FLOAT', 2 => 'DGPS', 1 => 'GPS', 0 => 'NO_FIX', null => '', _ => 'Q$q', }; final header = [ 'Vonal', 'Allomas', 'Nev', 'Tipus', 'Statusz', 'Terv_EOV_Y', 'Terv_EOV_X', 'Terv_EOV_Z', 'Mert_EOV_Y', 'Mert_EOV_X', 'Mert_EOV_Z', 'Inline_m', 'Crossline_m', 'dZ_m', 'Fix', 'Pontossag_m', 'Kituzes_ideje', 'Eltolt', 'Eltolas_m', 'Eltolas_irany_fok', 'Eszkoz_id', 'Forras', ].join(sep); final sb = StringBuffer(); sb.write('\uFEFF'); // UTF-8 BOM — az Excel enélkül elrontja az ékezeteket sb.writeln(header); for (final r in rows) { sb.writeln([ txt(r.lineId), r.station.toString(), txt(r.name), txt(r.pointType), status(r.status), num(r.planEovY), num(r.planEovX), num(r.planEovZ), num(r.measuredEovY), num(r.measuredEovX), num(r.measuredEovZ), num(r.devInline), num(r.devCrossline), num(r.devDz), fix(r.fixQuality), num(r.accuracy, 2), r.stakedAt?.toIso8601String() ?? '', r.isOffset ? '1' : '0', num(r.offsetDist, 2), num(r.offsetBearing, 1), txt(r.deviceId ?? ''), txt(r.source), ].join(sep)); } final dir = await getTemporaryDirectory(); final stamp = DateTime.now() .toIso8601String() .substring(0, 16) .replaceAll(':', '') .replaceAll('-', '') .replaceAll('T', '_'); final safeName = projectName.isEmpty ? 'kituzes' : projectName.replaceAll(RegExp(r'[^\w\-]'), '_'); final path = p.join(dir.path, '${safeName}_$stamp.csv'); await File(path).writeAsString(sb.toString(), flush: true); await SharePlus.instance.share(ShareParams( files: [XFile(path, mimeType: 'text/csv')], subject: 'Kitűzési jegyzőkönyv — $projectName', text: '${rows.length} pont' '${stakedOnly ? ' (csak kitűzöttek)' : ''}', )); } }