import 'package:flutter/material.dart';
import 'package:flutter_map_polygon_editor/polygon_editor/polygon_editor.dart';
import 'package:flutter_map_polywidget/flutter_map_polywidget.dart';
import 'package:get/get.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:terepi_seged/enums/map_edit_tool.dart';
import 'package:terepi_seged/enums/map_measure_type.dart';
import 'package:terepi_seged/enums/map_survey_mode.dart';
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
import 'package:terepi_seged/pages/map_survey/presentations/views/settings_dialog.dart';
import 'package:terepi_seged/pages/map_survey/presentations/widgets/stakeout_map_layer.dart';
import 'package:terepi_seged/pages/map_survey/presentations/widgets/stakeout_panel.dart';
import 'package:terepi_seged/pages/tracking/presentation/controllers/tracking_controller.dart';
import 'package:terepi_seged/services/gnss/gnss_device_service.dart';
import 'package:terepi_seged/services/gnss/gnss_service.dart';
import 'package:terepi_seged/utils/rive_utils.dart';
import 'package:terepi_seged/widgets/coordinate_panel.dart';
import 'package:terepi_seged/widgets/map/distance_or_area_measure_layer.dart';
import 'package:terepi_seged/widgets/map/imported_layer_overlay.dart';
import 'package:terepi_seged/widgets/map/measure_bottom_panel.dart';
import 'package:terepi_seged/widgets/map/note_item_label_layer.dart';
import 'package:terepi_seged/widgets/map_bottom_panel.dart';
import 'package:terepi_seged/widgets/map_edit_tools/map_edit_drawing_toolbar.dart';
import 'package:terepi_seged/widgets/map_edit_tools/map_edit_toolbar.dart';
import 'package:terepi_seged/widgets/map_info_card_column.dart';
import 'package:terepi_seged/widgets/save_point_fab.dart';
import 'package:terepi_seged/widgets/shared_map_widgets.dart';

import 'map_add_point_dialog.dart';

