import 'dart:math' as math;
import 'dart:ui' show FontFeature;

import 'package:flutter/material.dart';
//import 'package:flutter/widget_previews.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/map_survey/presentations/widgets/stakeout_list_sheet.dart';
import 'package:terepi_seged/pages/map_survey/presentations/widgets/stakeout_settings_dialog.dart';
import 'package:terepi_seged/pages/map_survey/presentations/widgets/tilt_bubble.dart';
import 'package:terepi_seged/routes/app_pages.dart';
import 'package:terepi_seged/services/gnss/gnss_service.dart';
import 'package:terepi_seged/services/stakeout_service.dart';

/// Kitűzési alsó panel — a map_survey nézet overlay-jébe illesztendő
/// (mode == MapSurveyMode.stakeout esetén). Kétfázisú: 5 m felett nagy
/// irány-nyíl + távolság, alatta céltábla cm-es eltérésekkel. A tárolás,
/// kihagyás és transzverzális eltolás gombjai is itt vannak.
class StakeoutPanel extends StatelessWidget {
  const StakeoutPanel({super.key});

  @override
  Widget build(BuildContext context) {
    if (!Get.isRegistered<StakeoutService>()) return const SizedBox.shrink();
    final svc = StakeoutService.to;

    return Obx(() {
      // Üres állapot: import-hívás.
      if (svc.points.isEmpty) {
        return Card(
          margin: const EdgeInsets.all(8),
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Row(
              children: [
                const Expanded(
                  child: Text('Nincsenek kitűzési pontok az aktív '
                      'projektben.'),
                ),
                FilledButton.icon(
                  onPressed: () => Get.toNamed(Routes.STAKEOUT_IMPORT),
                  icon: const Icon(Icons.upload_file, size: 18),
                  label: const Text('Import'),
                ),
              ],
            ),
          ),
        );
      }

      final t = svc.target.value;
      if (t == null) {
        return Card(
          margin: const EdgeInsets.all(8),
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Text('Minden pont kitűzve vagy kihagyva. '
                '(${svc.points.length} pont)'),
          ),
        );
      }

      final within = svc.withinTolerance.value;
      final progress = svc.lineProgress[t.lineId];

      return Card(
        margin: const EdgeInsets.all(8),
        elevation: 6,
        color: within
            ? Colors.green.shade50
            : Theme.of(context).colorScheme.surface,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(16),
          side: within
              ? const BorderSide(color: Colors.green, width: 2)
              : BorderSide.none,
        ),
        child: Padding(
          padding: const EdgeInsets.fromLTRB(12, 4, 12, 10),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              // ── Fejléc ───────────────────────────────────────────
              Row(
                children: [
                  IconButton(
                    icon: const Icon(Icons.skip_previous),
                    visualDensity: VisualDensity.compact,
                    padding: EdgeInsets.zero,
                    constraints:
                        const BoxConstraints(minWidth: 36, minHeight: 36),
                    onPressed: () => svc.advance(backwards: true),
                  ),
                  // A cím rugalmas: szűk helyen ZSUGORODIK (FittedBox),
                  // sosem tördelődik karakterenként.
                  Expanded(
                    child: Column(
                      children: [
                        FittedBox(
                          fit: BoxFit.scaleDown,
                          child: Text(
                            t.displayId,
                            maxLines: 1,
                            style: const TextStyle(
                                fontSize: 17, fontWeight: FontWeight.w700),
                          ),
                        ),
                        if (progress != null)
                          Text(
                            '${progress.staked}/${progress.total} kitűzve'
                            '${t.isOffset ? ' · ELTOLT' : ''}',
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                            style: TextStyle(
                                fontSize: 11, color: Colors.grey.shade600),
                          ),
                      ],
                    ),
                  ),
                  IconButton(
                    icon: const Icon(Icons.skip_next),
                    visualDensity: VisualDensity.compact,
                    padding: EdgeInsets.zero,
                    constraints:
                        const BoxConstraints(minWidth: 36, minHeight: 36),
                    onPressed: () => svc.advance(),
                  ),
                  const TiltBubble(),
                  PopupMenuButton<StakeoutOrder>(
                    icon: Icon(switch (svc.orderMode.value) {
                      StakeoutOrder.idAsc => Icons.trending_up,
                      StakeoutOrder.idDesc => Icons.trending_down,
                      StakeoutOrder.nearest => Icons.near_me,
                    }),
                    padding: EdgeInsets.zero,
                    tooltip: 'Sorrend',
                    onSelected: (m) => svc.orderMode.value = m,
                    itemBuilder: (_) => const [
                      PopupMenuItem(
                          value: StakeoutOrder.idAsc,
                          child: Text('Állomás növekvő')),
                      PopupMenuItem(
                          value: StakeoutOrder.idDesc,
                          child: Text('Állomás csökkenő')),
                      PopupMenuItem(
                          value: StakeoutOrder.nearest,
                          child: Text('Legközelebbi')),
                    ],
                  ),
                  // A ritkán használt műveletek EGY menüben — a fejléc
                  // így keskeny kijelzőn / nagy betűméretnél is kifér.
                  PopupMenuButton<String>(
                    icon: const Icon(Icons.more_vert),
                    padding: EdgeInsets.zero,
                    tooltip: 'További műveletek',
                    onSelected: (a) {
                      switch (a) {
                        case 'list':
                          StakeoutListSheet.show();
                        case 'settings':
                          showStakeoutSettingsDialog();
                        case 'import':
                          Get.toNamed(Routes.STAKEOUT_IMPORT);
                        case 'haptics':
                          svc.hapticsEnabled.toggle();
                      }
                    },
                    itemBuilder: (_) => [
                      const PopupMenuItem(
                          value: 'list', child: Text('Pontlista / export')),
                      const PopupMenuItem(
                          value: 'settings',
                          child: Text('Kitűzési beállítások')),
                      const PopupMenuItem(
                          value: 'import', child: Text('Pontok importja')),
                      CheckedPopupMenuItem(
                          value: 'haptics',
                          checked: svc.hapticsEnabled.value,
                          child: const Text('Haptikus visszajelzés')),
                    ],
                  ),
                ],
              ),
              // ── Fázis-tartalom ───────────────────────────────────
              if (!svc.hasPosition.value)
                const Padding(
                  padding: EdgeInsets.all(10),
                  child: Text('Várakozás GNSS pozícióra…',
                      style: TextStyle(color: Colors.orange)),
                )
              else if (svc.nearPhase.value)
                _NearPhase(svc: svc)
              else
                _FarPhase(svc: svc),

              const SizedBox(height: 4),

              // ── Gombsor ──────────────────────────────────────────
              Row(
                children: [
                  IconButton(
                    icon: Icon(svc.nearPhase.value ? Icons.map : Icons.adjust),
                    visualDensity: VisualDensity.compact,
                    padding: EdgeInsets.zero,
                    constraints:
                        const BoxConstraints(minWidth: 36, minHeight: 36),
                    tooltip:
                        svc.nearPhase.value ? 'Térkép-nézet' : 'Céltábla-nézet',
                    onPressed: svc.togglePhase,
                  ),
                  OutlinedButton(
                    onPressed: svc.skipCurrent,
                    style: OutlinedButton.styleFrom(
                      visualDensity: VisualDensity.compact,
                      padding: const EdgeInsets.symmetric(horizontal: 10),
                      tapTargetSize: MaterialTapTargetSize.shrinkWrap,
                    ),
                    child: const Text('Kihagy'),
                  ),
                  const SizedBox(width: 6),
                  OutlinedButton.icon(
                    onPressed: () => _offsetDialog(svc),
                    style: OutlinedButton.styleFrom(
                      visualDensity: VisualDensity.compact,
                      padding: const EdgeInsets.symmetric(horizontal: 10),
                      tapTargetSize: MaterialTapTargetSize.shrinkWrap,
                    ),
                    icon: const Icon(Icons.alt_route, size: 18),
                    label: const Text('Eltolás'),
                  ),
                  const SizedBox(width: 6),
                  // Expanded: a Tárol tölti ki a maradék helyet —
                  // fix-szélesség-összeg helyett, így nincs overflow.
                  Expanded(
                    child: FilledButton.icon(
                      onPressed:
                          svc.isAveraging.value ? null : () => _store(svc),
                      style: FilledButton.styleFrom(
                        backgroundColor: within ? Colors.green : null,
                        visualDensity: VisualDensity.compact,
                        padding: const EdgeInsets.symmetric(horizontal: 10),
                      ),
                      icon: svc.isAveraging.value
                          ? const SizedBox(
                              width: 18,
                              height: 18,
                              child: CircularProgressIndicator(strokeWidth: 2))
                          : const Icon(Icons.push_pin, size: 18),
                      label: FittedBox(
                        fit: BoxFit.scaleDown,
                        child: Text(svc.isAveraging.value
                            ? 'Átlagolás ${svc.averagingElapsed.value}/'
                                '${svc.averagingSeconds.value} s'
                            : 'Tárol'),
                      ),
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      );
    });
  }

  // ═════════════════════════════════════════════════════════════════
  // Tárolás — figyelmeztetés, ha nem RTK fixed (de NEM tiltás)
  // ═════════════════════════════════════════════════════════════════

  Future<void> _store(StakeoutService svc) async {
    if (svc.target.value == null || !svc.hasPosition.value) return;

    final quality = GnssService.to.gpsQuality.value;
    if (quality != 4) {
      final proceed = await Get.dialog<bool>(AlertDialog(
        icon: const Icon(Icons.warning_amber, color: Colors.orange),
        title: const Text('Nincs RTK fixed'),
        content: Text(
          'A jelenlegi megoldás: ${_fixLabel(quality)}.\n'
          'A pont tárolható, de a pontosság csökkent lehet — a '
          'fix-minőség bekerül a jegyzőkönyvbe.',
        ),
        actions: [
          TextButton(
              onPressed: () => Get.back(result: false),
              child: const Text('Mégse')),
          FilledButton(
              onPressed: () => Get.back(result: true),
              child: const Text('Tárolás így is')),
        ],
      ));
      if (proceed != true) return;
    }

    final stored = await svc.storeCurrent();
    if (stored == null) return;

    Get.snackbar(
      '✓ ${stored.displayId} kitűzve',
      'inline ${_cm(stored.devInline)} · crossline ${_cm(stored.devCrossline)}'
          '${stored.devDz != null ? ' · dZ ${_cm(stored.devDz)}' : ''}'
          ' · ${_fixLabel(stored.fixQuality ?? 0)}',
      snackPosition: SnackPosition.BOTTOM,
      backgroundColor: const Color(0xFF2E7D32),
      colorText: const Color(0xFFFFFFFF),
      duration: const Duration(seconds: 3),
    );

    svc.advance();
  }

  Future<void> _offsetDialog(StakeoutService svc) async {
    final distCtrl = TextEditingController(text: '2');
    final toRight = true.obs;
    final both = false.obs;

    await Get.dialog(AlertDialog(
      title: const Text('Eltolt pont (transzverzális)'),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Text(
            'A vonalra merőlegesen, a tervponttól mért távolságra. '
            'Az eltolás iránya és nagysága bekerül a jegyzőkönyvbe.',
            style: TextStyle(fontSize: 12),
          ),
          const SizedBox(height: 12),
          Wrap(
            spacing: 8,
            children: [
              for (final d in ['0.5', '1', '2', '5'])
                ActionChip(
                    label: Text('$d m'), onPressed: () => distCtrl.text = d),
            ],
          ),
          const SizedBox(height: 8),
          TextField(
            controller: distCtrl,
            keyboardType: const TextInputType.numberWithOptions(decimal: true),
            decoration:
                const InputDecoration(labelText: 'Távolság (m)', isDense: true),
          ),
          const SizedBox(height: 8),
          Obx(() => SegmentedButton<bool>(
                segments: const [
                  ButtonSegment(
                      value: false,
                      label: Text('Balra'),
                      icon: Icon(Icons.west)),
                  ButtonSegment(
                      value: true,
                      label: Text('Jobbra'),
                      icon: Icon(Icons.east)),
                ],
                selected: {toRight.value},
                onSelectionChanged: (s) => toRight.value = s.first,
              )),
          Obx(() => CheckboxListTile(
                contentPadding: EdgeInsets.zero,
                dense: true,
                title: const Text('Pár létrehozása (bal ÉS jobb)'),
                subtitle: const Text('az akadály két oldalára',
                    style: TextStyle(fontSize: 11)),
                value: both.value,
                onChanged: (v) => both.value = v ?? false,
              ))
        ],
      ),
      actions: [
        TextButton(onPressed: Get.back, child: const Text('Mégse')),
        FilledButton(
          onPressed: () async {
            final d = double.tryParse(distCtrl.text.replaceAll(',', '.'));
            if (d == null || d <= 0) return;

            // Megrendelői offset-korlát ellenőrzése (beállításokból).
            if (svc.maxOffset.value > 0 && d > svc.maxOffset.value) {
              final ok = await Get.dialog<bool>(AlertDialog(
                icon: const Icon(Icons.warning_amber, color: Colors.orange),
                title: const Text('Offset-korlát túllépése'),
                content: Text('A megadott ${d.toStringAsFixed(1)} m nagyobb '
                    'a beállított max. ${svc.maxOffset.value.toStringAsFixed(1)} m '
                    'crossline eltolásnál.'),
                actions: [
                  TextButton(
                      onPressed: () => Get.back(result: false),
                      child: const Text('Mégse')),
                  FilledButton(
                      onPressed: () => Get.back(result: true),
                      child: const Text('Mégis')),
                ],
              ));
              if (ok != true) return;
            }

            Get.back();
            if (both.value) {
              // Előbb az ellenoldali, aztán a választott — így a
              // választott oldal lesz az aktív cél.
              await svc.createOffset(dist: d, toRight: !toRight.value);
              await svc.createOffset(dist: d, toRight: toRight.value);
              Get.snackbar('Eltolt pontpár létrehozva',
                  '±${d.toStringAsFixed(2)} m a vonalra merőlegesen.',
                  snackPosition: SnackPosition.BOTTOM);
            } else {
              final p = await svc.createOffset(dist: d, toRight: toRight.value);
              if (p != null) {
                Get.snackbar(
                    'Eltolt pont létrehozva',
                    '${p.displayId} · ${d.toStringAsFixed(2)} m '
                        '${toRight.value ? 'jobbra' : 'balra'} — ez az új cél.',
                    snackPosition: SnackPosition.BOTTOM);
              }
            }
          },
          child: const Text('Létrehozás'),
        ),
      ],
    ));
  }

