package com.borjabolufer.elevate.utils;

import android.content.Context;
import android.util.Log;

import com.borjabolufer.elevate.model.Comida;
import com.borjabolufer.elevate.model.DiasEntrenamiento;
import com.borjabolufer.elevate.model.Dieta;
import com.borjabolufer.elevate.model.Ejercicio;
import com.borjabolufer.elevate.model.Entrenamiento;
import com.borjabolufer.elevate.model.Semana;
import com.borjabolufer.elevate.model.ValorNutricional;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
  
import java.util.List;
import java.util.ArrayList;

public class JsonParser {
    private static final String TAG = "JsonElevateParser";
    private Gson gson;
      

    public JsonParser(Context context) {   
          
        this.gson = new GsonBuilder()
                .setPrettyPrinting()
                .create();
    }

      
    public JSONObject parsearDesdeArchivoInterno(Context context) {
        try {
            File file = new File(context.getFilesDir(), "plan_entrenamiento.json");
            FileInputStream fis = new FileInputStream(file);
            int size = fis.available();
            byte[] buffer = new byte[size];
            int bytesRead = fis.read(buffer);
            fis.close();
            if (bytesRead < size) {
                Log.w(TAG, "No se pudo leer el archivo completo.");
                  
            }
            String jsonStr = new String(buffer, "UTF-8");
            return new JSONObject(jsonStr);
        } catch (Exception e) {
            Log.e(TAG, "Error al parsear desde archivo interno: " + e.getMessage(), e);
            return null;
        }
    }

      
    private ValorNutricional parseValorNutricional(JSONObject vnObj) throws JSONException {
        if (vnObj == null) return null;
        return new ValorNutricional(
                vnObj.optInt("calorias", 0),
                vnObj.optInt("proteinas", 0),
                vnObj.optInt("carbohidratos", 0),
                vnObj.optInt("grasas", 0)
        );
    }

      
    private Comida parseComida(JSONObject comidaObj) throws JSONException {
        if (comidaObj == null) return null;

          
        String nombre = comidaObj.optString("nombre_del_plato", "Comida sin nombre");
        String receta = comidaObj.optString("receta", "");
        String videoUrl = comidaObj.optString("video_url", "");

        List<String> ingredientes = new ArrayList<>();
        JSONArray alimentosArray = comidaObj.optJSONArray("ingredientes");   
        if (alimentosArray != null) {
            for (int i = 0; i < alimentosArray.length(); i++) {
                ingredientes.add(alimentosArray.getString(i));
            }
        }

        ValorNutricional valorNutricional = null;
        if (comidaObj.has("valor_nutricional") && !comidaObj.isNull("valor_nutricional")) {
            valorNutricional = parseValorNutricional(comidaObj.getJSONObject("valor_nutricional"));
        } else {
              
            valorNutricional = new ValorNutricional(0, 0, 0, 0);
        }
          
        return new Comida(nombre, ingredientes, receta, valorNutricional, videoUrl);
    }