class MapSurveyView extends GetView<MapSurveyController> {
  const MapSurveyView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(children: [
      SharedMapWidget(
        controls: const MapControls(),
        mapController: controller.mapController,
        isFollowing: controller.isMapMoveToCenter,
        initialCenter: LatLng(
          // ← nem fix érték
          controller.currentLatitude.value != 0.0
              ? controller.currentLatitude.value
              : 47.5,
          controller.currentLongitude.value != 0.0
              ? controller.currentLongitude.value
              : 19.0,
        ),
        initialZoom: controller.currentZoom.value,
        currentZoom: controller.currentZoom,
        onZoomIn: controller.mapZoomIn,
        onZoomOut: controller.mapZoomOut,
        onPositionChanged: controller.onMapPositionChanged,
        onCenterOnGps: controller.setIsMapMoveToCenter,
        onLongPress: (tapPosition, point) {
          if (controller.activeEditTool.value == MapEditTool.point) {
            if (controller.isGeometryEditing) {
              controller.saveEditedPoint(point: point);
            } else {
              //controller.saveEditedPoint(point: point);
              controller.showSavePointDialog(point: point);
            }
            return;
          }
          if (controller.activeEditTool.value == MapEditTool.line ||
              controller.activeEditTool.value == MapEditTool.polygon) {
            controller.polygonEditorController.addPoint(point);
          }
        },
        onTap: (tapPosition, point) {
          if (controller.isDistanceOrAreaMeasuring) {
            controller.addDistanceOrAreaMeasuredPoint(point);
            return;
          }
          if (controller.mode.value != MapSurveyMode.fieldWalk) return;
          if (controller.isMapEditing) return;
          final polygonHit = controller.polygonHitNotifier.value;
          if (polygonHit != null && polygonHit.hitValues.isNotEmpty) {
            final id = polygonHit.hitValues.first;
            controller.selectedNoteItem(id);
            return;
          }
          final polylineHit = controller.polylineHitNotifier.value;
          if (polylineHit != null && polylineHit.hitValues.isNotEmpty) {
            final id = polylineHit.hitValues.first;
            controller.selectedNoteItem(id);
            return;
          }
          controller.clearNoteItemSelection();
        },
        layers: [
          const ImportedLayerOverlay(),
          // Track polyline
          Obx(() {
            final inTrackMode = controller.mode.value == MapSurveyMode.track ||
                controller.mode.value == MapSurveyMode.fieldWalk;
            if (!inTrackMode) return const SizedBox.shrink();
            final ids = TrackingController.to.overlayTrackIds;
            if (ids.isEmpty) return const SizedBox.shrink();

            final polylines = ids
                .map((id) {
                  final pts = TrackingController.to.getCoordsFor(id);
                  if (pts.isEmpty) return null;
                  return Polyline(
                    points: pts,
                    color: Colors.blue.withOpacity(0.75),
                    strokeWidth: 2.5,
                    borderColor: Colors.white.withOpacity(0.4),
                    borderStrokeWidth: 1.0,
                  );
                })
                .whereType<Polyline>()
                .toList();

            if (polylines.isEmpty) return const SizedBox.shrink();
            return PolylineLayer(polylines: polylines);
          }),
          Obx(() {
            final isTracking = TrackingController.to.isRecording.value;
            final inTrackMode = controller.mode.value == MapSurveyMode.track;
            if (!isTracking && !inTrackMode) {
              return const SizedBox.shrink();
            } else {
              return _buildTrackLayer1();
            }
          }),
          Obx(() {
            if (controller.mode.value != MapSurveyMode.measure) {
              return SizedBox.shrink();
            }
            return MarkerLayer(markers: controller.pointNotesMarker.toList());
          }),
          Obx(() {
            // Pontok - terepi bejárás
            if (controller.mode.value != MapSurveyMode.fieldWalk) {
              return const SizedBox.shrink();
            }
            if (!controller.showPoints.value) return const SizedBox.shrink();

            return MarkerLayer(markers: [...controller.pointNotes]);
          }),
          Obx(() {
            // Vonalak - terepbejárás
            if (controller.mode.value != MapSurveyMode.fieldWalk) {
              return const SizedBox.shrink();
            }
            if (!controller.showLines.value) return const SizedBox.shrink();

            return PolylineLayer(
                hitNotifier: controller.polylineHitNotifier,
                polylines: [...controller.polylineNotes]);
          }),
          Obx(() {
            // Poligonok - terepbejárás
            if (controller.mode.value != MapSurveyMode.fieldWalk) {
              return const SizedBox.shrink();
            }
            if (!controller.showPolygons.value) return const SizedBox.shrink();

            return PolygonLayer(
                hitNotifier: controller.polygonHitNotifier,
                polygons: [...controller.polygonNotes],
                useAltRendering: true);
          }),
          Obx(() {
            if (controller.mode.value != MapSurveyMode.fieldWalk) {
              return const SizedBox.shrink();
            }
            final selectedId = controller.selectedNoteItemId.value;
            if (selectedId == null) return const SizedBox.shrink();

            // Polygon kiemelés
            final selectedPolygon = controller.polygonNotes
                .where((p) => p.hitValue == selectedId)
                .firstOrNull;
            if (selectedPolygon != null) {
              return PolygonLayer(polygons: [
                Polygon(
                  points: selectedPolygon.points,
                  color: Colors.transparent,
                  borderColor: Colors.white,
                  borderStrokeWidth: selectedPolygon.borderStrokeWidth + 3,
                ),
              ]);
            }

            // Polyline kiemelés
            final selectedPolyline = controller.polylineNotes
                .where((p) => p.hitValue == selectedId)
                .firstOrNull;
            if (selectedPolyline != null) {
              return PolylineLayer(polylines: [
                Polyline(
                  points: selectedPolyline.points,
                  color: Colors.white.withOpacity(0.6),
                  strokeWidth: selectedPolyline.strokeWidth + 4,
                ),
              ]);
            }

            return const SizedBox.shrink();
          }),
          Obx(() {
            if (controller.mode.value != MapSurveyMode.fieldWalk) {
              return const SizedBox.shrink();
            }
            return PolygonEditor(
                controller: controller.polygonEditorController,
                throttleDuration: Duration.zero);
          }),
          NoteItemLabelLayer(
            controller: controller,
          ),
          Obx(() {
            final tracks = controller.teamTrackPoints;
            if (tracks.isEmpty) return const SizedBox.shrink();
            return PolylineLayer(
              polylines: tracks.entries.map((e) {
                final colors = [
                  Colors.blue,
                  Colors.purple,
                  Colors.teal,
                  Colors.indigo,
                  Colors.cyan,
                  Colors.deepPurple
                ];
                final color = colors[e.key.hashCode.abs() % colors.length];
                return Polyline(
                    points: e.value,
                    color: color.withValues(alpha: 0.7),
                    strokeWidth: 2.5);
              }).toList(),
            );
          }),
          Obx(() {
            final markers =
                List<Marker>.from(controller.teamTrackMarkers.values);
            if (markers.isEmpty) return const SizedBox.shrink();
            return MarkerLayer(markers: markers);
          }),
          DistanceOrAreaMeasureLayer(controller: controller),
          const StakeoutMapLayers(),
          Obx(() {
            final isGpsActive = GnssService.to.activeConnectionType.value !=
                GnssConnectionType.none;
            if (isGpsActive && controller.mode.value != MapSurveyMode.track) {
              return MarkerLayer(
                  markers: controller.currentLocationMarker.toList());
            }
            return const SizedBox.shrink();
          }),
        ],
      ),
      Positioned(
        top: 12,
        left: 12,
        child: MapInfoCardColumn(controller: controller),
      ),

      // Positioned(
      //   top: 390,
      //   right: 60,
      //   left: 8,
      //   child: CoordinatePanel(
      //     eovY: controller.eovY,
      //     eovX: controller.eovX,
      //     horError: controller.gpsLatitudeError,
      //     vertError: controller.gpsAltitudeError,
      //     altitudeMsl: controller.gpsAltitude,
      //     geoidSeparation: controller.gpsGeoidSeparation,
      //     ntripConnected: controller.ntripIsConnected,
      //     ntripBytes: controller.ntripReceivedData,
      //     ntripPackets: controller.ntripDataPacketNumbers,
      //     ggaPackets: controller.ggaSenDataPacketNumber,
      //   ),
      // ),
      Obx(() {
        if (controller.mode.value != MapSurveyMode.fieldWalk) {
          return const SizedBox.shrink();
        }
        if (controller.activeEditTool.value == MapEditTool.none) {
          return Positioned(
              left: 0,
              right: 0,
              bottom: 0,
              child: MapEditCompactToolbar(controller: controller));
        }
        return Positioned(
            left: 0,
            right: 0,
            bottom: 0,
            child: MapEditDrawingToolbar(controller: controller));
      }),
      Obx(() {
        if (controller.mode.value != MapSurveyMode.measure) {
          return const SizedBox.shrink();
        }
        return Positioned(
            left: 0,
            right: 0,
            bottom: 0,
            child: MeasureBottomPanel(ctrl: controller));
      }),
      Obx(() {
        if (controller.mode.value != MapSurveyMode.fieldWalk)
          return SizedBox.shrink();
        return Positioned(
            right: 10,
            bottom: 300,
            child: Column(mainAxisSize: MainAxisSize.min, children: [
              // Távolság mérés
              _MeasureButton(
                icon: Icons.straighten,
                tooltip: 'Távolságmérés',
                active:
                    controller.mapMeasureType.value == MapMeasureType.distance,
                onTap: controller.toggleMeasureDistance,
              ),
              const SizedBox(height: 4),
              // Területmérés
              _MeasureButton(
                icon: Icons.pentagon_outlined,
                tooltip: 'Területmérés',
                active: controller.mapMeasureType.value == MapMeasureType.area,
                onTap: controller.toggleMeasureArea,
              ),
              // Visszavonás (ha van pont)
              if (controller.distanceOrAreaMeasurePoints.isNotEmpty) ...[
                const SizedBox(height: 4),
                _MeasureButton(
                  icon: Icons.undo,
                  tooltip: 'Utolsó pont törlése',
                  active: false,
                  onTap: controller.removeLastDistanceOrAreaMeasuredPoint,
                ),
              ]
            ]));
      }),
      Obx(() {
        if (controller.mode.value != MapSurveyMode.stakeout) {
          return SizedBox.shrink();
        }
        return const Positioned(
            left: 0, right: 0, bottom: 0, child: StakeoutPanel());
      }),
      // Positioned(top: 8, left: 0, right: 0, child: _ModeSelector()),
      // Positioned(
      //   bottom: 80,
      //   left: 8,
      //   right: 8,
      //   child: Obx(
      //     () => controller.mode.value == MapSurveyMode.stakeout
      //         ? _StakeoutPanel() // ΔY, ΔX, távolság, irányszög
      //         : const SizedBox.shrink(),
      //   ),
      // ),
      // Positioned(
      //   bottom: 16,
      //   right: 16,
      //   child: SavePointFab(controller: controller),
      // ),
      // Positioned(
      //     bottom: 0,
      //     left: 0,
      //     right: 0,
      //     child: MapBottomPanel(controller: controller))
    ]);
  }

  Widget _buildTrackLayer() {
    // FutureBuilder helyett a controller livePoints-ból
    return Obx(() {
      final ctrl = TrackingController.to;
      if (ctrl.livePoints.isEmpty) return const SizedBox.shrink();
      return PolylineLayer(polylines: [
        Polyline(
          points: ctrl.livePoints
              .map((p) => LatLng(p.latitude, p.longitude))
              .toList(),
          color: Colors.red.withOpacity(0.85),
          strokeWidth: 3.0,
        ),
      ]);
    });
  }

  Widget _buildTrackLayer1() {
    return Obx(() {
      final ctrl = TrackingController.to;
      final points = ctrl.livePoints.toList();
      if (points.isEmpty) return const SizedBox.shrink();

      return Stack(children: [
        // 1. Track vonal
        PolylineLayer(polylines: [
          Polyline(
            points: points,
            color: Colors.red.withOpacity(0.85),
            strokeWidth: 3.0,
          ),
        ]),
        // 2. Markerek a vonal felett
        MarkerLayer(markers: [
          // Kezdőpont — zöld
          Marker(
            point: points.first,
            child: const Icon(Icons.flag, color: Colors.green, size: 28),
          ),
          // Utolsó pont — piros (ha van legalább 2 pont)
          if (points.length > 1)
            Marker(
              point: points.last,
              child: _PulsingDot(
                color: TrackingController.to.isPaused.value
                    ? Colors.orange
                    : Colors.blue,
              ),
            ),
        ]),
      ]);
    });
  }
}

