import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:geolocator/geolocator.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart' show LatLng;

import '../../models/app_settings.dart';
import '../../providers/location_provider.dart';
import '../../providers/workforce_provider.dart';
import '../../providers/profile_provider.dart';
import '../../widgets/responsive_body.dart';

class GeofenceTestScreen extends ConsumerStatefulWidget {
  const GeofenceTestScreen({super.key});

  @override
  ConsumerState<GeofenceTestScreen> createState() => _GeofenceTestScreenState();
}

class _GeofenceTestScreenState extends ConsumerState<GeofenceTestScreen> {
  final _mapController = MapController();
  bool _followMe = true;
  bool _liveTracking = false; // enable periodic updates from the device stream

  bool _isInside(Position pos, GeofenceConfig? cfg) {
    if (cfg == null) return false;
    if (cfg.hasPolygon) {
      return cfg.containsPolygon(pos.latitude, pos.longitude);
    }
    if (cfg.hasCircle) {
      final dist = Geolocator.distanceBetween(
        pos.latitude,
        pos.longitude,
        cfg.lat!,
        cfg.lng!,
      );
      return dist <= (cfg.radiusMeters ?? 0);
    }
    return false;
  }

  void _centerOn(LatLng latLng) {
    // flutter_map v8+ MapController does not expose current zoom getter — use a
    // sensible default zoom when centering.
    _mapController.move(latLng, 16.0);
  }

