package com.borjabolufer.elevate.model;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

import androidx.annotation.Nullable;

import com.borjabolufer.elevate.utils.PasswordUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class UsuarioDbHelper extends SQLiteOpenHelper {
    private static final String TAG = "UsuarioDbHelper";

    private static final String DB_NAME = "elevate_fitness.db";
    private static final int DB_VERSION = 2;

    public static final String TABLE_USUARIOS = "usuarios";

    public static final String COLUMN_ID = "id";
    public static final String COLUMN_EMAIL = "email";
    public static final String COLUMN_NOMBRE_COMPLETO = "nombre_completo";
    public static final String COLUMN_PASSWORD_HASH = "password_hash";
    public static final String COLUMN_SEXO = "sexo";
    public static final String COLUMN_EDAD = "edad";
    public static final String COLUMN_OBJETIVO = "objetivo";
    public static final String COLUMN_DIAS_ENTRENAMIENTO = "dias_entrenamiento";
    public static final String COLUMN_INTENSIDAD = "intensidad";
    public static final String COLUMN_PESO = "peso";
    public static final String COLUMN_ALTURA = "altura";
    public static final String COLUMN_PLAN_JSON = "plan_json";
    public static final String COLUMN_FECHA_REGISTRO = "fecha_registro";

    public UsuarioDbHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_USUARIOS_TABLE = "CREATE TABLE " + TABLE_USUARIOS + "("
                + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                + COLUMN_EMAIL + " TEXT UNIQUE NOT NULL,"
                + COLUMN_NOMBRE_COMPLETO + " TEXT NOT NULL,"
                + COLUMN_PASSWORD_HASH + " TEXT NOT NULL,"
                + COLUMN_SEXO + " TEXT,"
                + COLUMN_EDAD + " INTEGER,"
                + COLUMN_OBJETIVO + " TEXT,"
                + COLUMN_DIAS_ENTRENAMIENTO + " INTEGER,"
                + COLUMN_INTENSIDAD + " TEXT,"
                + COLUMN_PESO + " REAL,"
                + COLUMN_ALTURA + " REAL,"
                + COLUMN_PLAN_JSON + " TEXT,"
                + COLUMN_FECHA_REGISTRO + " TEXT DEFAULT CURRENT_TIMESTAMP"
                + ")";
        db.execSQL(CREATE_USUARIOS_TABLE);
        Log.i(TAG, "Tabla usuarios creada.");
    }

    public void delete(SQLiteDatabase db) {
        String DROP_USUARIOS_TABLE = "DROP TABLE " + TABLE_USUARIOS;
        db.execSQL(DROP_USUARIOS_TABLE);
        Log.i(TAG, "Tabla usuarios eliminada.");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w(TAG, "Actualizando base de datos de la versión " + oldVersion + " a " + newVersion + ", se perderán los datos antiguos.");
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_USUARIOS);
        onCreate(db);
    }

    public long insertarUsuarioCompleto(UsuarioEntity usuario) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        values.put(COLUMN_EMAIL, usuario.getEmail());
        values.put(COLUMN_NOMBRE_COMPLETO, usuario.getNombreCompleto());
        values.put(COLUMN_PASSWORD_HASH, usuario.getPasswordHash());
        values.put(COLUMN_SEXO, usuario.getSexo());
        values.put(COLUMN_EDAD, usuario.getEdad());
        values.put(COLUMN_OBJETIVO, usuario.getObjetivo());
        values.put(COLUMN_DIAS_ENTRENAMIENTO, usuario.getDiasEntrenamiento());
        values.put(COLUMN_INTENSIDAD, usuario.getIntensidad());
        values.put(COLUMN_PESO, usuario.getPeso());
        values.put(COLUMN_ALTURA, usuario.getAltura());
        values.put(COLUMN_PLAN_JSON, usuario.getPlanJson());

        long id = -1;
        try {
            id = db.insertOrThrow(TABLE_USUARIOS, null, values);
            Log.i(TAG, "Nuevo usuario insertado con ID: " + id + " y email: " + usuario.getEmail());
        } catch (Exception e) {
            Log.e(TAG, "Error al insertar usuario: " + e.getMessage());
        } finally {
            db.close();
        }
        return id;
    }

    public boolean checkUserEmailExists(String email) {
        SQLiteDatabase db = this.getReadableDatabase();
        String[] columns = {COLUMN_ID};
        String selection = COLUMN_EMAIL + " = ?";
        String[] selectionArgs = {email};
        Cursor cursor = null;
        try {
            cursor = db.query(TABLE_USUARIOS, columns, selection, selectionArgs, null, null, null);
            int count = cursor.getCount();
            return count > 0;
        } catch (Exception e) {
            Log.e(TAG, "Error al verificar email: " + e.getMessage());
            return false;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            db.close();
        }
    }

    @Nullable
    public UsuarioEntity verificarUsuario(String email, String plainPassword) {
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = null;
        UsuarioEntity usuario = null;

        try {
            cursor = db.query(TABLE_USUARIOS,
                    new String[]{COLUMN_ID, COLUMN_EMAIL, COLUMN_NOMBRE_COMPLETO, COLUMN_PASSWORD_HASH, COLUMN_SEXO, COLUMN_EDAD, COLUMN_OBJETIVO, COLUMN_DIAS_ENTRENAMIENTO, COLUMN_INTENSIDAD, COLUMN_PESO, COLUMN_ALTURA, COLUMN_PLAN_JSON, COLUMN_FECHA_REGISTRO},
                    COLUMN_EMAIL + " = ?",
                    new String[]{email},
                    null, null, null);

            if (cursor != null && cursor.moveToFirst()) {
                String storedPasswordHash = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PASSWORD_HASH));

                Log.d(TAG, "plainPassword: " + plainPassword);
                Log.d(TAG, "storedPasswordHash: " + storedPasswordHash);

                if (PasswordUtils.verifyPassword(plainPassword, storedPasswordHash)) {
                    usuario = new UsuarioEntity();
                    usuario.setId(cursor.getLong(cursor.getColumnIndexOrThrow(COLUMN_ID)));
                    usuario.setEmail(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_EMAIL)));
                    usuario.setNombreCompleto(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_NOMBRE_COMPLETO)));
                    usuario.setPasswordHash(storedPasswordHash);
                    usuario.setSexo(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_SEXO)));
                    usuario.setEdad(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_EDAD)));
                    usuario.setObjetivo(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_OBJETIVO)));
                    usuario.setDiasEntrenamiento(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_DIAS_ENTRENAMIENTO)));
                    usuario.setIntentensidad(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_INTENSIDAD)));
                    usuario.setPeso(cursor.getDouble(cursor.getColumnIndexOrThrow(COLUMN_PESO)));
                    usuario.setAltura(cursor.getDouble(cursor.getColumnIndexOrThrow(COLUMN_ALTURA)));
                    usuario.setPlanJson(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PLAN_JSON)));
                    usuario.setFechaRegistro(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_FECHA_REGISTRO)));
                    Log.i(TAG, "Usuario verificado: " + email);
                } else {
                    Log.w(TAG, "Contraseña incorrecta para el usuario: " + email);
                }
            } else {
                Log.w(TAG, "Usuario no encontrado con email: " + email);
            }
        } catch (Exception e) {
            Log.e(TAG, "Error al verificar usuario: " + e.getMessage());
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            db.close();
        }
        return usuario;
    }

    @Nullable
    public UsuarioEntity getUsuarioPorEmail(String email) {
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = null;
        UsuarioEntity usuario = null;

        try {
            cursor = db.query(TABLE_USUARIOS,
                    new String[]{COLUMN_ID, COLUMN_EMAIL, COLUMN_NOMBRE_COMPLETO, COLUMN_PASSWORD_HASH, COLUMN_SEXO, COLUMN_EDAD, COLUMN_OBJETIVO, COLUMN_DIAS_ENTRENAMIENTO, COLUMN_INTENSIDAD, COLUMN_PESO, COLUMN_ALTURA, COLUMN_PLAN_JSON, COLUMN_FECHA_REGISTRO},
                    COLUMN_EMAIL + " = ?",
                    new String[]{email},
                    null, null, null);

            if (cursor != null && cursor.moveToFirst()) {
                usuario = new UsuarioEntity();
                usuario.setId(cursor.getLong(cursor.getColumnIndexOrThrow(COLUMN_ID)));
                usuario.setEmail(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_EMAIL)));
                usuario.setNombreCompleto(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_NOMBRE_COMPLETO)));
                usuario.setPasswordHash(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PASSWORD_HASH)));
                usuario.setSexo(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_SEXO)));
                usuario.setEdad(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_EDAD)));
                usuario.setObjetivo(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_OBJETIVO)));
                usuario.setDiasEntrenamiento(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_DIAS_ENTRENAMIENTO)));
                usuario.setIntentensidad(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_INTENSIDAD)));
                usuario.setPeso(cursor.getDouble(cursor.getColumnIndexOrThrow(COLUMN_PESO)));
                usuario.setAltura(cursor.getDouble(cursor.getColumnIndexOrThrow(COLUMN_ALTURA)));
                usuario.setPlanJson(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PLAN_JSON)));
                usuario.setFechaRegistro(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_FECHA_REGISTRO)));
            }
        } catch (Exception e) {
            Log.e(TAG, "Error al obtener usuario por email: " + e.getMessage());
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            db.close();
        }
        return usuario;
    }

    public int actualizarUsuario(UsuarioEntity usuario) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        values.put(COLUMN_NOMBRE_COMPLETO, usuario.getNombreCompleto());
        values.put(COLUMN_EMAIL, usuario.getEmail());

        if (usuario.getPasswordHash() != null && !usuario.getPasswordHash().isEmpty()) {
            values.put(COLUMN_PASSWORD_HASH, usuario.getPasswordHash());
        }

        values.put(COLUMN_SEXO, usuario.getSexo());
        values.put(COLUMN_EDAD, usuario.getEdad());
        values.put(COLUMN_OBJETIVO, usuario.getObjetivo());
        values.put(COLUMN_DIAS_ENTRENAMIENTO, usuario.getDiasEntrenamiento());
        values.put(COLUMN_INTENSIDAD, usuario.getIntensidad());
        values.put(COLUMN_PESO, usuario.getPeso());
        values.put(COLUMN_ALTURA, usuario.getAltura());

        int rowsAffected = 0;
        try {
            rowsAffected = db.update(TABLE_USUARIOS, values, COLUMN_ID + " = ?",
                    new String[]{String.valueOf(usuario.getId())});

            if (rowsAffected > 0) {
                Log.i(TAG, "Usuario actualizado correctamente: " + usuario.getEmail());
            } else {
                Log.w(TAG, "No se pudo actualizar el usuario: " + usuario.getEmail());
            }
        } catch (Exception e) {
            Log.e(TAG, "Error al actualizar usuario: " + e.getMessage());
        } finally {
            db.close();
        }
        return rowsAffected;
    }

    public boolean migrarPlanJson(String emailAnterior, String emailNuevo) {
        SQLiteDatabase db = this.getWritableDatabase();
        try {
            String planJson = obtenerPlanJson(emailAnterior);

            if (planJson != null && !planJson.trim().isEmpty()) {
                ContentValues values = new ContentValues();
                values.put(COLUMN_PLAN_JSON, planJson);

                int updated = db.update(TABLE_USUARIOS, values, COLUMN_EMAIL + " = ?",
                        new String[]{emailNuevo});

                Log.d(TAG, "Plan JSON migrado de " + emailAnterior + " a " + emailNuevo);
                return updated > 0;
            }
            return true;

        } catch (Exception e) {
            Log.e(TAG, "Error al migrar plan JSON: " + e.getMessage());
            return false;
        } finally {
            db.close();
        }
    }

    public int updatePlanJson(String email, String nuevoPlanJson) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(COLUMN_PLAN_JSON, nuevoPlanJson);

        int rowsAffected = 0;
        try {
            rowsAffected = db.update(TABLE_USUARIOS, values, COLUMN_EMAIL + " = ?", new String[]{email});
            if (rowsAffected > 0) {
                Log.i(TAG, "Plan JSON actualizado para el usuario: " + email);
            } else {
                Log.w(TAG, "No se pudo actualizar el plan JSON para el usuario (no encontrado o sin cambios): " + email);
            }
        } catch (Exception e) {
            Log.e(TAG, "Error al actualizar plan JSON: " + e.getMessage());
        } finally {
            db.close();
        }
        return rowsAffected;
    }

    public void actualizarPlanJson(String email, String planJson) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(COLUMN_PLAN_JSON, planJson);

        try {
            db.update(TABLE_USUARIOS, values, COLUMN_EMAIL + " = ?", new String[]{email});
            Log.i(TAG, "Plan JSON actualizado (método legacy) para: " + email);
        } catch (Exception e) {
            Log.e(TAG, "Error al actualizar plan JSON (método legacy): " + e.getMessage());
        } finally {
            db.close();
        }
    }

    public String obtenerPlanJson(String email) {
        SQLiteDatabase db = this.getReadableDatabase();
        String planJson = null;
        Cursor cursor = null;

        try {
            cursor = db.query(TABLE_USUARIOS,
                    new String[]{COLUMN_PLAN_JSON},
                    COLUMN_EMAIL + "=?",
                    new String[]{email},
                    null, null, null);

            if (cursor != null && cursor.moveToFirst()) {
                planJson = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PLAN_JSON));
            }
        } catch (Exception e) {
            Log.e(TAG, "Error al obtener plan JSON: " + e.getMessage());
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            db.close();
        }
        return planJson;
    }

    public boolean guardarPlanJsonEnArchivo(Context context, String email) {
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = null;
        boolean success = false;

        try {
            cursor = db.query(TABLE_USUARIOS,
                    new String[]{COLUMN_PLAN_JSON},
                    COLUMN_EMAIL + "=?",
                    new String[]{email},
                    null, null, null);

            if (cursor != null && cursor.moveToFirst()) {
                String planJson = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PLAN_JSON));

                if (planJson != null && !planJson.trim().isEmpty()) {
                    planJson = planJson.replace("```json", "").replace("```", "").trim();

                    String fileName = "plan_" + email.replace("@", "_").replace(".", "_") + ".json";

                    File jsonFile = new File(context.getFilesDir(), fileName);
                    FileWriter writer = new FileWriter(jsonFile);
                    writer.write(planJson);
                    writer.flush();
                    writer.close();

                    Log.i(TAG, "Plan guardado en archivo: " + fileName);
                    success = true;
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "Error al guardar JSON en archivo interno: ", e);
        } catch (Exception e) {
            Log.e(TAG, "Error general al guardar JSON: ", e);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            db.close();
        }
        return success;
    }

    public String cargarPlanJsonDesdeArchivo(Context context, String email) {
        try {
            String fileName = "plan_" + email.replace("@", "_").replace(".", "_") + ".json";
            File jsonFile = new File(context.getFilesDir(), fileName);

            if (!jsonFile.exists()) {
                Log.w(TAG, "Archivo no encontrado: " + fileName);
                return null;
            }

            StringBuilder jsonContent = new StringBuilder();
            java.io.FileInputStream fis = new java.io.FileInputStream(jsonFile);
            byte[] buffer = new byte[1024];
            int bytesRead;

            while ((bytesRead = fis.read(buffer)) != -1) {
                jsonContent.append(new String(buffer, 0, bytesRead, "UTF-8"));
            }
            fis.close();

            Log.i(TAG, "Plan cargado desde archivo: " + fileName);
            return jsonContent.toString();

        } catch (IOException e) {
            Log.e(TAG, "Error al cargar JSON desde archivo: ", e);
            return null;
        }
    }

    public boolean existePlanJsonArchivo(Context context, String email) {
        String fileName = "plan_" + email.replace("@", "_").replace(".", "_") + ".json";
        File jsonFile = new File(context.getFilesDir(), fileName);
        return jsonFile.exists();
    }

    public boolean eliminarPlanJsonArchivo(Context context, String email) {
        try {
            String fileName = "plan_" + email.replace("@", "_").replace(".", "_") + ".json";
            File jsonFile = new File(context.getFilesDir(), fileName);

            if (jsonFile.exists()) {
                boolean deleted = jsonFile.delete();
                Log.i(TAG, "Archivo eliminado: " + fileName + " - Éxito: " + deleted);
                return deleted;
            }
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Error al eliminar archivo JSON: ", e);
            return false;
        }
    }

    public List<String> listarPlanesExistentes(Context context) {
        List<String> planes = new ArrayList<>();
        File filesDir = context.getFilesDir();
        File[] files = filesDir.listFiles();

        if (files != null) {
            for (File file : files) {
                if (file.getName().startsWith("plan_") && file.getName().endsWith(".json")) {
                    String fileName = file.getName();
                    String email = fileName.replace("plan_", "").replace(".json", "")
                            .replace("_", "@");
                    planes.add(email);
                }
            }
        }
        return planes;
    }

    public String obtenerNombreUsuario(String email) {
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = null;
        String nombre = "Usuario";

        try {
            cursor = db.rawQuery("SELECT nombre_completo FROM usuarios WHERE email = ?", new String[]{email});
            if (cursor != null && cursor.moveToFirst()) {
                nombre = cursor.getString(0);
            }
        } catch (Exception e) {
            Log.e(TAG, "Error al obtener nombre de usuario: " + e.getMessage());
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            db.close();
        }
        return nombre;
    }

    public boolean eliminarUsuario(String email) {
        SQLiteDatabase db = this.getWritableDatabase();
        try {
            int deleted = db.delete(TABLE_USUARIOS, COLUMN_EMAIL + " = ?", new String[]{email});
            if (deleted > 0) {
                Log.i(TAG, "Usuario eliminado: " + email);
                return true;
            } else {
                Log.w(TAG, "No se encontró usuario para eliminar: " + email);
                return false;
            }
        } catch (Exception e) {
            Log.e(TAG, "Error al eliminar usuario: " + e.getMessage());
            return false;
        } finally {
            db.close();
        }
    }

    public List<UsuarioEntity> obtenerTodosLosUsuarios() {
        List<UsuarioEntity> usuarios = new ArrayList<>();
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = null;

        try {
            cursor = db.query(TABLE_USUARIOS, null, null, null, null, null, COLUMN_FECHA_REGISTRO + " DESC");

            if (cursor != null && cursor.moveToFirst()) {
                do {
                    UsuarioEntity usuario = new UsuarioEntity();
                    usuario.setId(cursor.getLong(cursor.getColumnIndexOrThrow(COLUMN_ID)));
                    usuario.setEmail(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_EMAIL)));
                    usuario.setNombreCompleto(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_NOMBRE_COMPLETO)));
                    usuario.setPasswordHash(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PASSWORD_HASH)));
                    usuario.setSexo(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_SEXO)));
                    usuario.setEdad(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_EDAD)));
                    usuario.setObjetivo(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_OBJETIVO)));
                    usuario.setDiasEntrenamiento(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_DIAS_ENTRENAMIENTO)));
                    usuario.setIntentensidad(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_INTENSIDAD)));
                    usuario.setPeso(cursor.getDouble(cursor.getColumnIndexOrThrow(COLUMN_PESO)));
                    usuario.setAltura(cursor.getDouble(cursor.getColumnIndexOrThrow(COLUMN_ALTURA)));
                    usuario.setPlanJson(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PLAN_JSON)));
                    usuario.setFechaRegistro(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_FECHA_REGISTRO)));
                    usuarios.add(usuario);
                } while (cursor.moveToNext());
            }
        } catch (Exception e) {
            Log.e(TAG, "Error al obtener todos los usuarios: " + e.getMessage());
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            db.close();
        }
        return usuarios;
    }

    public int contarUsuarios() {
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = null;
        int count = 0;

        try {
            cursor = db.rawQuery("SELECT COUNT(*) FROM " + TABLE_USUARIOS, null);
            if (cursor != null && cursor.moveToFirst()) {
                count = cursor.getInt(0);
            }
        } catch (Exception e) {
            Log.e(TAG, "Error al contar usuarios: " + e.getMessage());
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            db.close();
        }
        return count;
    }
}