class _ModeSelector extends GetView<MapSurveyController> {
  const _ModeSelector();

  @override
  Widget build(BuildContext context) {
    return Obx(() => SegmentedButton<MapSurveyMode>(
          segments: const [
            ButtonSegment(
              value: MapSurveyMode.measure,
              icon: Icon(Icons.gps_fixed, size: 16),
              label: Text('Bemérés'),
            ),
            ButtonSegment(
              value: MapSurveyMode.stakeout,
              icon: Icon(Icons.my_location, size: 16),
              label: Text('Kitűzés'),
            ),
          ],
          selected: {controller.mode.value},
          onSelectionChanged: (s) => controller.switchMode(s.first),
        ));
  }
}

class _PulsingDot extends StatefulWidget {
  final Color color;
  const _PulsingDot({required this.color});

  @override
  State<_PulsingDot> createState() => _PulsingDotState();
}

class _PulsingDotState extends State<_PulsingDot>
    with SingleTickerProviderStateMixin {
  late AnimationController _anim;
  late Animation<double> _scale;

  @override
  void initState() {
    super.initState();
    _anim = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 1000))
      ..repeat(reverse: true);
    _scale = Tween(begin: 0.8, end: 1.1)
        .animate(CurvedAnimation(parent: _anim, curve: Curves.easeInOut));
  }

  @override
  void dispose() {
    _anim.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return ScaleTransition(
      scale: _scale,
      child: Container(
        width: 8,
        height: 8,
        decoration: BoxDecoration(
          color: widget.color,
          shape: BoxShape.circle,
          border: Border.all(color: Colors.white, width: 2),
          boxShadow: [
            BoxShadow(
                color: widget.color.withOpacity(0.5),
                blurRadius: 4,
                spreadRadius: 2)
          ],
        ),
      ),
    );
  }
}

