package br.com.localizacelularweb.localizador;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.PowerManager;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import org.json.JSONObject;

import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

public class MainActivity extends AppCompatActivity {

    private static final int REQ_LOCATION = 1001;
    private static final int REQ_NOTIFICATIONS = 1002;

    private LinearLayout areaEscolha, areaCadastro, areaLogin, areaPainel;
    private EditText edtNome, edtUsuarioCadastro, edtSenhaCadastro, edtConfirmarSenha;
    private EditText edtUsuarioLogin, edtSenhaLogin;
    private TextView txtConta, txtDispositivo, txtStatus, txtUltima;
    private Button btnIniciar, btnParar;

    private SharedPreferences prefs;
    private String token;
    private String nomeDispositivo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ligarViews();

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

        mostrarAvisoBateriaPrimeiroAcesso();
        nomeDispositivo = buildDeviceName();
        token = prefs.getString("token", "");

        if (token == null || token.trim().isEmpty()) {
            token = generateToken();
            prefs.edit().putString("token", token).apply();
        }

        configurarAcoes();

        // Esta versão exige uma autenticação/cadastro confirmado pela API.
        // Não reutiliza automaticamente o antigo booleano "autenticado", pois ele pode
        // permanecer salvo quando um APK é atualizado por cima de uma versão anterior.
        if (prefs.getBoolean("autenticado_v2", false)) {
            mostrarPainel();
        } else {
            mostrarEscolha();
        }
    }

    private void ligarViews() {
        areaEscolha = findViewById(R.id.areaEscolha);
        areaCadastro = findViewById(R.id.areaCadastro);
        areaLogin = findViewById(R.id.areaLogin);
        areaPainel = findViewById(R.id.areaPainel);

        edtNome = findViewById(R.id.edtNome);
        edtUsuarioCadastro = findViewById(R.id.edtUsuarioCadastro);
        edtSenhaCadastro = findViewById(R.id.edtSenhaCadastro);
        edtConfirmarSenha = findViewById(R.id.edtConfirmarSenha);
        edtUsuarioLogin = findViewById(R.id.edtUsuarioLogin);
        edtSenhaLogin = findViewById(R.id.edtSenhaLogin);

        txtConta = findViewById(R.id.txtConta);
        txtDispositivo = findViewById(R.id.txtDispositivo);
        txtStatus = findViewById(R.id.txtStatus);
        txtUltima = findViewById(R.id.txtUltima);
        btnIniciar = findViewById(R.id.btnIniciar);
        btnParar = findViewById(R.id.btnParar);
    }

    private void configurarAcoes() {
        findViewById(R.id.btnCriarCadastro).setOnClickListener(v -> mostrarCadastro());
        findViewById(R.id.btnJaTenhoCadastro).setOnClickListener(v -> mostrarLogin());
        findViewById(R.id.btnVoltarCadastro).setOnClickListener(v -> mostrarEscolha());
        findViewById(R.id.btnVoltarLogin).setOnClickListener(v -> mostrarEscolha());
        findViewById(R.id.btnCadastrarContinuar).setOnClickListener(v -> cadastrarUsuario());
        findViewById(R.id.btnConfirmarAcesso).setOnClickListener(v -> confirmarAcesso());
        findViewById(R.id.btnSairConta).setOnClickListener(v -> sairConta());

        btnIniciar.setOnClickListener(v -> iniciarFluxoPermissao());
        btnParar.setOnClickListener(v -> pararServico());
    }

    private void esconderAreas() {
        areaEscolha.setVisibility(View.GONE);
        areaCadastro.setVisibility(View.GONE);
        areaLogin.setVisibility(View.GONE);
        areaPainel.setVisibility(View.GONE);
    }

    private void mostrarEscolha() {
        esconderAreas();
        areaEscolha.setVisibility(View.VISIBLE);
    }

    private void mostrarCadastro() {
        esconderAreas();
        areaCadastro.setVisibility(View.VISIBLE);
    }

    private void mostrarLogin() {
        esconderAreas();
        areaLogin.setVisibility(View.VISIBLE);
    }

    private void mostrarPainel() {
        esconderAreas();
        areaPainel.setVisibility(View.VISIBLE);

        String nomeConta = prefs.getString("nome_conta", "");
        String usuarioConta = prefs.getString("usuario_conta", "");
        String conta = nomeConta.trim().isEmpty() ? usuarioConta : nomeConta;

        txtConta.setText("Conta conectada: " + conta);
        txtDispositivo.setText("Dispositivo: " + nomeDispositivo);
        atualizarEstadoBotoes();

        String ultima = prefs.getString("ultima_localizacao", "");
        if (ultima != null && !ultima.isEmpty()) {
            txtUltima.setText(ultima);
        }
    }

    private void cadastrarUsuario() {
        String nome = edtNome.getText().toString().trim();
        String usuario = edtUsuarioCadastro.getText().toString().trim();
        String senha = edtSenhaCadastro.getText().toString();
        String confirmar = edtConfirmarSenha.getText().toString();

        if (nome.isEmpty() || usuario.isEmpty() || senha.isEmpty()) {
            toast("Preencha nome, usuário e senha.");
            return;
        }

        if (senha.length() < 8) {
            toast("A senha precisa ter pelo menos 8 caracteres.");
            return;
        }

        if (!senha.equals(confirmar)) {
            toast("As senhas não conferem.");
            return;
        }

        Map<String, String> dados = new HashMap<>();
        dados.put("nome", nome);
        dados.put("usuario", usuario);
        dados.put("senha", senha);
        dados.put("token", token);
        dados.put("nome_dispositivo", nomeDispositivo);

        txtStatus.setText("Status: criando cadastro...");

        HttpHelper.postForm(
                BuildConfig.BASE_URL + "api/cadastrar_usuario_app.php",
                dados,
                (okHttp, body) -> {
                    if (okHttp && HttpHelper.jsonOk(body)) {
                        salvarSessao(body, nome, usuario);
                        toast("Cadastro realizado com sucesso.");
                        mostrarPainel();
                    } else {
                        toast(mensagemApi(body, "Não foi possível criar o cadastro."));
                    }
                }
        );
    }

    private void confirmarAcesso() {
        String usuario = edtUsuarioLogin.getText().toString().trim();
        String senha = edtSenhaLogin.getText().toString();

        if (usuario.isEmpty() || senha.isEmpty()) {
            toast("Informe usuário e senha.");
            return;
        }

        Map<String, String> dados = new HashMap<>();
        dados.put("usuario", usuario);
        dados.put("senha", senha);
        dados.put("token", token);
        dados.put("nome", nomeDispositivo);

        HttpHelper.postForm(
                BuildConfig.BASE_URL + "api/login_vincular.php",
                dados,
                (okHttp, body) -> {
                    if (okHttp && HttpHelper.jsonOk(body)) {
                        salvarSessao(body, "", usuario);
                        toast("Acesso confirmado.");
                        mostrarPainel();
                    } else {
                        toast(mensagemApi(body, "Usuário ou senha inválidos."));
                    }
                }
        );
    }

    private void salvarSessao(String body, String nomePadrao, String usuarioPadrao) {
        String nome = nomePadrao;
        String usuario = usuarioPadrao;

        try {
            JSONObject obj = new JSONObject(body);
            nome = obj.optString("usuario_nome", nomePadrao);
            usuario = obj.optString("usuario_login", usuarioPadrao);
        } catch (Exception ignored) {}

        prefs.edit()
                .putBoolean("autenticado", true)
                .putBoolean("autenticado_v2", true)
                .putString("nome_conta", nome)
                .putString("usuario_conta", usuario)
                .apply();
    }

    private String mensagemApi(String body, String padrao) {
        try {
            JSONObject obj = new JSONObject(body);
            String mensagem = obj.optString("mensagem", "");
            return mensagem.trim().isEmpty() ? padrao : mensagem;
        } catch (Exception e) {
            return padrao;
        }
    }

    private void sairConta() {
        pararServico();
        prefs.edit()
                .remove("autenticado")
                .remove("autenticado_v2")
                .remove("nome_conta")
                .remove("usuario_conta")
                .apply();
        edtSenhaLogin.setText("");
        mostrarEscolha();
    }

    private String buildDeviceName() {
        String fabricante = Build.MANUFACTURER == null ? "" : Build.MANUFACTURER.trim();
        String modelo = Build.MODEL == null ? "" : Build.MODEL.trim();
        if (fabricante.equalsIgnoreCase(modelo)) return modelo;
        return (fabricante + " " + modelo).trim();
    }

    private String generateToken() {
        try {
            String base = UUID.randomUUID().toString() + "-" + System.currentTimeMillis() + "-" +
                    Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] hash = md.digest(base.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte b : hash) sb.append(String.format(Locale.US, "%02x", b));
            return sb.toString();
        } catch (Exception e) {
            return UUID.randomUUID().toString().replace("-", "") +
                    UUID.randomUUID().toString().replace("-", "");
        }
    }

    private void iniciarFluxoPermissao() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                    REQ_LOCATION
            );
            return;
        }
        pedirNotificacaoSeNecessario();
        iniciarServico();
    }

    private void pedirNotificacaoSeNecessario() {
        if (Build.VERSION.SDK_INT >= 33 &&
                ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
                        != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    this,
                    new String[]{Manifest.permission.POST_NOTIFICATIONS},
                    REQ_NOTIFICATIONS
            );
        }
    }

    private void iniciarServico() {
        // Guarda a intenção do próprio usuário de manter o compartilhamento ativo.
        // Fechar/minimizar o aplicativo não altera esta preferência.
        prefs.edit()
                .putBoolean("compartilhamento_ativo", true)
                .putBoolean("servico_ativo", true)
                .apply();

        Intent intent = new Intent(this, LocationService.class);
        intent.putExtra("token", token);
        ContextCompat.startForegroundService(this, intent);

        txtStatus.setText("Status: compartilhamento ativo");
        btnIniciar.setEnabled(false);
        btnParar.setEnabled(true);
    }

    private void mostrarAvisoBateriaPrimeiroAcesso() {
        boolean jaMostrou = prefs.getBoolean("aviso_bateria_primeiro_acesso", false);

        if (jaMostrou) {
            return;
        }

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

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return;
        }

        PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        if (powerManager != null && powerManager.isIgnoringBatteryOptimizations(getPackageName())) {
            return;
        }

        new AlertDialog.Builder(this)
                .setTitle("Permitir funcionamento em segundo plano")
                .setMessage("Para que a localização continue sendo compartilhada mesmo quando o aplicativo estiver fechado, configure o aplicativo para funcionar sem restrições de bateria.")
                .setCancelable(false)
                .setPositiveButton("CONFIGURAR AGORA", (dialog, which) -> abrirConfiguracaoBateria())
                .setNegativeButton("DEPOIS", null)
                .show();
    }

    private void abrirConfiguracaoBateria() {
        try {
            Intent intentBateria = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
            startActivity(intentBateria);
        } catch (Exception e) {
            try {
                Intent detalhes = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                detalhes.setData(Uri.parse("package:" + getPackageName()));
                startActivity(detalhes);
            } catch (Exception ignored) {
                toast("Abra as configurações do aplicativo e selecione Bateria > Sem restrições.");
            }
        }
    }

    private void pararServico() {
        // Somente este comando, acionado pelo usuário, desliga de forma persistente.
        prefs.edit()
                .putBoolean("compartilhamento_ativo", false)
                .putBoolean("servico_ativo", false)
                .apply();

        stopService(new Intent(this, LocationService.class));

        if (txtStatus != null) txtStatus.setText("Status: compartilhamento parado");
        if (btnIniciar != null) btnIniciar.setEnabled(true);
        if (btnParar != null) btnParar.setEnabled(false);
    }

    private void atualizarEstadoBotoes() {
        boolean ativo = prefs.getBoolean("compartilhamento_ativo", false);
        btnIniciar.setEnabled(!ativo);
        btnParar.setEnabled(ativo);
        if (ativo) txtStatus.setText("Status: compartilhamento ativo");
        else txtStatus.setText("Status: pronto para iniciar");
    }

    private void toast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (prefs == null) return;
        String ultima = prefs.getString("ultima_localizacao", "");
        if (txtUltima != null && ultima != null && !ultima.isEmpty()) txtUltima.setText(ultima);
        if (prefs.getBoolean("autenticado_v2", false) && areaPainel.getVisibility() == View.VISIBLE) {
            atualizarEstadoBotoes();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQ_LOCATION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                pedirNotificacaoSeNecessario();
                iniciarServico();
            } else {
                toast("A localização precisa ser autorizada para iniciar o compartilhamento.");
            }
        }
    }
}
