import 'dart:async';
import 'dart:convert';
import 'dart:math';
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:url_launcher/url_launcher.dart';
import 'package:supplier_new/common/settings.dart';
import 'otp_start_unloading.dart';
import 'unloading_inprogress.dart';
import 'collect_money.dart';

class DeliveryUpdatesPage extends StatefulWidget {
  var details;
  final String orderId;
  final String initialStatus;

   DeliveryUpdatesPage({
    super.key,
    this.details,
    required this.orderId,
    required this.initialStatus,
  });

  @override
  State<DeliveryUpdatesPage> createState() => _DeliveryUpdatesPageState();
}

class _DeliveryUpdatesPageState extends State<DeliveryUpdatesPage> {

  GoogleMapController? _mapController;
  Timer? _timer;

  final PolylinePoints _polylinePoints = PolylinePoints();

  static const String googleApiKey = "YOUR_GOOGLE_KEY";

  bool isLoading=true;
  bool mapReady=false;

  String currentStatus='';
  String etaText='--';
  String distanceText='--';
  String durationText='--';

  String driverName='';
  String driverPhone='';
  String tankerName='';
  String orderAddress='';

  double? driverLat;
  double? driverLng;

  double? destinationLat;
  double? destinationLng;

  Set<Marker> markers={};
  Set<Polyline> polylines={};

  List<LatLng> routePoints=[];
  LatLng? _lastDriverPosition;
  bool firstCameraMove=true;

  @override
  void initState(){

    super.initState();

    currentStatus=_beautifyStatus(widget.initialStatus);

    _loadTracking(showLoader:true);

    _timer=Timer.periodic(
        Duration(seconds:5),
            (_){
          _loadTracking();
        });

  }

  @override
  void dispose(){

    _timer?.cancel();
    _mapController?.dispose();

    super.dispose();
  }

  Future<void> _loadTracking({bool showLoader=false}) async{

    try{

      final uri=Uri.parse(
          '${AppSettings.host}trackOrder/${widget.orderId}'
      );

      final response=await http.get(uri);

      final decoded=jsonDecode(response.body);

      final data=decoded["data"]??decoded;

      driverLat=_toDouble(data["driverLat"]);
      driverLng=_toDouble(data["driverLng"]);

      destinationLat=_toDouble(data["destinationLat"]);
      destinationLng=_toDouble(data["destinationLng"]);

      driverName=(data["driverName"]??"").toString();

      driverPhone=(data["driverPhone"]??"").toString();

      tankerName=(data["tankerName"]??"").toString();

      orderAddress=(data["address"]??"").toString();

      currentStatus=_beautifyStatus(
          (data["status"]??widget.initialStatus).toString()
      );

      if(driverLat!=null &&
          driverLng!=null &&
          destinationLat!=null &&
          destinationLng!=null){

        await _buildMarkers();
        if(currentStatus.toLowerCase().contains("out for delivery")){

          await _fetchGoogleRouteAndEta();

        }
        await _moveCameraToBounds();

      }

      setState(() {
        isLoading=false;
      });

    }
    catch(e){

      setState(() {
        isLoading=false;
      });

    }

  }

  double _calculateDistanceKm(
      double startLat,
      double startLng,
      double endLat,
      double endLng){

    const double earthRadius=6371;

    final dLat=_degToRad(endLat-startLat);
    final dLng=_degToRad(endLng-startLng);

    final a=
        sin(dLat/2)*sin(dLat/2)+
            cos(_degToRad(startLat))*
                cos(_degToRad(endLat))*
                sin(dLng/2)*
                sin(dLng/2);

    final c=2*atan2(sqrt(a),sqrt(1-a));

    return earthRadius*c;
  }

  double _degToRad(double deg){
    return deg*pi/180;
  }