class _StakeoutPanel extends GetView<MapSurveyController> {
  const _StakeoutPanel();

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(12),
        child: Obx(() {
          final onTarget = controller.isOnTarget;
          final dy = controller.deltaY;
          final dx = controller.deltaX;
          final dist = controller.distanceToTarget;
          return Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              // Célpont neve
              Row(children: [
                const Icon(Icons.flag, size: 16, color: Colors.orange),
                const SizedBox(width: 6),
                Text(controller.targetName.value,
                    style: const TextStyle(fontWeight: FontWeight.w600)),
                const Spacer(),
                TextButton(
                  onPressed: _showTargetPicker,
                  child: const Text('Változtat'),
                ),
              ]),

              const Divider(height: 16),

              // Eltérések
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  _DeltaCell(
                    label: 'ΔY',
                    value: dy,
                    unit: 'm',
                  ),
                  _DeltaCell(
                    label: 'ΔX',
                    value: dx,
                    unit: 'm',
                  ),
                  _DeltaCell(
                    label: 'Táv',
                    value: dist,
                    unit: 'm',
                    alwaysPositive: true,
                  ),
                ],
              ),

              const SizedBox(height: 8),

              // Státusz
              Container(
                width: double.infinity,
                padding: const EdgeInsets.symmetric(vertical: 6),
                decoration: BoxDecoration(
                  color: onTarget
                      ? Colors.green.withOpacity(0.12)
                      : Colors.orange.withOpacity(0.12),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Text(
                  onTarget
                      ? '✓ Célponton — pont rögzíthető'
                      : '${controller.distanceToTarget.toStringAsFixed(3)} m a céltól',
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    fontWeight: FontWeight.w500,
                    color: onTarget ? Colors.green : Colors.orange,
                    fontSize: 13,
                  ),
                ),
              ),
            ],
          );
        }),
      ),
    );
  }

  void _showTargetPicker() {
    // Lista a korábban bemért vagy tervezett pontokból
    //Get.bottomSheet(const _TargetPickerSheet());
  }
}

