package com.utopiaindustries.qualitychecker.db;

import static com.utopiaindustries.qualitychecker.db.DatabaseHelper.DRAFT_REPORT_COLUMN_ID;
import static com.utopiaindustries.qualitychecker.db.DatabaseHelper.DRAFT_REPORT_TABLE_NAME;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.utopiaindustries.qualitychecker.models.InspectionReportWrapper;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;

public class ReportRepository {

    private final DatabaseHelper dbHelper;
    private SQLiteDatabase database;
    private final ExecutorService executorService;
    private Context cxt;

    public ReportRepository(Context context) {
        dbHelper = new DatabaseHelper(context);
        executorService = Executors.newSingleThreadExecutor();
        cxt = context;
    }

    private void openDatabase() {
        try {
            if (database == null || !database.isOpen() || !database.isDbLockedByCurrentThread()) {
                database = dbHelper.getWritableDatabase();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void insert(InspectionReportWrapper wrapper) {
        Log.e("insert:  ","*********"+wrapper.getId());
        executeSafely(() -> {
            openDatabase();
            database.beginTransaction();
            try {
                ContentValues values = new ContentValues();
                values.put(DatabaseHelper.REPORT_COLUMN_CONTENT, wrapper.getContent());
                values.put(DatabaseHelper.REPORT_COLUMN_SYNCED, wrapper.isSynced());
                database.insertWithOnConflict(DatabaseHelper.REPORT_TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
                database.setTransactionSuccessful();

                // Count total rows after insert
                /*Cursor cursor = database.rawQuery("SELECT COUNT(*) FROM " + DatabaseHelper.REPORT_TABLE_NAME, null);
                if (cursor != null && cursor.moveToFirst()) {
                    int count = cursor.getInt(0);
                    Log.e("Total Rows Inserted", String.valueOf(count));
                    cursor.close();
                }*/
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                database.endTransaction();
                close();
            }
        });
    }

    public List<String> getAllSavedPaths() {
        List<String> paths = new ArrayList<>();
        openDatabase();
        Cursor cursor = null;
        try {
            cursor = database.query(
                    DatabaseHelper.REPORT_TABLE_NAME,
                    new String[]{DatabaseHelper.REPORT_COLUMN_CONTENT},
                    null, null, null, null, null
            );
            if (cursor != null && cursor.moveToFirst()) {
                do {
                    paths.add(cursor.getString(0));
                } while (cursor.moveToNext());
            }
        } finally {
            if (cursor != null) cursor.close();
            close();
        }
        return paths;
    }


    public void insertOrReplaceUser(InspectionReportWrapper wrapper) {
        executeSafely(() -> {
            openDatabase();
            database.beginTransaction();
            try {

                ContentValues values = new ContentValues();
                values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_ID, wrapper.getId());  // You need to explicitly provide the ID
                values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_CONTENT, wrapper.getContent());
                values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_SYNCED, wrapper.isSynced());

                // Insert or replace a row
                database.replace(DRAFT_REPORT_TABLE_NAME, null, values);
            } catch (Exception e) {
                System.out.println("Draft Button Click-12");
                e.printStackTrace();
            } finally {
                System.out.println("Draft Button Click-13");
                database.endTransaction();
                close();
            }
        });
    }

    public void insertDraft(InspectionReportWrapper wrapper, String fnsku) {
        //System.out.println("Report-ID: "+ wrapper.getId());
        long[] recordId = new long[1];
        executeSafely(() -> {
            openDatabase();
            database.beginTransaction();
            try {
                ContentValues values = new ContentValues();
                if (wrapper.getId() != 0) {
                    //System.out.println("final-insertion: " + wrapper.getId());
                    values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_ID, wrapper.getId());
                    //Log.e("RecordId-Existing: ",""+wrapper.getId());
                    recordId[0] = wrapper.getId();
                }
                values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_CONTENT, wrapper.getContent());
                values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_SYNCED, wrapper.isSynced());
                //database.insertWithOnConflict(DRAFT_REPORT_TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
                long rowId = database.insertWithOnConflict(DRAFT_REPORT_TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
                database.setTransactionSuccessful();
                if (wrapper.getId() == 0 && rowId != -1) {
                    //Log.e("RecordId-New: ", "" + rowId);
                    recordId[0] = rowId;
                }

                SharedPreferences sharedPreferences = cxt.getSharedPreferences("login_prefs", Context.MODE_PRIVATE);
                SharedPreferences.Editor editor = sharedPreferences.edit();

                editor.putString("draftReportId", String.valueOf(recordId[0]));
                editor.apply();

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                database.endTransaction();
                close();
            }
        });
    }

    // Update data based on the id
    /*public void updateData(InspectionReportWrapper wrapper) {

        executeSafely(() -> {
            openDatabase();
            database.beginTransaction();
            try {
                ContentValues values = new ContentValues();
                values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_CONTENT, wrapper.getContent());
                values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_SYNCED, wrapper.isSynced());
                database.update(DRAFT_REPORT_TABLE_NAME, values, DRAFT_REPORT_COLUMN_ID + " = ?", new String[]{String.valueOf(wrapper.getId())});
                database.setTransactionSuccessful();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                database.endTransaction();
                close();
            }
        });
    }*/

    public void updateSyncStatus(long id) {
        executeSafely(() -> {
            openDatabase();
            database.beginTransaction();
            try {
                ContentValues values = new ContentValues();
                values.put(DatabaseHelper.REPORT_COLUMN_SYNCED, true );  // Set the synced value to true
                String whereClause = DatabaseHelper.REPORT_COLUMN_ID + " = ?";
                String[] whereArgs = {String.valueOf(id)};
                database.update(DatabaseHelper.REPORT_TABLE_NAME, values, whereClause, whereArgs);
                database.setTransactionSuccessful();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                database.endTransaction();
                close();
            }
        });
    }

    @SuppressLint("Range")
    public List<InspectionReportWrapper> findAllUnsynced() {
        List<InspectionReportWrapper> reports = new ArrayList<>();
        openDatabase();
        String selection = DatabaseHelper.REPORT_COLUMN_SYNCED + " = ?";
        String[] selectionArgs = {"0"};

        try (Cursor cursor = database.query(DatabaseHelper.REPORT_TABLE_NAME,
                null,
                selection,
                selectionArgs,
                null,
                null,
                null)) {

            if (cursor != null && cursor.moveToFirst()) {
                do {
                    InspectionReportWrapper wrapper = new InspectionReportWrapper();
                    wrapper.setId(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_ID)));
                    wrapper.setContent(cursor.getString(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_CONTENT)));
                    wrapper.setSynced(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_SYNCED)) == 1);
                    reports.add(wrapper);
                } while (cursor.moveToNext());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close();
        }
        return reports;
    }

    /*
    * List Of Draft Reports
    * */
    @SuppressLint("Range")
    public List<InspectionReportWrapper> findAllDraftReports() {
        List<InspectionReportWrapper> reports = new ArrayList<>();
        openDatabase();

        try (Cursor cursor = database.query(DRAFT_REPORT_TABLE_NAME,
                null,
                null,
                null,
                null,
                null,
                null)) {

            if (cursor != null && cursor.moveToFirst()) {
                do {
                    InspectionReportWrapper wrapper = new InspectionReportWrapper();
                    wrapper.setId(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_ID)));
                    wrapper.setContent(cursor.getString(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_CONTENT)));
                    wrapper.setSynced(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_SYNCED)) == 1);
                    reports.add(wrapper);
                } while (cursor.moveToNext());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close();
        }
        return reports;
    }

    /*
     * Single Draft Report
     * */
    @SuppressLint("Range")
    public InspectionReportWrapper findDraftReportById(long id) {
        InspectionReportWrapper report = null;
        openDatabase();

        String selection = DatabaseHelper.REPORT_COLUMN_ID + " = ?";
        String[] selectionArgs = { String.valueOf(id) }; // The ID to search for

        try (Cursor cursor = database.query(DRAFT_REPORT_TABLE_NAME,
                null, // Columns - null selects all columns
                selection, // The WHERE clause
                selectionArgs, // The arguments for the WHERE clause
                null, // Group by
                null, // Having
                null)) { // Order by

            if (cursor != null && cursor.moveToFirst()) {
                report = new InspectionReportWrapper();
                report.setId(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_ID)));
                report.setContent(cursor.getString(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_CONTENT)));
                report.setSynced(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_SYNCED)) == 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close();
        }

        return report; // Returns null if no report is found with the given ID
    }

    /*
     *  Close the database when all operations are complete
     */
    public void close() {
        if (database != null && database.isOpen()) {
            database.close();
        }
    }

    /*
     *  Executes a task safely, ensuring the ExecutorService is still active
     */
    private void executeSafely(Runnable task) {
        try {
            if (!executorService.isShutdown()) {
                executorService.submit(task);
            } else {
                // Handle the situation when the executor is already shut down
                System.err.println("Task execution rejected because ExecutorService is shut down");
            }
        } catch (RejectedExecutionException e) {
            e.printStackTrace();
        }
    }

    /*
    * Delete Draft Record from draft table
    * */

    public void deleteDraftRecordById(Long id) {
        executeSafely(() -> {
            openDatabase();
            database.beginTransaction();
            try {
                String whereClause = DatabaseHelper.DRAFT_REPORT_COLUMN_ID + " = ?";

                String[] whereArgs = {String.valueOf(id)};

                database.delete(DRAFT_REPORT_TABLE_NAME, whereClause, whereArgs);

                database.setTransactionSuccessful();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                database.endTransaction();
                close();
            }

        });
    }
}
