package com.example.pap_teste;

import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import android.widget.Button;

public class NovaReservaActivity extends AppCompatActivity {

    private enum State {
        CATEGORIES, RESTAURANTS, DETAILS
    }

    private State currentState = State.CATEGORIES;
    private String selectedCategory = null;
    private com.example.pap_teste.models.Restaurant selectedRestaurant = null;

    private androidx.recyclerview.widget.RecyclerView rvCategories, rvRestaurants;
    private android.view.View scrollNovaReserva;
    private android.widget.TextView txtTitle;
    private android.widget.ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_nova_reserva);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.novaReservaRoot), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        rvCategories = findViewById(R.id.rvCategories);
        rvRestaurants = findViewById(R.id.rvRestaurants);
        scrollNovaReserva = findViewById(R.id.scrollNovaReserva);
        txtTitle = findViewById(R.id.txtTituloNovaReserva);
        progressBar = findViewById(R.id.progressBar);

        Button back = findViewById(R.id.btnVoltar);
        if (back != null) {
            back.setOnClickListener(v -> handleBackNavigation());
        }

        setupCategories();
        updateViewState();
    }

    private void handleBackNavigation() {
        if (currentState == State.RESTAURANTS) {
            currentState = State.CATEGORIES;
            updateViewState();
        } else if (currentState == State.DETAILS) {
            currentState = State.RESTAURANTS;
            updateViewState();
        } else {
            finish();
        }
    }

    private void updateViewState() {
        rvCategories
                .setVisibility(currentState == State.CATEGORIES ? android.view.View.VISIBLE : android.view.View.GONE);
        rvRestaurants
                .setVisibility(currentState == State.RESTAURANTS ? android.view.View.VISIBLE : android.view.View.GONE);
        scrollNovaReserva
                .setVisibility(currentState == State.DETAILS ? android.view.View.VISIBLE : android.view.View.GONE);

        if (currentState == State.CATEGORIES) {
            txtTitle.setText("Escolha o tema");
        } else if (currentState == State.RESTAURANTS) {
            txtTitle.setText("Restaurantes: " + selectedCategory);
        } else {
            txtTitle.setText("Reserva: " + (selectedRestaurant != null ? selectedRestaurant.getName() : ""));
            setupReservationOptions();
            
            android.widget.TextView txtFechado = findViewById(R.id.txtRestauranteFechado);
            boolean isFechado = selectedRestaurant != null && selectedRestaurant.isFechadoWebsite();
            
            if (txtFechado != null) {
                txtFechado.setVisibility(isFechado ? android.view.View.VISIBLE : android.view.View.GONE);
            }
            
            findViewById(R.id.btnSelectDate).setEnabled(!isFechado);
            findViewById(R.id.btnSelectTime).setEnabled(!isFechado);
            findViewById(R.id.etPartySize).setEnabled(!isFechado);
            findViewById(R.id.btnConfirmarReserva).setEnabled(!isFechado);
        }
    }

    private void setupCategories() {
        java.util.List<com.example.pap_teste.models.FoodCategory> cats = new java.util.ArrayList<>();
        cats.add(new com.example.pap_teste.models.FoodCategory("Carnes", R.drawable.cat_carnes));
        cats.add(new com.example.pap_teste.models.FoodCategory("Massas", R.drawable.cat_massas));
        cats.add(new com.example.pap_teste.models.FoodCategory("Sushi", R.drawable.cat_sushi));
        cats.add(new com.example.pap_teste.models.FoodCategory("Pizzas", R.drawable.cat_pizzas));
        cats.add(new com.example.pap_teste.models.FoodCategory("Sobremesas", R.drawable.cat_sobremesas));

        rvCategories.setLayoutManager(new androidx.recyclerview.widget.LinearLayoutManager(this));
        rvCategories.setAdapter(new FoodCategoryAdapter(cats, category -> {
            selectedCategory = category.getName();
            currentState = State.RESTAURANTS;
            setupRestaurants();
            updateViewState();
        }));
    }

    private void setupRestaurants() {
        java.util.List<com.example.pap_teste.models.Restaurant> filteredList = new java.util.ArrayList<>();
        com.google.firebase.database.DatabaseReference usersRef = com.google.firebase.database.FirebaseDatabase
                .getInstance().getReference("Restaurantes");

        if (progressBar != null)
            progressBar.setVisibility(android.view.View.VISIBLE);

        usersRef.orderByChild("category").equalTo(selectedCategory)
                .addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
                    @Override
                    public void onDataChange(
                            @androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
                        if (progressBar != null)
                            progressBar.setVisibility(android.view.View.GONE);
                        filteredList.clear();
                        for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
                            String role = ds.child("role").getValue(String.class);
                            String accountType = ds.child("accountType").getValue(String.class);

                            // Aceitar todos os registos na coleção Restaurantes
                            if (true) {
                                String name = ds.child("establishmentName").getValue(String.class);
                                if (name == null)
                                    name = ds.child("displayName").getValue(String.class);
                                String email = ds.child("email").getValue(String.class);
                                String cat = ds.child("category").getValue(String.class);
                                String logoUrl = ds.child("logoUrl").getValue(String.class);
                                Boolean fechadoWebsite = ds.child("fechadoWebsite").getValue(Boolean.class);

                                if (name != null && email != null) {
                                    com.example.pap_teste.models.Restaurant rest = new com.example.pap_teste.models.Restaurant(name, cat, email,
                                            false, logoUrl);
                                    if (fechadoWebsite != null) {
                                        rest.setFechadoWebsite(fechadoWebsite);
                                    }
                                    if (ds.hasChild("schedule")) {
                                        java.util.Map<String, com.example.pap_teste.models.ScheduleDay> schMap = new java.util.HashMap<>();
                                        for (com.google.firebase.database.DataSnapshot schDs : ds.child("schedule").getChildren()) {
                                            com.example.pap_teste.models.ScheduleDay sd = schDs.getValue(com.example.pap_teste.models.ScheduleDay.class);
                                            schMap.put(schDs.getKey(), sd);
                                        }
                                        rest.setSchedule(schMap);
                                    }
                                    filteredList.add(rest);
                                }
                            }
                        }

                        rvRestaurants.setLayoutManager(
                                new androidx.recyclerview.widget.LinearLayoutManager(NovaReservaActivity.this));
                        rvRestaurants.setAdapter(new RestaurantAdapter(filteredList, restaurant -> {
                            selectedRestaurant = restaurant;
                            currentState = State.DETAILS;
                            updateViewState();
                        }));
                    }

                    @Override
                    public void onCancelled(
                            @androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
                        if (progressBar != null)
                            progressBar.setVisibility(android.view.View.GONE);
                        android.widget.Toast.makeText(NovaReservaActivity.this, "Erro ao carregar restaurantes.",
                                android.widget.Toast.LENGTH_SHORT).show();
                    }
                });
    }

    private String selectedDate = null;
    private String selectedTime = null;

    private void setupReservationOptions() {
        android.widget.Button btnDate = findViewById(R.id.btnSelectDate);
        android.widget.Button btnTime = findViewById(R.id.btnSelectTime);

        btnDate.setOnClickListener(v -> {
            java.util.Calendar cal = java.util.Calendar.getInstance();
            new android.app.DatePickerDialog(this, (view, year, month, dayOfMonth) -> {
                java.util.Calendar selectedCal = java.util.Calendar.getInstance();
                selectedCal.set(year, month, dayOfMonth);
                int dayOfWeek = selectedCal.get(java.util.Calendar.DAY_OF_WEEK);
                String[] dayKeys = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
                String dayKey = dayKeys[dayOfWeek - 1];
                
                boolean isClosed = false;
                if (selectedRestaurant.getSchedule() != null && selectedRestaurant.getSchedule().containsKey(dayKey)) {
                    com.example.pap_teste.models.ScheduleDay sd = selectedRestaurant.getSchedule().get(dayKey);
                    if (sd != null && sd.isClosed()) isClosed = true;
                }
                
                if (isClosed) {
                    android.widget.Toast.makeText(this, "O restaurante encontra-se encerrado na data selecionada.", android.widget.Toast.LENGTH_LONG).show();
                    selectedDate = null;
                    btnDate.setText("Selecionar Data");
                    btnTime.setEnabled(false);
                } else {
                    selectedDate = dayOfMonth + "/" + (month + 1) + "/" + year;
                    btnDate.setText(selectedDate);
                    btnTime.setEnabled(true);
                }
            }, cal.get(java.util.Calendar.YEAR), cal.get(java.util.Calendar.MONTH),
                    cal.get(java.util.Calendar.DAY_OF_MONTH)).show();
        });

        btnTime.setOnClickListener(v -> {
            if (selectedDate == null) {
                android.widget.Toast.makeText(this, "Por favor, selecione primeiro a data.", android.widget.Toast.LENGTH_SHORT).show();
                return;
            }
            java.util.Calendar cal = java.util.Calendar.getInstance();
            new android.app.TimePickerDialog(this, (view, hourOfDay, minute) -> {
                String chosenTime = String.format(java.util.Locale.getDefault(), "%02d:%02d", hourOfDay, minute);
                
                boolean isOutOfHours = false;
                if (selectedDate != null && selectedRestaurant.getSchedule() != null) {
                    try {
                        java.util.Date d = new java.text.SimpleDateFormat("d/M/yyyy", java.util.Locale.getDefault()).parse(selectedDate);
                        java.util.Calendar selectedCal = java.util.Calendar.getInstance();
                        if (d != null) selectedCal.setTime(d);
                        int dayOfWeek = selectedCal.get(java.util.Calendar.DAY_OF_WEEK);
                        String[] dayKeys = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
                        String dayKey = dayKeys[dayOfWeek - 1];
                        
                        com.example.pap_teste.models.ScheduleDay sd = selectedRestaurant.getSchedule().get(dayKey);
                        if (sd != null && !sd.isClosed()) {
                            if (sd.getOpenTime() != null && sd.getCloseTime() != null && !sd.getOpenTime().isEmpty() && !sd.getCloseTime().isEmpty()) {
                                if (chosenTime.compareTo(sd.getOpenTime()) < 0 || chosenTime.compareTo(sd.getCloseTime()) > 0) {
                                    isOutOfHours = true;
                                }
                            }
                        }
                    } catch (Exception e) {}
                }
                
                if (isOutOfHours) {
                    android.widget.Toast.makeText(this, "Por favor selecione uma hora dentro do horário de funcionamento.", android.widget.Toast.LENGTH_LONG).show();
                    selectedTime = null;
                    btnTime.setText("Selecionar Hora");
                } else {
                    selectedTime = chosenTime;
                    btnTime.setText(selectedTime);
                }
            }, cal.get(java.util.Calendar.HOUR_OF_DAY), cal.get(java.util.Calendar.MINUTE), true).show();
        });

        findViewById(R.id.btnConfirmarReserva).setOnClickListener(v -> saveReservation());
    }

    private void saveReservation() {
        android.widget.EditText etPartySize = findViewById(R.id.etPartySize);
        int val = 0;
        try {
            val = Integer.parseInt(etPartySize.getText().toString());
        } catch (Exception e) {
        }
        final int partySize = val;

        if (selectedDate == null || selectedTime == null || partySize == 0) {
            android.widget.Toast.makeText(this, "Por favor, selecione data, hora e número de pessoas.",
                    android.widget.Toast.LENGTH_SHORT).show();
            return;
        }

        String restEmail = selectedRestaurant.getEmail();

        if (progressBar != null)
            progressBar.setVisibility(android.view.View.VISIBLE);
        android.widget.Button btnConfirmar = findViewById(R.id.btnConfirmarReserva);
        if (btnConfirmar != null)
            btnConfirmar.setEnabled(false);

        com.google.firebase.database.DatabaseReference mesasRef = com.google.firebase.database.FirebaseDatabase
                .getInstance().getReference("Mesas");

        mesasRef.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
            @Override
            public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
                int totalMesas = 0;
                for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
                    com.example.pap_teste.models.Mesa m = ds.getValue(com.example.pap_teste.models.Mesa.class);
                    if (m != null && m.getRestauranteEmail() != null && restEmail.trim().equalsIgnoreCase(m.getRestauranteEmail().trim())) {
                        totalMesas++;
                    }
                }

                if (totalMesas == 0) {
                    proceedWithReservation(partySize);
                    return;
                }

                checkReservationsAndSave(totalMesas, partySize);
            }

            @Override
            public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
                proceedWithReservation(partySize);
            }
        });
    }

    private void checkReservationsAndSave(int totalMesas, final int partySize) {
        String restEmail = selectedRestaurant.getEmail();
        com.google.firebase.database.DatabaseReference reservasRef = com.google.firebase.database.FirebaseDatabase
                .getInstance().getReference("reservas");

        reservasRef.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
                    @Override
                    public void onDataChange(
                            @androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
                        int ocupadas = 0;
                        java.util.Map<String, Integer> ocupacaoPorHora = new java.util.HashMap<>();

                        for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
                            com.example.pap_teste.models.Reserva r = ds
                                    .getValue(com.example.pap_teste.models.Reserva.class);
                            if (r != null && r.getRestauranteEmail() != null && 
                                r.getRestauranteEmail().trim().equalsIgnoreCase(restEmail.trim()) && 
                                selectedDate.equals(r.getData()) && !"Cancelada".equals(r.getEstado())
                                    && !"Recusada".equals(r.getEstado())) {
                                int count = ocupacaoPorHora.getOrDefault(r.getHora(), 0) + 1;
                                ocupacaoPorHora.put(r.getHora(), count);
                                if (selectedTime.equals(r.getHora())) {
                                    ocupadas++;
                                }
                            }
                        }

                        if (ocupadas >= totalMesas) {
                            String sugestao = "";
                            String[] horasComuns = { "12:00", "12:30", "13:00", "13:30", "14:00", "19:00", "19:30",
                                    "20:00", "20:30", "21:00", "21:30", "22:00" };
                            for (String h : horasComuns) {
                                if (ocupacaoPorHora.getOrDefault(h, 0) < totalMesas && !h.equals(selectedTime)) {
                                    sugestao = h;
                                    break; // Encontramos a primeira sugestão livre
                                }
                            }
                            String msg = "Não há mesas disponíveis para as " + selectedTime + ".";
                            if (!sugestao.isEmpty()) {
                                msg += " Sugestão: tente reservar para as " + sugestao + ".";
                            } else {
                                msg += " Tente para outro dia.";
                            }
                            android.widget.Toast
                                    .makeText(NovaReservaActivity.this, msg, android.widget.Toast.LENGTH_LONG).show();
                        } else {
                            proceedWithReservation(partySize);
                        }
                    }

                    @Override
                    public void onCancelled(
                            @androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
                        proceedWithReservation(partySize);
                    }
                });
    }

    private void proceedWithReservation(int partySize) {
        String userEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null
                ? com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail()
                : "cliente@teste.com";
        com.google.firebase.database.DatabaseReference ref = com.google.firebase.database.FirebaseDatabase.getInstance()
                .getReference("reservas");
        String id = ref.push().getKey();

        com.example.pap_teste.models.Reserva reserva = new com.example.pap_teste.models.Reserva(
                id,
                userEmail,
                selectedRestaurant.getName(),
                selectedRestaurant.getEmail(),
                selectedDate,
                selectedTime,
                partySize,
                "Pendente");

        if (id != null) {
            ref.child(id).setValue(reserva).addOnCompleteListener(task -> {
                if (progressBar != null)
                    progressBar.setVisibility(android.view.View.GONE);
                android.widget.Button btnConfirmar = findViewById(R.id.btnConfirmarReserva);
                if (btnConfirmar != null)
                    btnConfirmar.setEnabled(true);

                if (task.isSuccessful()) {
                    android.widget.Toast
                            .makeText(NovaReservaActivity.this, "Reserva solicitada com sucesso!",
                                    android.widget.Toast.LENGTH_SHORT)
                            .show();
                    finish();
                } else {
                    android.widget.Toast
                            .makeText(NovaReservaActivity.this, "Erro ao salvar reserva.",
                                    android.widget.Toast.LENGTH_SHORT)
                            .show();
                }
            });
        }
    }
}