class _DeltaCell extends StatelessWidget {
  final String label;
  final double value;
  final String unit;
  final bool alwaysPositive;

  const _DeltaCell({
    required this.label,
    required this.value,
    required this.unit,
    this.alwaysPositive = false,
  });

  @override
  Widget build(BuildContext context) {
    final display = alwaysPositive ? value.abs() : value;
    final prefix = (!alwaysPositive && value > 0) ? '+' : '';
    final color = value.abs() < 0.05
        ? Colors.green
        : value.abs() < 0.5
            ? Colors.orange
            : Colors.red;

    return Column(
      children: [
        Text(label, style: const TextStyle(fontSize: 11, color: Colors.grey)),
        const SizedBox(height: 2),
        Text(
          '$prefix${display.toStringAsFixed(3)} $unit',
          style: TextStyle(
            fontSize: 15,
            fontWeight: FontWeight.w600,
            color: color,
          ),
        ),
      ],
    );
  }
}

class _MeasureButton extends StatelessWidget {
  final IconData icon;
  final String tooltip;
  final bool active;
  final VoidCallback onTap;
  const _MeasureButton({
    required this.icon,
    required this.tooltip,
    required this.active,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    return Tooltip(
      message: tooltip,
      child: Material(
        color: active
            ? Colors.deepOrange
            : isDark
                ? Colors.grey.shade800.withOpacity(0.9)
                : Colors.white.withOpacity(0.9),
        borderRadius: BorderRadius.circular(8),
        elevation: 3,
        shadowColor: Colors.black38,
        child: InkWell(
          borderRadius: BorderRadius.circular(8),
          onTap: onTap,
          child: SizedBox(
            width: 42,
            height: 42,
            child: Center(
              child: Icon(icon,
                  size: 20,
                  color: active
                      ? Colors.white
                      : isDark
                          ? Colors.white70
                          : Colors.black87),
            ),
          ),
        ),
      ),
    );
  }
}