  static String _cm(double? v) => v == null
      ? '—'
      : v.abs() < 1
          ? '${(v * 100).toStringAsFixed(0)} cm'
          : '${v.toStringAsFixed(2)} m';

  static String _fixLabel(int q) => switch (q) {
        4 => 'RTK FIXED',
        5 => 'RTK FLOAT',
        2 => 'DGPS',
        1 => 'GPS',
        0 => 'nincs fix',
        _ => 'fix: $q',
      };
}

// ═══════════════════════════════════════════════════════════════════
// Távoli fázis: nagy nyíl + távolság
// ═══════════════════════════════════════════════════════════════════

class _FarPhase extends StatelessWidget {
  final StakeoutService svc;
  const _FarPhase({required this.svc});

  static const _compass = ['É', 'ÉK', 'K', 'DK', 'D', 'DNy', 'Ny', 'ÉNy'];

  @override
  Widget build(BuildContext context) {
    return Obx(() {
      final heading = svc.travelHeading.value;
      final bearing = svc.bearingToTarget.value;
      final compass = _compass[((bearing + 22.5) % 360 ~/ 45)];

      return Padding(
        padding: const EdgeInsets.symmetric(vertical: 2),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // A nyíl a HALADÁSI IRÁNYHOZ képest forog; álló helyzetben
            // iránytű-ikon + égtáj-szöveg.
            SizedBox(
              width: 64,
              height: 64,
              child: heading != null
                  ? Transform.rotate(
                      angle: (bearing - heading) * math.pi / 180,
                      child: const Icon(Icons.navigation,
                          size: 58, color: Colors.blue),
                    )
                  : const Icon(Icons.explore, size: 52, color: Colors.blueGrey),
            ),
            const SizedBox(width: 16),
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  _fmtDist(svc.distance.value),
                  style: const TextStyle(
                    fontSize: 30,
                    fontWeight: FontWeight.w800,
                    fontFeatures: [FontFeature.tabularFigures()],
                  ),
                ),
                Text(
                  heading != null
                      ? '$compass felé (${bearing.toStringAsFixed(0)}°)'
                      : 'Indulj el — a nyíl követi a haladásod · $compass',
                  style: TextStyle(fontSize: 12, color: Colors.grey.shade600),
                ),
                if (svc.devDz.value != null)
                  Text(
                    'dZ: ${svc.devDz.value! >= 0 ? 'fel' : 'le'} '
                    '${_fmtDist(svc.devDz.value!.abs())}',
                    style: TextStyle(fontSize: 12, color: Colors.grey.shade600),
                  ),
              ],
            ),
          ],
        ),
      );
    });
  }

  static String _fmtDist(double d) => d >= 1000
      ? '${(d / 1000).toStringAsFixed(2)} km'
      : d >= 10
          ? '${d.toStringAsFixed(1)} m'
          : '${d.toStringAsFixed(2)} m';
}

