import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:get/get.dart';
import 'package:latlong2/latlong.dart';
import 'package:terepi_seged/services/coord_converter_service.dart';
import 'package:terepi_seged/services/gnss/gnss_service.dart';
import 'package:terepi_seged/services/stakeout_service.dart';

import '../../../../models/stakeout_point.dart';

/// Kitűzési térképréteg — a SharedMapWidget children listájába illesztendő.
///
/// Csak akkor rajzol, ha a StakeoutService aktív (mode == stakeout), így
/// feltétel nélkül bent maradhat a rétegek között. Tartalma: vonalanként
/// polyline (station-sorrendben), státusz-színezett markerek (koppintás =
/// célváltás), vezetővonal a pozíciótól a célig.
class StakeoutMapLayers extends StatelessWidget {
  const StakeoutMapLayers({super.key});

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

    return Obx(() {
      final svc = StakeoutService.to;
      if (!svc.active.value || svc.points.isEmpty) {
        return const SizedBox.shrink();
      }

      final points = svc.points;
      final target = svc.target.value;
      final g = GnssService.to;
      final hasPos = svc.hasPosition.value && g.latitude.value != 0;

      // Vonalanként polyline (station-sorrendben, eltolt pontok nélkül).
      final linePolys = <Polyline>[];
      for (final line in svc.lines) {
        final lp = points.where((p) => p.lineId == line && !p.isOffset).toList()
          ..sort((a, b) => a.station.compareTo(b.station));
        if (lp.length < 2) continue;
        linePolys.add(Polyline(
          points: [for (final p in lp) LatLng(p.planLat, p.planLon)],
          color: Colors.blueGrey.withOpacity(0.5),
          strokeWidth: 2,
        ));
      }
      // Transzverzális az aktuális célnál: a vonalra merőleges segédvonal
      // ±30 m hosszan, 10 m-enkénti méter-címkékkel — terepi akadálynál
      // e mentén látszik, hova tolható el a pont.
      final transversal = <LatLng>[];
      final transversalTicks = <Marker>[];
      if (target != null && Get.isRegistered<CoordConverterService>()) {
        final lb = svc.lineBearingAt(target);
        if (lb != null) {
          final perpRad = (lb + 90) * math.pi / 180;
          LatLng at(double d) {
            final y = target.planEovY + d * math.sin(perpRad);
            final x = target.planEovX + d * math.cos(perpRad);
            final w = CoordConverterService.to.eovToWgsPoint(y, x);
            return LatLng(w.y, w.x);
          }

          transversal
            ..add(at(-30))
            ..add(at(30));

          for (final d in const [-30.0, -20.0, -10.0, 10.0, 20.0, 30.0]) {
            transversalTicks.add(Marker(
              point: at(d),
              width: 24,
              height: 16,
              child: Container(
                alignment: Alignment.center,
                decoration: BoxDecoration(
                  color: Colors.orange.withOpacity(0.85),
                  borderRadius: BorderRadius.circular(4),
                ),
                child: Text(
                  d.abs().toStringAsFixed(0),
                  style: const TextStyle(
                      fontSize: 9,
                      color: Colors.white,
                      fontWeight: FontWeight.w700),
                ),
              ),
            ));
          }
        }
      }
      // 300 pont fölött a címkék csak a célon (teljesítmény).
      final showLabels = points.length <= 300;

      return Stack(children: [
        PolylineLayer(polylines: [
          if (transversal.isNotEmpty)
            Polyline(
                points: transversal,
                color: Colors.orange.withValues(alpha: 0.8),
                strokeWidth: 2),
          ...linePolys,
          if (hasPos && target != null)
            Polyline(
              points: [
                LatLng(g.latitude.value, g.longitude.value),
                LatLng(target.planLat, target.planLon),
              ],
              color: Colors.blue,
              strokeWidth: 3,
            ),
        ]),
        MarkerLayer(markers: [
          ...transversalTicks,
          for (final p in points)
            Marker(
              point: LatLng(p.planLat, p.planLon),
              width: 56,
              height: 40,
              child: GestureDetector(
                onTap: () => svc.setTarget(p),
                child: _StakeoutMarker(
                  point: p,
                  isTarget: p.uuid == target?.uuid,
                  showLabel: showLabels || p.uuid == target?.uuid,
                ),
              ),
            ),
        ]),
      ]);
    });
  }
}

class _StakeoutMarker extends StatelessWidget {
  final StakeoutPoint point;
  final bool isTarget;
  final bool showLabel;
  const _StakeoutMarker(
      {required this.point, required this.isTarget, required this.showLabel});

  @override
  Widget build(BuildContext context) {
    final (color, icon) = switch (point.status) {
      StakeoutStatus.staked => (Colors.green, Icons.check_circle),
      StakeoutStatus.skipped => (Colors.grey, Icons.block),
      StakeoutStatus.pending => point.isOffset
          ? (Colors.purple, Icons.change_history)
          : (Colors.deepOrange, Icons.change_history),
    };

    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Icon(icon,
            size: isTarget ? 26 : 16, color: isTarget ? Colors.red : color),
        if (showLabel)
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 3),
            decoration: BoxDecoration(
              color: Colors.white.withOpacity(0.85),
              borderRadius: BorderRadius.circular(4),
            ),
            child: Text(
              point.name,
              style: TextStyle(
                fontSize: 9,
                fontWeight: isTarget ? FontWeight.w700 : FontWeight.w400,
                color: isTarget ? Colors.red : Colors.black87,
              ),
            ),
          ),
      ],
    );
  }
}