  Future<void> _buildMarkers() async{

    if(driverLat==null ||
        driverLng==null ||
        destinationLat==null ||
        destinationLng==null){
      return;
    }

    LatLng newDriverPos=
    LatLng(driverLat!,driverLng!);

    /// CHECK MOVEMENT DISTANCE
    bool moved=true;

    if(_lastDriverPosition!=null){

      double diff=
      _calculateDistanceKm(
          _lastDriverPosition!.latitude,
          _lastDriverPosition!.longitude,
          newDriverPos.latitude,
          newDriverPos.longitude
      );

      /// UPDATE ROUTE ONLY IF DRIVER MOVED > 30m
      moved=diff>0.03;

    }

    _lastDriverPosition=newDriverPos;

    markers={

      Marker(
          markerId:MarkerId("driver"),
          position:newDriverPos,
          rotation:0,
          icon:BitmapDescriptor.defaultMarkerWithHue(
              BitmapDescriptor.hueAzure
          )
      ),

      Marker(
          markerId:MarkerId("destination"),
          position:LatLng(destinationLat!,destinationLng!),
          icon:BitmapDescriptor.defaultMarkerWithHue(
              BitmapDescriptor.hueRed
          )
      )

    };

    /// FOLLOW DRIVER CAMERA
    if(_mapController!=null){

      if(firstCameraMove){

        _mapController!.animateCamera(

            CameraUpdate.newLatLngZoom(
                newDriverPos,
                15
            )

        );

        firstCameraMove=false;

      }
      else{

        _mapController!.animateCamera(

            CameraUpdate.newLatLng(
                newDriverPos
            )

        );

      }

    }

  }

  Future<void> _fetchGoogleRouteAndEta() async{

    if(driverLat==null ||
        driverLng==null ||
        destinationLat==null ||
        destinationLng==null){
      return;
    }

    final origin='${driverLat!},${driverLng!}';
    final destination='${destinationLat!},${destinationLng!}';

    final url=Uri.parse(

        "https://maps.googleapis.com/maps/api/directions/json?"
            "origin=$origin"
            "&destination=$destination"
            "&departure_time=now"
            "&traffic_model=best_guess"
            "&mode=driving"
            "&key=$googleApiKey"
    );

    try{

      final res=await http.get(url);

      final data=jsonDecode(res.body);

      if(data["routes"]==null || data["routes"].isEmpty)return;

      final route=data["routes"][0];

      final leg=route["legs"][0];

      /// DISTANCE
      distanceText=
          (leg["distance"]["text"]??"--").toString();

      /// DURATION
      durationText=
          (leg["duration"]["text"]??"--").toString();

      /// ETA WITH TRAFFIC
      if(leg["duration_in_traffic"]!=null){

        etaText=
            leg["duration_in_traffic"]["text"].toString();

      }
      else{

        etaText=durationText;

      }

      /// ROUTE POLYLINE
      final poly=
      route["overview_polyline"]["points"];

      final decoded=
      _polylinePoints.decodePolyline(poly);

      routePoints=
          decoded.map((e)=>
              LatLng(e.latitude,e.longitude)
          ).toList();

      polylines={

        Polyline(
            polylineId:PolylineId("route"),
            points:routePoints,
            width:5,
            color:Color(0XFF8270DB)
        )

      };

    }
    catch(e){

      print("Route error $e");

    }

  }

  Future<void> _moveCameraToBounds() async{

    if(_mapController==null)return;

    LatLngBounds bounds=LatLngBounds(

        southwest:LatLng(
            min(driverLat!,destinationLat!),
            min(driverLng!,destinationLng!)
        ),

        northeast:LatLng(
            max(driverLat!,destinationLat!),
            max(driverLng!,destinationLng!)
        )

    );

    _mapController!.animateCamera(
        CameraUpdate.newLatLngBounds(bounds,70)
    );

  }

  double? _toDouble(val){

    if(val==null)return null;

    return double.tryParse(val.toString());

  }

  String _beautifyStatus(String s){

    return s.replaceAll("_"," ").toUpperCase();

  }

  /// STATUS FLOW BUTTON
  Widget _buildActionButton(){

    String status=currentStatus
        .replaceAll("_"," ")
        .toLowerCase()
        .trim();

    if(status.contains("arrived")){

      return _actionButton(

          "Start Unloading",

              (){

            Navigator.push(
                context,
                MaterialPageRoute(
                    builder:(_)=>UnloadArrivalScreen(
                        details:widget.details
                    )
                )
            );

          });

    }
    if(status.contains("arrived")){
      etaText="Reached destination";
    }

    if(status.contains("unloading started")){

      return _actionButton(

          "Unloading Progress",

              (){

            Navigator.push(
                context,
                MaterialPageRoute(
                    builder:(_)=>UnloadingInProgressScreen(
                        details:widget.details
                    )
                )
            );

          });

    }

    if(status.contains("unloading stopped")){

      return _actionButton(

          "Collect Payment",

              (){

            Navigator.push(
                context,
                MaterialPageRoute(
                    builder:(_)=>CollectMoney(
                        details:widget.details
                    )
                )
            );

          });

    }

    if(status.contains("payment pending")){

      return _actionButton(

          "Complete Delivery",

              (){

            Navigator.push(
                context,
                MaterialPageRoute(
                    builder:(_)=>CollectMoney(
                        details:widget.details
                    )
                )
            );

          });

    }

    return SizedBox();

  }