// ═══════════════════════════════════════════════════════════════════
// Közeli fázis: céltábla + cm-es eltérések
// ═══════════════════════════════════════════════════════════════════

class _NearPhase extends StatelessWidget {
  final StakeoutService svc;
  const _NearPhase({required this.svc});

  @override
  Widget build(BuildContext context) {
    return Obx(() {
      final fwd = svc.devForward.value;
      final right = svc.devRight.value;
      final dz = svc.devDz.value;
      final within = svc.withinTolerance.value;
      final ne = svc.deviationMode.value == DeviationMode.northEast;

      final (fwdLabel, rightLabel) = switch (svc.deviationMode.value) {
        DeviationMode.line => ('Inline', 'Crossline'),
        DeviationMode.travel => ('Előre/hátra', 'Jobbra/balra'),
        DeviationMode.northEast => ('Észak', 'Kelet'),
      };

      return Column(
        children: [
          SegmentedButton<DeviationMode>(
            segments: [
              for (final m in DeviationMode.values)
                ButtonSegment(
                    value: m,
                    label: Text(m.label, style: const TextStyle(fontSize: 10))),
            ],
            selected: {svc.deviationMode.value},
            onSelectionChanged: (s) => svc.deviationMode.value = s.first,
            showSelectedIcon: false,
            style: const ButtonStyle(
                visualDensity: VisualDensity.compact,
                tapTargetSize: MaterialTapTargetSize.shrinkWrap),
          ),
          const SizedBox(height: 6),
          Row(
            children: [
              SizedBox(
                width: 140,
                height: 140,
                child: CustomPaint(
                  painter: _BullseyePainter(
                    devForward: fwd,
                    devRight: right,
                    tolerance: svc.toleranceXY.value,
                    within: within,
                  ),
                ),
              ),
              const SizedBox(width: 10),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    _DevRow(
                        label: fwdLabel,
                        value: fwd,
                        posText: ne ? 'É' : 'előre',
                        negText: ne ? 'D' : 'hátra'),
                    _DevRow(
                        label: rightLabel,
                        value: right,
                        posText: ne ? 'K' : 'jobbra',
                        negText: ne ? 'Ny' : 'balra'),
                    if (dz != null)
                      _DevRow(
                          label: 'Magasság',
                          value: dz,
                          posText: 'fel',
                          negText: 'le'),
                    const SizedBox(height: 4),
                    Text(
                      within
                          ? '✓ Tűrésen belül '
                              '(${(svc.toleranceXY.value * 100).toStringAsFixed(0)} cm)'
                          : 'Távolság: '
                              '${(svc.distance.value * 100).toStringAsFixed(0)} cm',
                      style: TextStyle(
                        fontSize: 13,
                        fontWeight: FontWeight.w700,
                        color: within ? Colors.green : null,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ],
      );
    });
  }
}

class _DevRow extends StatelessWidget {
  final String label;
  final double value;
  final String posText;
  final String negText;
  const _DevRow(
      {required this.label,
      required this.value,
      required this.posText,
      required this.negText});

  //@Preview(name: 'Example')
  @override
  Widget build(BuildContext context) {
    final cm = value.abs() * 100;
    final txt = cm < 100
        ? '${cm.toStringAsFixed(0)} cm'
        : '${value.abs().toStringAsFixed(2)} m';
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 2),
      child: Row(
        children: [
          SizedBox(
            width: 78,
            child: Text(label,
                style: TextStyle(fontSize: 11, color: Colors.grey.shade600)),
          ),
          Text(
            '${value >= 0 ? posText : negText} $txt',
            style: const TextStyle(
              fontSize: 16,
              fontWeight: FontWeight.w700,
              fontFeatures: [FontFeature.tabularFigures()],
            ),
          ),
        ],
      ),
    );
  }
}

/// Céltábla: középen a CÉL, a kék pötty a MI pozíciónk a célhoz képest.
/// A "felfelé" tengely az aktuális eltérés-mód "előre" iránya.
class _BullseyePainter extends CustomPainter {
  final double devForward;
  final double devRight;
  final double tolerance;
  final bool within;

  _BullseyePainter({
    required this.devForward,
    required this.devRight,
    required this.tolerance,
    required this.within,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final c = Offset(size.width / 2, size.height / 2);
    final maxR = size.width / 2 - 4;
    const viewRadiusM = 1.2;
    final scale = maxR / viewRadiusM;

    final ring = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 1
      ..color = Colors.grey.shade400;

    for (final r in [1.0, 0.5]) {
      canvas.drawCircle(c, r * scale, ring);
    }
    canvas.drawCircle(
        c,
        tolerance * scale,
        Paint()
          ..style = PaintingStyle.stroke
          ..strokeWidth = 2
          ..color = within ? Colors.green : Colors.grey.shade600);

    canvas.drawLine(Offset(c.dx - maxR, c.dy), Offset(c.dx + maxR, c.dy), ring);
    canvas.drawLine(Offset(c.dx, c.dy - maxR), Offset(c.dx, c.dy + maxR), ring);

    canvas.drawCircle(
        c, 4, Paint()..color = within ? Colors.green : Colors.red);

    // A MI pozíciónk a célhoz képest: offset = −(eltérés) az
    // (előre, jobbra) bázisban; képernyő-y felfelé = előre.
    var px = -devRight * scale;
    var py = devForward * scale;
    final d = math.sqrt(px * px + py * py);
    if (d > maxR) {
      px = px / d * maxR;
      py = py / d * maxR;
    }
    final me = c + Offset(px, py);
    canvas.drawCircle(me, 7, Paint()..color = Colors.blue);
    canvas.drawCircle(
        me,
        7,
        Paint()
          ..style = PaintingStyle.stroke
          ..strokeWidth = 2
          ..color = Colors.white);
  }

  @override
  bool shouldRepaint(_BullseyePainter old) =>
      old.devForward != devForward ||
      old.devRight != devRight ||
      old.within != within ||
      old.tolerance != tolerance;
}