    public Semana convertirJsonASemana(JSONObject jsonObj) {
        List<DiasEntrenamiento> listaDias = new ArrayList<>();

        if (jsonObj == null) {
            Log.e(TAG, "El objeto JSON principal es null en convertirJsonASemana");
            return null;
        }

        try {
            JSONArray diasArray = jsonObj.getJSONArray("semana");

            for (int i = 0; i < diasArray.length(); i++) {
                JSONObject diaObj = diasArray.getJSONObject(i);
                String nombreDia = diaObj.getString("dia");

                  
                Entrenamiento entrenamiento = null;
                if (diaObj.has("entrenamiento") && !diaObj.isNull("entrenamiento")) {
                    JSONObject entObj = diaObj.getJSONObject("entrenamiento");
                    entrenamiento = new Entrenamiento(
                            JsonUtils.parseEjercicios(entObj.getJSONArray("calentamiento")),
                            JsonUtils.parseEjerciciosPrincipales(entObj.getJSONArray("ejercicios_principales")),
                            JsonUtils.parseEjercicios(entObj.getJSONArray("enfriamiento"))
                    );
                }


                  
                Dieta dieta = null;
                if (diaObj.has("dieta") && !diaObj.isNull("dieta")) {
                    JSONObject dietaObj = diaObj.getJSONObject("dieta");
                    Comida desayuno = dietaObj.has("desayuno") && !dietaObj.isNull("desayuno") ? parseComida(dietaObj.getJSONObject("desayuno")) : null;
                    Comida comida = dietaObj.has("comida") && !dietaObj.isNull("comida") ? parseComida(dietaObj.getJSONObject("comida")) : null;
                    Comida cena = dietaObj.has("cena") && !dietaObj.isNull("cena") ? parseComida(dietaObj.getJSONObject("cena")) : null;
                    Comida snacks = dietaObj.has("snack") && !dietaObj.isNull("snack") ? parseComida(dietaObj.getJSONObject("snack")) : null;
                    dieta = new Dieta(desayuno, comida, cena, snacks);
                }

                DiasEntrenamiento dia = new DiasEntrenamiento(0, nombreDia, entrenamiento, dieta);
                listaDias.add(dia);
            }

        } catch (JSONException e) {
            Log.e(TAG, "Error al convertir JSON a Semana: " + e.getMessage(), e);
            return null;
        }

        return new Semana(listaDias);
    }


      
    public Semana parsearDesdeString(String jsonString) {
        try {
            Semana semana = gson.fromJson(jsonString, Semana.class);
            Log.d(TAG, "JSON parseado exitosamente desde String con Gson");
            return semana;
        } catch (Exception e) {
            Log.e(TAG, "Error al parsear JSON desde String con Gson: " + e.getMessage(), e);
            return null;
        }
    }

      
    public String convertirAJson(Semana semana) {
        try {
            return gson.toJson(semana);
        } catch (Exception e) {
            Log.e(TAG, "Error al convertir a JSON con Gson: " + e.getMessage(), e);
            return null;
        }
    }

      
    public DiasEntrenamiento obtenerDia(Semana semana, String nombreDia) {
        if (semana == null || semana.getSemana() == null) return null;

        for (DiasEntrenamiento dia : semana.getSemana()) {
            if (dia.getDia().equalsIgnoreCase(nombreDia)) {
                return dia;
            }
        }
        return null;
    }

      
    public List<String> obtenerEjerciciosDelDia(DiasEntrenamiento dia) {
        List<String> ejercicios = new ArrayList<>();

        if (dia == null || dia.getEntrenamiento() == null) return ejercicios;

        Entrenamiento entrenamiento = dia.getEntrenamiento();

        if (entrenamiento.getCalentamiento() != null) {
            for (Ejercicio ejercicio : entrenamiento.getCalentamiento()) {
                if (ejercicio != null) ejercicios.add("Calentamiento: " + ejercicio.getNombre());
            }
        }

        if (entrenamiento.getEjercicios_principales() != null) {
            for (Ejercicio ejercicio : entrenamiento.getEjercicios_principales()) {
                if (ejercicio != null) ejercicios.add("Principal: " + ejercicio.getNombre() +
                        " (" + ejercicio.getSeries() + "x" + ejercicio.getRepeticiones() + ")");
            }
        }

        if (entrenamiento.getEnfriamiento() != null) {
            for (Ejercicio ejercicio : entrenamiento.getEnfriamiento()) {
                if (ejercicio != null) ejercicios.add("Enfriamiento: " + ejercicio.getNombre());
            }
        }
        return ejercicios;
    }

      
    public int calcularCaloriasTotales(DiasEntrenamiento dia) {
        if (dia == null || dia.getDieta() == null) return 0;

        Dieta dieta = dia.getDieta();
        int total = 0;

        if (dieta.getDesayuno() != null && dieta.getDesayuno().getValor_nutricional() != null) {
            total += dieta.getDesayuno().getValor_nutricional().getCalorías();
        }
        if (dieta.getComida() != null && dieta.getComida().getValor_nutricional() != null) {
            total += dieta.getComida().getValor_nutricional().getCalorías();
        }
        if (dieta.getCena() != null && dieta.getCena().getValor_nutricional() != null) {
            total += dieta.getCena().getValor_nutricional().getCalorías();
        }
        if (dieta.getSnacks() != null && dieta.getSnacks().getValor_nutricional() != null) {
            total += dieta.getSnacks().getValor_nutricional().getCalorías();
        }

        return total;
    }

      
    public String obtenerResumenNutricional(DiasEntrenamiento dia) {
        if (dia == null || dia.getDieta() == null) return "Sin información";

        Dieta dieta = dia.getDieta();
        int calorias = 0, proteinas = 0, carbohidratos = 0, grasas = 0;

        ValorNutricional[] valores = {
                dieta.getDesayuno() != null ? dieta.getDesayuno().getValor_nutricional() : null,
                dieta.getComida() != null ? dieta.getComida().getValor_nutricional() : null,
                dieta.getCena() != null ? dieta.getCena().getValor_nutricional() : null,
                dieta.getSnacks() != null ? dieta.getSnacks().getValor_nutricional() : null
        };

        for (ValorNutricional vn : valores) {
            if (vn != null) {
                calorias += vn.getCalorías();
                proteinas += vn.getProteínas();
                carbohidratos += vn.getCarbohidratos();
                grasas += vn.getGrasas();
            }
        }

        return String.format("Calorías: %d | Proteínas: %dg | Carbohidratos: %dg | Grasas: %dg",
                calorias, proteinas, carbohidratos, grasas);
    }

      
    public boolean validarSemana(Semana semana) {
        if (semana == null) {
            Log.w(TAG, "Semana es null");
            return false;
        }

        if (semana.getSemana() == null || semana.getSemana().isEmpty()) {
            Log.w(TAG, "Lista de días está vacía");
            return false;
        }

        Log.d(TAG, "Semana válida con " + semana.getSemana().size() + " días");
        return true;
    }
}