package com.grigowashere.aismap.controllers;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;
import android.location.GnssStatus;
import android.location.GpsStatus;
import android.location.GpsSatellite;
import com.grigowashere.aismap.models.Vessel;

/**
 * Слушатель GPS координат через стандартный Android Location API
 * Более надежен чем NMEA для получения позиции
 */
public class GPSLocationListener implements LocationListener {
    
    private static final String TAG = "GPSLocationListener";
    
    private Context context;
    private LocationManager locationManager;
    private LocationCallback callback;
    private boolean isListening;
    
    // GPS статус
    private int satelliteCount;
    private int activeSatellites;
    private double pdop = -1.0;
    private double hdop = -1.0;
    private double vdop = -1.0;
    
    // Callback интерфейс
    public interface LocationCallback {
        void onLocationUpdated(Vessel vessel);
        void onGPSStatusChanged(int status);
        void onError(String error);
    }
    
    public GPSLocationListener(Context context) {
        this.context = context;
        this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        this.isListening = false;
    }
    
    public void setCallback(LocationCallback callback) {
        this.callback = callback;
    }
    
    /**
     * Запускает прослушивание GPS координат
     */
    public boolean startListening() {
        if (isListening) {
            Log.w(TAG, "GPS слушатель уже запущен");
            return true;
        }
        
        if (locationManager == null) {
            Log.e(TAG, "LocationManager недоступен");
            if (callback != null) {
                callback.onError("LocationManager недоступен");
            }
            return false;
        }
        
        // Проверяем GPS провайдер
        if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            Log.w(TAG, "GPS провайдер отключен");
            if (callback != null) {
                callback.onError("GPS провайдер отключен");
            }
            return false;
        }
        
