import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:http/http.dart' as http;
import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/resources/source_loctaions_model.dart';
import '../resources/drivers_model.dart';
import '../resources/tankers_model.dart';

class AssignDriverScreenNewDesign extends StatefulWidget {
  final dynamic order;
  final dynamic status;

  const AssignDriverScreenNewDesign({
    super.key,
    this.order,
    this.status,
  });

  @override
  State<AssignDriverScreenNewDesign> createState() =>
      _AssignDriverScreenNewDesignState();
}

class _AssignDriverScreenNewDesignState
    extends State<AssignDriverScreenNewDesign> {
  GoogleMapController? _mapController;

  List<DriversModel> driversList = [];
  List<TankersModel> tankersList = [];
  List<SourceLocationsModel> sourceLocationsList = [];

  DriversModel? selectedDriver;
  TankersModel? selectedTanker;
  SourceLocationsModel? selectedSource;

  bool loading = true;
  bool routeLoading = false;

  Set<Marker> _markers = {};
  Set<Polyline> _polylines = {};

  String eta = '';
  String distanceText = '';
  String routeError = '';

  static const String googleApiKey = 'AIzaSyDJpK9RVhlBejtJu9xSGfneuTN6HOfJgSM';

  @override
  void initState() {
    super.initState();
    loadData();
  }

  Future<void> loadData() async {
    try {
      final d = await AppSettings.getDrivers();
      driversList = (jsonDecode(d)['data'] as List)
          .map((e) => DriversModel.fromJson(e))
          .toList();

      final t = await AppSettings.getTankers();
      tankersList = (jsonDecode(t)['data'] as List)
          .map((e) => TankersModel.fromJson(e))
          .toList();

      final s = await AppSettings.getSourceLoctaions();
      sourceLocationsList = (jsonDecode(s)['data'] as List)
          .map((e) => SourceLocationsModel.fromJson(e))
          .toList();
    } catch (e) {
      debugPrint('Load error: $e');
    }

    if (!mounted) return;

    setState(() {
      loading = false;
      _rebuildMarkers();
    });

    WidgetsBinding.instance.addPostFrameCallback((_) {
      _fitMap();
    });
  }

  double? _toDouble(dynamic value) {
    if (value == null) return null;
    if (value is double) return value;
    if (value is int) return value.toDouble();
    return double.tryParse(value.toString().trim());
  }

  LatLng? _deliveryPosition() {
    try {
      final lat = _toDouble(
        widget.order?.lat ??
            widget.order?.delivery_lat ??
            widget.order?.location_lat,
      );
      final lng = _toDouble(
        widget.order?.lng ??
            widget.order?.delivery_lng ??
            widget.order?.location_lng,
      );

      if (lat == null || lng == null) return null;
      return LatLng(lat, lng);
    } catch (e) {
      debugPrint('Delivery parse error: $e');
      return null;
    }
  }

  LatLng? _sourcePosition(SourceLocationsModel source) {
    try {
      final lat = _toDouble(source.latitude);
      final lng = _toDouble(source.longitude);
      if (lat == null || lng == null) return null;
      return LatLng(lat, lng);
    } catch (e) {
      debugPrint('Source parse error: $e');
      return null;
    }
  }

  void _rebuildMarkers() {
    final Set<Marker> markers = {};

    final delivery = _deliveryPosition();
    if (delivery != null) {
      markers.add(
        Marker(
          markerId: const MarkerId('delivery'),
          position: delivery,
          icon: BitmapDescriptor.defaultMarkerWithHue(
            BitmapDescriptor.hueRed,
          ),
          infoWindow: InfoWindow(
            title: widget.order?.building_name?.toString() ?? 'Delivery',
            snippet: 'Customer location',
          ),
        ),
      );
    }

    for (final source in sourceLocationsList) {
      final pos = _sourcePosition(source);
      if (pos == null) continue;

      final bool isSelected = selectedSource?.dbId == source.dbId;

      markers.add(
        Marker(
          markerId: MarkerId('source_${source.dbId}'),
          position: pos,
          icon: BitmapDescriptor.defaultMarkerWithHue(
            isSelected
                ? BitmapDescriptor.hueViolet
                : BitmapDescriptor.hueAzure,
          ),
          infoWindow: InfoWindow(
            title: source.source_name?.toString() ?? 'Source',
            snippet: isSelected ? 'Selected source' : 'Tap to select source',
          ),
          onTap: () async {
            setState(() {
              selectedSource = source;
              routeError = '';
              eta = '';
              distanceText = '';
              _rebuildMarkers();
            });

            await _loadRouteAndEta();

            WidgetsBinding.instance.addPostFrameCallback((_) {
              _fitMap();
            });
          },
        ),
      );
    }

    _markers = markers;
  }

  Future<void> _loadRouteAndEta() async {
    final source = selectedSource;
    final sourcePos = source == null ? null : _sourcePosition(source);
    final deliveryPos = _deliveryPosition();

    if (sourcePos == null || deliveryPos == null) {
      setState(() {
        routeError = 'Source or delivery coordinates missing';
        _polylines = {};
      });
      return;
    }

    setState(() {
      routeLoading = true;
      routeError = '';
    });

    try {
      await Future.wait([
        _loadDirectionsPolyline(sourcePos, deliveryPos),
        _loadEtaWithDirections(sourcePos, deliveryPos),
      ]);
    } catch (e) {
      debugPrint('Route load error: $e');
      if (mounted) {
        setState(() {
          routeError = 'Unable to load route';
        });
      }
    }

    if (!mounted) return;
    setState(() {
      routeLoading = false;
    });
  }

  Future<void> _loadEtaWithDirections(
      LatLng origin,
      LatLng destination,
      ) async {
    try {
      final uri = Uri.parse(
        'https://maps.googleapis.com/maps/api/directions/json'
            '?origin=${origin.latitude},${origin.longitude}'
            '&destination=${destination.latitude},${destination.longitude}'
            '&mode=driving'
            '&departure_time=now'
            '&traffic_model=best_guess'
            '&key=$googleApiKey',
      );

      final response = await http.get(uri);
      final data = jsonDecode(response.body);

      debugPrint('Directions ETA response: $data');

      if (data['status'] != 'OK') {
        setState(() {
          routeError = 'ETA unavailable: ${data['status']}';
        });
        return;
      }

      final routes = data['routes'] as List?;
      if (routes == null || routes.isEmpty) {
        setState(() {
          routeError = 'ETA unavailable';
        });
        return;
      }

      final legs = routes.first['legs'] as List?;
      if (legs == null || legs.isEmpty) {
        setState(() {
          routeError = 'ETA unavailable';
        });
        return;
      }

      final leg = legs.first;
      final distance = leg['distance'];
      final duration = leg['duration'];
      final durationInTraffic = leg['duration_in_traffic'];

      setState(() {
        distanceText = (distance?['text'] ?? '').toString();
        eta = (durationInTraffic?['text'] ?? duration?['text'] ?? '').toString();
      });
    } catch (e) {
      debugPrint('ETA error: $e');
      setState(() {
        routeError = 'ETA request failed';
      });
    }
  }

  Future<void> _loadDirectionsPolyline(
      LatLng origin,
      LatLng destination,
      ) async {
    try {
      final uri = Uri.parse(
        'https://maps.googleapis.com/maps/api/directions/json'
            '?origin=${origin.latitude},${origin.longitude}'
            '&destination=${destination.latitude},${destination.longitude}'
            '&mode=driving'
            '&departure_time=now'
            '&traffic_model=best_guess'
            '&key=$googleApiKey',
      );

      final response = await http.get(uri);
      final data = jsonDecode(response.body);

      debugPrint('Directions route response: $data');

      if (data['status'] != 'OK') {
        setState(() {
          routeError = 'Route unavailable: ${data['status']}';
          _polylines = {};
        });
        return;
      }

      final routes = data['routes'] as List?;
      if (routes == null || routes.isEmpty) {
        setState(() {
          routeError = 'No route found';
          _polylines = {};
        });
        return;
      }

      final encoded = routes.first['overview_polyline']?['points']?.toString();
      if (encoded == null || encoded.isEmpty) {
        setState(() {
          routeError = 'Route polyline missing';
          _polylines = {};
        });
        return;
      }

      final polylinePoints = PolylinePoints();
      final decoded = polylinePoints.decodePolyline(encoded);

      final points = decoded
          .map((p) => LatLng(p.latitude, p.longitude))
          .toList();

      if (points.isEmpty) {
        setState(() {
          routeError = 'Failed to decode route';
          _polylines = {};
        });
        return;
      }

      setState(() {
        _polylines = {
          Polyline(
            polylineId: const PolylineId('source_delivery_route'),
            points: points,
            color: Colors.blue,
            width: 6,
          ),
        };
      });
    } catch (e) {
      debugPrint('Polyline error: $e');
      setState(() {
        routeError = 'Route request failed';
        _polylines = {};
      });
    }
  }

  Future<void> _fitMap() async {
    if (_mapController == null) return;

    final List<LatLng> points = [];

    final delivery = _deliveryPosition();
    if (delivery != null) points.add(delivery);

    for (final source in sourceLocationsList) {
      final pos = _sourcePosition(source);
      if (pos != null) points.add(pos);
    }

    if (points.isEmpty) return;

    if (points.length == 1) {
      await _mapController!.animateCamera(
        CameraUpdate.newCameraPosition(
          CameraPosition(target: points.first, zoom: 14),
        ),
      );
      return;
    }

    double minLat = points.first.latitude;
    double maxLat = points.first.latitude;
    double minLng = points.first.longitude;
    double maxLng = points.first.longitude;

    for (final point in points) {
      if (point.latitude < minLat) minLat = point.latitude;
      if (point.latitude > maxLat) maxLat = point.latitude;
      if (point.longitude < minLng) minLng = point.longitude;
      if (point.longitude > maxLng) maxLng = point.longitude;
    }

    try {
      await _mapController!.animateCamera(
        CameraUpdate.newLatLngBounds(
          LatLngBounds(
            southwest: LatLng(minLat, minLng),
            northeast: LatLng(maxLat, maxLng),
          ),
          80,
        ),
      );
    } catch (_) {
      await Future.delayed(const Duration(milliseconds: 300));
      try {
        await _mapController!.animateCamera(
          CameraUpdate.newLatLngBounds(
            LatLngBounds(
              southwest: LatLng(minLat, minLng),
              northeast: LatLng(maxLat, maxLng),
            ),
            80,
          ),
        );
      } catch (_) {}
    }
  }

  Future<void> assign() async {
    if (selectedDriver == null) {
      _msg('Select driver');
      return;
    }

    if (selectedTanker == null) {
      _msg('Select tanker');
      return;
    }

    if (selectedSource == null) {
      _msg('Select source from map');
      return;
    }

    final payload = <String, dynamic>{};
    payload["tankerName"] = selectedTanker!.tanker_name;
    payload["delivery_agent"] = selectedDriver!.driver_name;
    payload["delivery_agent_mobile"] = selectedDriver!.phone_number;
    payload["water_source_location"] = selectedSource!.source_name;

    AppSettings.preLoaderDialog(context);

    bool status = false;
    try {
      status = await AppSettings.assignTanker(payload, widget.order.dbId);
    } catch (e) {
      debugPrint('Assign error: $e');
    }

    if (mounted) {
      Navigator.pop(context);
    }

    if (!mounted) return;

    if (status) {
      _msg('Assigned successfully');
      Navigator.pop(context, true);
    } else {
      _msg('Assignment failed');
    }
  }

  void _msg(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message)),
    );
  }

  Widget _buildInfoRow(IconData icon, String text) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 8),
      child: Row(
        children: [
          Icon(icon, size: 18),
          const SizedBox(width: 8),
          Expanded(child: Text(text)),
        ],
      ),
    );
  }

  Widget _buildBottomCard() {
    return Container(
      margin: const EdgeInsets.all(15),
      padding: const EdgeInsets.all(15),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(18),
        boxShadow: const [
          BoxShadow(
            blurRadius: 10,
            color: Colors.black26,
            offset: Offset(0, 3),
          ),
        ],
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          DropdownButton<DriversModel>(
            isExpanded: true,
            hint: const Text('Select Driver'),
            value: selectedDriver,
            items: driversList.map((driver) {
              return DropdownMenuItem(
                value: driver,
                child: Text(driver.driver_name?.toString() ?? 'Driver'),
              );
            }).toList(),
            onChanged: (value) {
              setState(() {
                selectedDriver = value;
              });
            },
          ),
          const SizedBox(height: 8),
          DropdownButton<TankersModel>(
            isExpanded: true,
            hint: const Text('Select Tanker'),
            value: selectedTanker,
            items: tankersList.map((tanker) {
              return DropdownMenuItem(
                value: tanker,
                child: Text(
                  '${tanker.tanker_name} (${tanker.capacity})',
                ),
              );
            }).toList(),
            onChanged: (value) {
              setState(() {
                selectedTanker = value;
              });
            },
          ),
          const SizedBox(height: 8),
          _buildInfoRow(
            Icons.water_drop_outlined,
            selectedSource?.source_name?.toString() ?? 'Select source from map',
          ),
          if (routeLoading) ...[
            const SizedBox(height: 8),
            const LinearProgressIndicator(),
          ],
          if (distanceText.isNotEmpty || eta.isNotEmpty) ...[
            const SizedBox(height: 10),
            Container(
              width: double.infinity,
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(
                color: const Color(0XFFF5F4FF),
                borderRadius: BorderRadius.circular(12),
              ),
              child: Column(
                children: [
                  if (distanceText.isNotEmpty)
                    _buildInfoRow(Icons.route, 'Distance: $distanceText'),
                  if (eta.isNotEmpty)
                    _buildInfoRow(Icons.timer_outlined, 'ETA: $eta'),
                ],
              ),
            ),
          ],
          if (routeError.isNotEmpty) ...[
            const SizedBox(height: 8),
            Text(
              routeError,
              style: const TextStyle(
                color: Colors.red,
                fontSize: 12,
              ),
            ),
          ],
          const SizedBox(height: 12),
          SizedBox(
            width: double.infinity,
            child: ElevatedButton(
              onPressed: assign,
              child: const Text('ASSIGN'),
            ),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    if (loading) {
      return const Scaffold(
        body: Center(
          child: CircularProgressIndicator(),
        ),
      );
    }

    return Scaffold(
      appBar: AppBar(
        title: const Text('Enterprise Dispatch Map'),
      ),
      body: Stack(
        children: [
          GoogleMap(
            initialCameraPosition: CameraPosition(
              target: _deliveryPosition() ?? const LatLng(17.3850, 78.4867),
              zoom: 12,
            ),
            markers: _markers,
            polylines: _polylines,
            trafficEnabled: true,
            zoomControlsEnabled: true,
            myLocationButtonEnabled: true,
            mapToolbarEnabled: false,
            onMapCreated: (controller) {
              _mapController = controller;
              Future.delayed(const Duration(milliseconds: 400), () {
                _fitMap();
              });
            },
          ),
          Align(
            alignment: Alignment.bottomCenter,
            child: _buildBottomCard(),
          ),
        ],
      ),
    );
  }
}