package com.example.weighttracker;

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

import java.util.ArrayList;
import java.util.List;

// This class handles the local SQLite database for users, weights, and goal weight.
public class DatabaseHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "WeightTracker.db";
    private static final int DATABASE_VERSION = 1;

    private static final String TABLE_USERS = "users";
    private static final String TABLE_WEIGHTS = "weights";
    private static final String TABLE_GOAL = "goal";

    private static final String COL_USER_ID = "id";
    private static final String COL_USERNAME = "username";
    private static final String COL_PASSWORD = "password";

    private static final String COL_WEIGHT_ID = "id";
    private static final String COL_DATE = "date";
    private static final String COL_WEIGHT = "weight";

    private static final String COL_GOAL_ID = "id";
    private static final String COL_GOAL_WEIGHT = "goal_weight";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // Creates all required database tables when the app database is first made.
    @Override
    public void onCreate(SQLiteDatabase db) {
        String createUsersTable = "CREATE TABLE " + TABLE_USERS + " (" +
                COL_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_USERNAME + " TEXT UNIQUE, " +
                COL_PASSWORD + " TEXT)";

        String createWeightsTable = "CREATE TABLE " + TABLE_WEIGHTS + " (" +
                COL_WEIGHT_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_DATE + " TEXT, " +
                COL_WEIGHT + " REAL)";

        String createGoalTable = "CREATE TABLE " + TABLE_GOAL + " (" +
                COL_GOAL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_GOAL_WEIGHT + " REAL)";

        db.execSQL(createUsersTable);
        db.execSQL(createWeightsTable);
        db.execSQL(createGoalTable);
    }

    // This works for a class project, but it would erase data in a real app update.
    // A stronger version would migrate the database instead of dropping every table.
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_USERS);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_WEIGHTS);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_GOAL);
        onCreate(db);
    }

    // Creates a new login record.
    public boolean createUser(String username, String password) {
        SQLiteDatabase db = getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(COL_USERNAME, username);

        // Critical note from my review: this is plain text password storage.
        // It is acceptable for this beginner project, but a real app should hash passwords.
        values.put(COL_PASSWORD, password);

        long result = db.insert(TABLE_USERS, null, values);
        db.close();

        return result != -1;
    }

    // Checks whether a username already exists before creating another account.
    public boolean userExists(String username) {
        SQLiteDatabase db = getReadableDatabase();

        Cursor cursor = db.rawQuery(
                "SELECT * FROM " + TABLE_USERS + " WHERE " + COL_USERNAME + " = ?",
                new String[]{username}
        );

        boolean exists = cursor.getCount() > 0;

        cursor.close();
        db.close();

        return exists;
    }

    // Validates login info against the database.
    public boolean validateUser(String username, String password) {
        SQLiteDatabase db = getReadableDatabase();

        // This uses placeholders instead of directly building a query with user input.
        Cursor cursor = db.rawQuery(
                "SELECT * FROM " + TABLE_USERS +
                        " WHERE " + COL_USERNAME + " = ? AND " + COL_PASSWORD + " = ?",
                new String[]{username, password}
        );

        boolean valid = cursor.getCount() > 0;

        cursor.close();
        db.close();

        return valid;
    }

    // Adds a new weight entry.
    public boolean addWeight(String date, double weight) {
        SQLiteDatabase db = getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(COL_DATE, date);
        values.put(COL_WEIGHT, weight);

        long result = db.insert(TABLE_WEIGHTS, null, values);
        db.close();

        return result != -1;
    }

    // Reads every saved weight entry for the RecyclerView.
// Entries are ordered by ID so the progress summary can compare first entry to latest entry.
    public List<WeightEntry> getAllWeights() {
        List<WeightEntry> entries = new ArrayList<>();
        SQLiteDatabase db = getReadableDatabase();

        Cursor cursor = db.rawQuery(
                "SELECT " + COL_WEIGHT_ID + ", " + COL_DATE + ", " + COL_WEIGHT +
                        " FROM " + TABLE_WEIGHTS +
                        " ORDER BY " + COL_WEIGHT_ID + " ASC",
                null
        );

        if (cursor.moveToFirst()) {
            do {
                int id = cursor.getInt(0);
                String date = cursor.getString(1);
                double weight = cursor.getDouble(2);

                entries.add(new WeightEntry(id, date, weight));
            } while (cursor.moveToNext());
        }

        cursor.close();
        db.close();

        return entries;
    }

    // Deletes one weight entry by ID.
    public void deleteWeight(int id) {
        SQLiteDatabase db = getWritableDatabase();

        db.delete(
                TABLE_WEIGHTS,
                COL_WEIGHT_ID + " = ?",
                new String[]{String.valueOf(id)}
        );

        db.close();
    }

    // Updates a selected entry instead of creating a duplicate row.
    public boolean updateWeight(int id, String date, double weight) {
        SQLiteDatabase db = getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(COL_DATE, date);
        values.put(COL_WEIGHT, weight);

        int rows = db.update(
                TABLE_WEIGHTS,
                values,
                COL_WEIGHT_ID + " = ?",
                new String[]{String.valueOf(id)}
        );

        db.close();

        return rows > 0;
    }

    // Saves one goal weight.
    public boolean setGoalWeight(double goalWeight) {
        SQLiteDatabase db = getWritableDatabase();

        // I only keep one goal for this project.
        // If the app grew later, this could support goal history or multiple goals.
        db.delete(TABLE_GOAL, null, null);

        ContentValues values = new ContentValues();
        values.put(COL_GOAL_WEIGHT, goalWeight);

        long result = db.insert(TABLE_GOAL, null, values);
        db.close();

        return result != -1;
    }

    // Gets the saved goal weight, or returns null if the user has not set one yet.
    public Double getGoalWeight() {
        SQLiteDatabase db = getReadableDatabase();

        Cursor cursor = db.rawQuery(
                "SELECT " + COL_GOAL_WEIGHT + " FROM " + TABLE_GOAL + " LIMIT 1",
                null
        );

        Double goal = null;

        if (cursor.moveToFirst()) {
            goal = cursor.getDouble(0);
        }

        cursor.close();
        db.close();

        return goal;
    }
}