        // Проверяем разрешения
        if (context.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) 
                != android.content.pm.PackageManager.PERMISSION_GRANTED) {
            Log.e(TAG, "Нет разрешения ACCESS_FINE_LOCATION");
            if (callback != null) {
                callback.onError("Нет разрешения ACCESS_FINE_LOCATION");
            }
            return false;
        }
        
        try {
            Log.i(TAG, "=== ЗАПУСК GPS LOCATION LISTENER ===");
            
            // Регистрируем слушатель локации с минимальным интервалом
            locationManager.requestLocationUpdates(
                LocationManager.GPS_PROVIDER,
                100L,  // минимальный интервал в мс
                0.0f,  // минимальное расстояние в метрах
                this,
                Looper.getMainLooper()
            );
            
            Log.i(TAG, "✅ GPS location updates запрошены");
            
            // Регистрируем GNSS статус callback для получения информации о спутниках
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                GnssStatus.Callback gnssCallback = new GnssStatus.Callback() {
                    @Override
                    public void onSatelliteStatusChanged(GnssStatus status) {
                        updateSatelliteInfo(status);
                    }
                };
                locationManager.registerGnssStatusCallback(gnssCallback, new android.os.Handler(Looper.getMainLooper()));
                Log.i(TAG, "✅ GNSS статус callback зарегистрирован");
            }
            
            // Для старых версий Android
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                GpsStatus.Listener gpsListener = new GpsStatus.Listener() {
                    @Override
                    public void onGpsStatusChanged(int event) {
                        if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS) {
                            GpsStatus gpsStatus = locationManager.getGpsStatus(null);
                            if (gpsStatus != null) {
                                updateSatelliteInfoLegacy(gpsStatus);
                            }
                        }
                        if (callback != null) {
                            callback.onGPSStatusChanged(event);
                        }
                    }
                };
                locationManager.addGpsStatusListener(gpsListener);
                Log.i(TAG, "✅ GPS статус слушатель зарегистрирован (старый API)");
            }
            
            isListening = true;
            Log.i(TAG, "🎉 GPS Location Listener успешно запущен!");
            return true;
            
        } catch (SecurityException e) {
            Log.e(TAG, "❌ Нет разрешений для доступа к GPS: " + e.getMessage());
            if (callback != null) {
                callback.onError("Нет разрешений для доступа к GPS");
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "❌ Ошибка при запуске GPS слушателя: " + e.getMessage());
            e.printStackTrace();
            if (callback != null) {
                callback.onError("Ошибка запуска: " + e.getMessage());
            }
            return false;
        }
    }
    
    /**
     * Останавливает прослушивание
     */
    public void stopListening() {
        if (!isListening) {
            return;
        }
        
        try {
            if (locationManager != null) {
                locationManager.removeUpdates(this);
                Log.i(TAG, "GPS location updates остановлены");
            }
            
            isListening = false;
            Log.i(TAG, "GPS Location Listener остановлен");
            
        } catch (Exception e) {
            Log.e(TAG, "Ошибка при остановке GPS слушателя: " + e.getMessage());
        }
    }
    
    /**
     * Обновляет информацию о спутниках (новый API)
     */
    private void updateSatelliteInfo(GnssStatus status) {
        int totalCount = status.getSatelliteCount();
        int usedCount = 0;
        
        for (int i = 0; i < totalCount; i++) {
            if (status.usedInFix(i)) {
                usedCount++;
            }
        }
        
        satelliteCount = totalCount;
        activeSatellites = usedCount;
        
        Log.d(TAG, "Спутники: " + usedCount + "/" + totalCount + " активны");
    }
    
    /**
     * Обновляет информацию о спутниках (старый API)
     */
    private void updateSatelliteInfoLegacy(GpsStatus status) {
        int totalCount = 0;
        int usedCount = 0;
        
        for (GpsSatellite satellite : status.getSatellites()) {
            totalCount++;
            if (satellite.usedInFix()) {
                usedCount++;
            }
        }
        
        satelliteCount = totalCount;
        activeSatellites = usedCount;
        
        Log.d(TAG, "Спутники (legacy): " + usedCount + "/" + totalCount + " активны");
    }
    
    // Реализация LocationListener
    
    @Override
    public void onLocationChanged(Location location) {
        if (location == null) {
            Log.w(TAG, "⚠️ Получен null location");
            return;
        }
        
        Log.i(TAG, "📍 Location обновлен: " + location.getLatitude() + ", " + location.getLongitude());
        Log.i(TAG, "📍 Точность: " + location.getAccuracy() + "м, время: " + location.getTime());
        
        // Создаем объект судна с полученными данными
        Vessel vessel = new Vessel();
        vessel.setLatitude(location.getLatitude());
        vessel.setLongitude(location.getLongitude());
        vessel.setAccuracy(location.getAccuracy());
        vessel.setFixTime(location.getTime());
        
        // Определяем качество фикса
        if (location.hasAccuracy()) {
            if (location.getAccuracy() <= 3) {
                vessel.setFixQuality("HIGH_ACCURACY");
            } else if (location.getAccuracy() <= 10) {
                vessel.setFixQuality("GPS");
            } else {
                vessel.setFixQuality("LOW_ACCURACY");
            }
        }
        
        // Обновляем информацию о спутниках
        vessel.updateGPSQuality(satelliteCount, activeSatellites, pdop, hdop, vdop, location.getAccuracy());
        
        // Отправляем обновление через callback
        if (callback != null) {
            callback.onLocationUpdated(vessel);
        }
    }
    
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        String statusName = getLocationStatusName(status);
        Log.d(TAG, "📍 Location статус изменился: " + provider + " = " + status + " (" + statusName + ")");
        
        if (callback != null) {
            callback.onGPSStatusChanged(status);
        }
    }
    
    @Override
    public void onProviderEnabled(String provider) {
        Log.i(TAG, "📍 Location провайдер включен: " + provider);
    }
    
    @Override
    public void onProviderDisabled(String provider) {
        Log.w(TAG, "📍 Location провайдер отключен: " + provider);
    }
    
    /**
     * Устанавливает DOP значения (получаются из NMEA GSA)
     */
    public void setDOPValues(double pdop, double hdop, double vdop) {
        this.pdop = pdop;
        this.hdop = hdop;
        this.vdop = vdop;
        Log.d(TAG, "📊 DOP обновлен: PDOP=" + pdop + ", HDOP=" + hdop + ", VDOP=" + vdop);
    }
    
    /**
     * Устанавливает количество спутников в объект Vessel
     */
    public void setSatellitesInVessel(Vessel vessel) {
        if (vessel != null) {
            // НЕ перезаписываем общее количество спутников из NMEA
            // vessel.setSatellites(satelliteCount); // Убираем эту строку!
            
            // Устанавливаем только количество активных спутников
            vessel.setActiveSatellites(activeSatellites);
            
            Log.d(TAG, "Обновлен Vessel: активных спутников=" + activeSatellites + 
                  " (общее количество из NMEA: " + vessel.getSatellites() + ")");
        }
    }
    
    /**
     * Получает текущее количество спутников
     */
    public int getSatelliteCount() {
        return satelliteCount;
    }
    
    /**
     * Получает количество активных спутников
     */
    public int getActiveSatellites() {
        return activeSatellites;
    }
    
    /**
     * Получает детальную информацию о спутниках
     */
    public String getSatelliteInfo() {
        return String.format("Всего: %d, Активных: %d", satelliteCount, activeSatellites);
    }
    
    /**
     * Проверяет, запущен ли слушатель
     */
    public boolean isListening() {
        return isListening;
    }
    
    /**
     * Получает название статуса локации
     */
    private String getLocationStatusName(int status) {
        switch (status) {
            case android.location.LocationProvider.AVAILABLE: return "AVAILABLE";
            case android.location.LocationProvider.TEMPORARILY_UNAVAILABLE: return "TEMPORARILY_UNAVAILABLE";
            case android.location.LocationProvider.OUT_OF_SERVICE: return "OUT_OF_SERVICE";
            default: return "UNKNOWN(" + status + ")";
        }
    }
    
    /**
     * Освобождает ресурсы
     */
    public void cleanup() {
        if (isListening) {
            stopListening();
        }
        locationManager = null;
    }
}