  Widget _actionButton(
      String text,
      VoidCallback onTap){

    return SizedBox(

      width:double.infinity,

      child:ElevatedButton(

          style:ElevatedButton.styleFrom(

              backgroundColor:Color(0XFF8270DB),

              padding:EdgeInsets.symmetric(vertical:15),

              shape:RoundedRectangleBorder(
                  borderRadius:BorderRadius.circular(20)
              )

          ),

          onPressed:onTap,

          child:Text(
              text,
              style:TextStyle(
                  color:Colors.white,
                  fontSize:16,
                  fontWeight:FontWeight.w600
              )
          )

      ),

    );

  }

  Future<void> _callDriver() async{

    if(widget.details.delivery_agent_mobile.isEmpty)return;

    final uri=Uri.parse("tel:${widget.details.delivery_agent_mobile}");

    await launchUrl(uri);

  }

  @override
  Widget build(BuildContext context){

    return Scaffold(

      backgroundColor:Color(0XFFF2F2F2),

      appBar:AppBar(
        title:Text("Track Delivery"),
        backgroundColor:Colors.white,
      ),

      body:isLoading?

      Center(child:CircularProgressIndicator())

          :

      Column(

        children:[

          Expanded(

              child:GoogleMap(

                  initialCameraPosition:

                  CameraPosition(

                      target:LatLng(
                          driverLat??17.385,
                          driverLng??78.486
                      ),

                      zoom:14

                  ),

                  markers:markers,

                  polylines:polylines,

                  onMapCreated:(c){

                    _mapController=c;

                    mapReady=true;

                  }

              )

          ),

          Container(

            padding:EdgeInsets.all(16),

            decoration:BoxDecoration(

                color:Colors.white,

                borderRadius:BorderRadius.vertical(
                    top:Radius.circular(25)
                )

            ),

            child:Column(

              children:[

                Row(

                  children:[

                    Expanded(

                        child:Text(
                  "${widget.details.delivery_agent_name}",
                            style:TextStyle(
                                fontSize:16,
                                fontWeight:FontWeight.bold
                            )
                        )

                    ),

                    IconButton(

                        onPressed:_callDriver,

                        icon:Icon(Icons.call)

                    )

                  ],

                ),

                SizedBox(height:10),
                Text(
                    "Status : $currentStatus"
                ),
                SizedBox(height:8),

                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [

                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [

                        Text(
                          "ETA",
                          style: TextStyle(
                              fontSize:12,
                              color:Colors.grey
                          ),
                        ),

                        Text(
                          etaText,
                          style: TextStyle(
                              fontSize:14,
                              fontWeight:FontWeight.bold
                          ),
                        )

                      ],
                    ),

                    Column(
                      children: [

                        Text(
                          "Distance",
                          style: TextStyle(
                              fontSize:12,
                              color:Colors.grey
                          ),
                        ),

                        Text(
                          distanceText,
                          style: TextStyle(
                              fontSize:14,
                              fontWeight:FontWeight.bold
                          ),
                        )

                      ],
                    ),

                    Column(
                      children: [

                        Text(
                          "Duration",
                          style: TextStyle(
                              fontSize:12,
                              color:Colors.grey
                          ),
                        ),

                        Text(
                          durationText,
                          style: TextStyle(
                              fontSize:14,
                              fontWeight:FontWeight.bold
                          ),
                        )

                      ],
                    )

                  ],
                ),

                SizedBox(height:15),
                SizedBox(height:20),

                _buildActionButton(),

                SizedBox(height:10),

              ],

            ),

          )

        ],

      ),

    );

  }

}