package br.com.detetivesprofissionais.localizacao;

import android.Manifest;
import android.app.*;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public class LocationService extends Service implements LocationListener {

    private static final String CHANNEL_ID = "localizacao_autorizada";
    private static final int NOTIFICATION_ID = 100;

    private LocationManager locationManager;
    private SharedPreferences prefs;
    private String token;

    @Override
    public void onCreate() {
        super.onCreate();

        prefs = getSharedPreferences("localizacao", Context.MODE_PRIVATE);

        criarCanal();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if (intent != null) {
            token = intent.getStringExtra("token");
        }

        if (token == null || token.trim().isEmpty()) {
            token = prefs.getString("token", "");
        }

        iniciarForeground();
        iniciarGps();

        prefs.edit().putBoolean("servico_ativo", true).apply();

        return START_STICKY;
    }

    private void criarCanal() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    "Compartilhamento de localização",
                    NotificationManager.IMPORTANCE_LOW
            );

            channel.setDescription("Informa que a localização está sendo compartilhada.");

            NotificationManager manager = getSystemService(NotificationManager.class);

            if (manager != null) {
                manager.createNotificationChannel(channel);
            }
        }
    }

    private void iniciarForeground() {
        Intent abrirIntent = new Intent(this, MainActivity.class);

        PendingIntent pendingIntent = PendingIntent.getActivity(
                this,
                0,
                abrirIntent,
                Build.VERSION.SDK_INT >= 23
                        ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT
                        : PendingIntent.FLAG_UPDATE_CURRENT
        );

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(android.R.drawable.ic_menu_mylocation)
                .setContentTitle("Localização sendo compartilhada")
                .setContentText("Toque para abrir e interromper o compartilhamento.")
                .setOngoing(true)
                .setContentIntent(pendingIntent)
                .build();

        startForeground(NOTIFICATION_ID, notification);
    }

    private void iniciarGps() {
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        if (locationManager == null) {
            return;
        }

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                        != PackageManager.PERMISSION_GRANTED) {
            stopSelf();
            return;
        }

        try {
            locationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER,
                    30000L,
                    5f,
                    this
            );
        } catch (Exception ignored) {}

        try {
            locationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER,
                    30000L,
                    10f,
                    this
            );
        } catch (Exception ignored) {}
    }

    @Override
    public void onLocationChanged(Location location) {
        enviarLocalizacao(location);
    }

    private void enviarLocalizacao(Location location) {
        if (token == null || token.trim().isEmpty()) {
            return;
        }

        Map<String, String> dados = new HashMap<>();
        dados.put("token", token);
        dados.put("latitude", String.valueOf(location.getLatitude()));
        dados.put("longitude", String.valueOf(location.getLongitude()));
        dados.put("precisao", String.valueOf(location.getAccuracy()));

        if (location.hasSpeed()) {
            dados.put("velocidade", String.valueOf(location.getSpeed()));
        }

        BatteryManager bm = (BatteryManager) getSystemService(BATTERY_SERVICE);

        if (bm != null && Build.VERSION.SDK_INT >= 21) {
            int bateria = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);

            if (bateria >= 0 && bateria <= 100) {
                dados.put("bateria", String.valueOf(bateria));
            }
        }

        HttpHelper.postForm(
                BuildConfig.BASE_URL + "api/localizacao.php",
                dados,
                (okHttp, body) -> {
                    if (okHttp && HttpHelper.jsonOk(body)) {
                        String data = new SimpleDateFormat(
                                "dd/MM/yyyy HH:mm:ss",
                                Locale.getDefault()
                        ).format(new Date());

                        String ultima =
                                "Último envio: " + data +
                                "\nLatitude: " + location.getLatitude() +
                                "\nLongitude: " + location.getLongitude() +
                                "\nPrecisão: " + Math.round(location.getAccuracy()) + " m";

                        prefs.edit()
                                .putString("ultima_localizacao", ultima)
                                .apply();
                    }
                }
        );
    }

    @Override
    public void onDestroy() {
        if (locationManager != null) {
            try {
                locationManager.removeUpdates(this);
            } catch (Exception ignored) {}
        }

        prefs.edit().putBoolean("servico_ativo", false).apply();

        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onProviderEnabled(String provider) {}

    @Override
    public void onProviderDisabled(String provider) {}

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {}
}
