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<void> exportAndShare({
    required List<StakeoutPoint> 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)' : ''}',
    ));
  }
}