  @override
  Widget build(BuildContext context) {
    final isAdmin = ref.watch(isAdminProvider);
    final geofenceAsync = ref.watch(geofenceProvider);
    final positionAsync = ref.watch(currentPositionProvider);
    // Only watch the live stream when the user enables "Live" so tests that
    // don't enable live tracking won't need to provide a stream override.
    final AsyncValue<Position>? streamAsync = _liveTracking
        ? ref.watch(currentPositionStreamProvider)
        : null;

    // If live-tracking is active and the stream yields a position while the
    // UI is following the device, recenter the map.
    if (_liveTracking && streamAsync != null) {
      streamAsync.whenData((p) {
        if (_followMe) {
          WidgetsBinding.instance.addPostFrameCallback((_) {
            _centerOn(LatLng(p.latitude, p.longitude));
          });
        }
      });
    }

    return ResponsiveBody(
      child: !isAdmin
          ? const Center(child: Text('Admin access required.'))
          : Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                const SizedBox(height: 12),
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16.0),
                  child: Row(
                    children: [
                      Expanded(
                        child: Card(
                          child: Padding(
                            padding: const EdgeInsets.all(12.0),
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text('Geofence status'),
                                const SizedBox(height: 8),
                                // Show either the one-shot position or the live-stream
                                // value depending on the user's toggle.
                                _liveTracking
                                    ? (streamAsync == null
                                          ? const Text('Live tracking disabled')
                                          : streamAsync.when(
                                              data: (pos) {
                                                final inside = _isInside(
                                                  pos,
                                                  geofenceAsync.valueOrNull,
                                                );
                                                return Column(
                                                  crossAxisAlignment:
                                                      CrossAxisAlignment.start,
                                                  children: [
                                                    Row(
                                                      children: [
                                                        Icon(
                                                          inside
                                                              ? Icons
                                                                    .check_circle
                                                              : Icons.cancel,
                                                          color: inside
                                                              ? Colors.green
                                                              : Colors.red,
                                                        ),
                                                        const SizedBox(
                                                          width: 8,
                                                        ),
                                                        Text(
                                                          inside
                                                              ? 'Inside geofence'
                                                              : 'Outside geofence',
                                                        ),
                                                        const SizedBox(
                                                          width: 12,
                                                        ),
                                                        Flexible(
                                                          child: Text(
                                                            'Lat: ${pos.latitude.toStringAsFixed(6)}, Lng: ${pos.longitude.toStringAsFixed(6)}',
                                                            overflow:
                                                                TextOverflow
                                                                    .ellipsis,
                                                          ),
                                                        ),
                                                      ],
                                                    ),
                                                    const SizedBox(height: 8),
                                                    _buildGeofenceSummary(
                                                      geofenceAsync.valueOrNull,
                                                    ),
                                                  ],
                                                );
                                              },
                                              loading: () => const Text(
                                                'Waiting for live position...',
                                              ),
                                              error: (err, st) => Text(
                                                'Live location error: $err',
                                              ),
                                            ))
                                    : positionAsync.when(
                                        data: (pos) {
                                          final inside = _isInside(
                                            pos,
                                            geofenceAsync.valueOrNull,
                                          );
                                          return Column(
                                            crossAxisAlignment:
                                                CrossAxisAlignment.start,
                                            children: [
                                              Row(
                                                children: [
                                                  Icon(
                                                    inside
                                                        ? Icons.check_circle
                                                        : Icons.cancel,
                                                    color: inside
                                                        ? Colors.green
                                                        : Colors.red,
                                                  ),
                                                  const SizedBox(width: 8),
                                                  Text(
                                                    inside
                                                        ? 'Inside geofence'
                                                        : 'Outside geofence',
                                                  ),
                                                  const SizedBox(width: 12),
                                                  Flexible(
                                                    child: Text(
                                                      'Lat: ${pos.latitude.toStringAsFixed(6)}, Lng: ${pos.longitude.toStringAsFixed(6)}',
                                                      overflow:
                                                          TextOverflow.ellipsis,
                                                    ),
                                                  ),
                                                ],
                                              ),
                                              const SizedBox(height: 8),
                                              _buildGeofenceSummary(
                                                geofenceAsync.valueOrNull,
                                              ),
                                            ],
                                          );
                                        },
                                        loading: () =>
                                            const Text('Fetching location...'),
                                        error: (err, st) =>
                                            Text('Location error: $err'),
                                      ),
                              ],
                            ),
                          ),
                        ),
                      ),
                      const SizedBox(width: 12),
                      Material(
                        type: MaterialType.transparency,
                        child: Column(
                          children: [
                            Row(
                              mainAxisSize: MainAxisSize.min,
                              children: [
                                const Text('Live'),
                                const SizedBox(width: 6),
                                Switch.adaptive(
                                  key: const Key('live-switch'),
                                  value: _liveTracking,
                                  onChanged: (v) =>
                                      setState(() => _liveTracking = v),
                                ),
                              ],
                            ),
                            const SizedBox(height: 6),
                            SizedBox(
                              height: 48,
                              child: FilledButton.icon(
                                icon: const Icon(Icons.my_location),
                                label: const Text('Refresh'),
                                onPressed: () =>
                                    ref.refresh(currentPositionProvider),
                              ),
                            ),
                            const SizedBox(height: 8),
                            IconButton(
                              tooltip: 'Center map on current location',
                              onPressed: () {
                                final pos = (_liveTracking
                                    ? streamAsync?.valueOrNull
                                    : positionAsync.valueOrNull);
                                if (pos != null) {
                                  _centerOn(
                                    LatLng(pos.latitude, pos.longitude),
                                  );
                                  setState(() => _followMe = true);
                                }
                              },
                              icon: const Icon(Icons.center_focus_strong),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
                const SizedBox(height: 12),
                Expanded(
                  child: Card(
                    margin: const EdgeInsets.symmetric(horizontal: 16.0),
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: geofenceAsync.when(
                        data: (cfg) {
                          final polygonPoints =
                              cfg?.polygon
                                  ?.map((p) => LatLng(p.lat, p.lng))
                                  .toList() ??
                              <LatLng>[];

                          final markers = <Marker>[];
                          if (positionAsync.valueOrNull != null) {
                            final p = positionAsync.value!;
                            markers.add(
                              Marker(
                                point: LatLng(p.latitude, p.longitude),
                                width: 40,
                                height: 40,
                                // `child` is used by newer flutter_map Marker API.
                                child: const Icon(
                                  Icons.person_pin_circle,
                                  size: 36,
                                  color: Colors.blue,
                                ),
                              ),
                            );
                          }

                          final polygonLayer = polygonPoints.isNotEmpty
                              ? PolygonLayer(
                                  polygons: [
                                    Polygon(
                                      points: polygonPoints,
                                      color: Colors.green.withValues(
                                        alpha: 0.15,
                                      ),
                                      borderColor: Colors.green,
                                      borderStrokeWidth: 2,
                                    ),
                                  ],
                                )
                              : const SizedBox.shrink();

                          final circleLayer = (cfg?.hasCircle == true)
                              ? CircleLayer(
                                  circles: [
                                    CircleMarker(
                                      point: LatLng(cfg!.lat!, cfg.lng!),
                                      color: Colors.green.withValues(
                                        alpha: 0.10,
                                      ),
                                      borderStrokeWidth: 2,
                                      useRadiusInMeter: true,
                                      radius: cfg.radiusMeters ?? 100,
                                    ),
                                  ],
                                )
                              : const SizedBox.shrink();

                          // Prefer the live-stream position when enabled, else
                          // fall back to the one-shot value used by the rest of
                          // the app/tests.
                          final activePos = _liveTracking
                              ? streamAsync?.valueOrNull
                              : positionAsync.valueOrNull;

                          final effectiveCenter = cfg?.hasCircle == true
                              ? LatLng(cfg!.lat!, cfg.lng!)
                              : (activePos != null
                                    ? LatLng(
                                        activePos.latitude,
                                        activePos.longitude,
                                      )
                                    : const LatLng(7.2009, 124.2360));

                          // Build the map inside a Stack so we can overlay a
                          // small legend/radius label on top of the map.
                          return Stack(
                            children: [
                              FlutterMap(
                                mapController: _mapController,
                                options: MapOptions(
                                  initialCenter: effectiveCenter,
                                  initialZoom: 16.0,
                                  maxZoom: 18,
                                  minZoom: 3,
                                  onPositionChanged: (pos, hasGesture) {
                                    if (hasGesture) {
                                      setState(() => _followMe = false);
                                    }
                                  },
                                ),
                                children: [
                                  TileLayer(
                                    urlTemplate:
                                        'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                                    // Per OSM tile usage policy: set a User-Agent that
                                    // identifies this application. Use the Android
                                    // applicationId so tile servers can contact the
                                    // publisher if necessary.
                                    userAgentPackageName: 'com.example.tasq',
                                  ),
                                  if (polygonPoints.isNotEmpty) polygonLayer,
                                  if (cfg?.hasCircle == true) circleLayer,
                                  if (markers.isNotEmpty)
                                    MarkerLayer(markers: markers),
                                ],
                              ),

                              // Legend / radius label
                              Positioned(
                                right: 12,
                                top: 12,
                                child: Card(
                                  elevation: 2,
                                  child: Padding(
                                    padding: const EdgeInsets.symmetric(
                                      horizontal: 10.0,
                                      vertical: 8.0,
                                    ),
                                    child: Column(
                                      crossAxisAlignment:
                                          CrossAxisAlignment.start,
                                      children: [
                                        Row(
                                          children: [
                                            Container(
                                              width: 12,
                                              height: 12,
                                              decoration: BoxDecoration(
                                                color: Colors.green.withValues(
                                                  alpha: 0.25,
                                                ),
                                                border: Border.all(
                                                  color: Colors.green,
                                                ),
                                              ),
                                            ),
                                            const SizedBox(width: 8),
                                            Text(
                                              cfg?.hasPolygon == true
                                                  ? 'Geofence (polygon)'
                                                  : 'Geofence (circle)',
                                            ),
                                          ],
                                        ),
                                        if (cfg?.hasCircle == true)
                                          Padding(
                                            padding: const EdgeInsets.only(
                                              top: 6.0,
                                            ),
                                            child: Text(
                                              'Radius: ${cfg!.radiusMeters?.toStringAsFixed(0) ?? '-'} m',
                                              style: Theme.of(
                                                context,
                                              ).textTheme.bodySmall,
                                            ),
                                          ),
                                        Padding(
                                          padding: const EdgeInsets.only(
                                            top: 6.0,
                                          ),
                                          child: Row(
                                            children: const [
                                              Icon(
                                                Icons.person_pin_circle,
                                                size: 14,
                                                color: Colors.blue,
                                              ),
                                              SizedBox(width: 8),
                                              Text('You'),
                                            ],
                                          ),
                                        ),
                                        const SizedBox(height: 6),
                                        Text(
                                          'Map tiles: © OpenStreetMap contributors',
                                          style: Theme.of(
                                            context,
                                          ).textTheme.bodySmall,
                                        ),
                                      ],
                                    ),
                                  ),
                                ),
                              ),
                            ],
                          );
                        },
                        loading: () =>
                            const Center(child: CircularProgressIndicator()),
                        error: (err, st) => Center(
                          child: Text('Failed to load geofence: $err'),
                        ),
                      ),
                    ),
                  ),
                ),
                const SizedBox(height: 12),
              ],
            ),
    );
  }

  Widget _buildGeofenceSummary(GeofenceConfig? cfg) {
    if (cfg == null) return const Text('Geofence: not configured');
    if (cfg.hasCircle) {
      return Text(
        'Geofence: Circle • Radius: ${cfg.radiusMeters?.toStringAsFixed(0) ?? '-'} m',
      );
    }
    if (cfg.hasPolygon) {
      return Text('Geofence: Polygon • ${cfg.polygon?.length ?? 0} points');
    }
    return const Text('Geofence: not configured');
  }
}
