'''
  ____   ___  _     _ _       
 / ___| / _ \| |   (_) |_ ___ 
 \___ \| | | | |   | | __/ _ \
  ___) | |_| | |___| | ||  __/
 |____/ \__\_\_____|_|\__\___|
                              
Script to flush (delete) data from a sqlite database

/usr/bin/python3 /var/www/nebuleair_pro_4g/sqlite/flush_old_data.py

Script that is triggered by a systemd
sudo systemctl status nebuleair-db-cleanup-data.service

Available table are

data_NPM
data_NPM_5channels
data_BME280
data_envea
timestamp_table
data_MPPT
data_NOISE
data_WIND
data_MHZ19

'''

import sqlite3
import datetime
import sys


def table_exists(cursor, table_name):
    """Check if a table exists in the database"""
    try:
        cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name=?", (table_name,))
        return cursor.fetchone() is not None
    except sqlite3.Error as e:
        print(f"[ERROR] Failed to check if table '{table_name}' exists: {e}")
        return False


def get_table_count(cursor, table_name):
    """Get the number of records in a table"""
    try:
        cursor.execute(f"SELECT COUNT(*) FROM {table_name}")
        return cursor.fetchone()[0]
    except sqlite3.Error as e:
        print(f"[WARNING] Could not get count for table '{table_name}': {e}")
        return 0


def delete_old_records(cursor, table_name, cutoff_date_str):
    """Delete old records from a specific table"""
    try:
        # First check how many records will be deleted
        cursor.execute(f"SELECT COUNT(*) FROM {table_name} WHERE timestamp < ?", (cutoff_date_str,))
        records_to_delete = cursor.fetchone()[0]
        
        if records_to_delete == 0:
            print(f"[INFO] No old records to delete from '{table_name}'")
            return True
        
        # Delete the records
        cursor.execute(f"DELETE FROM {table_name} WHERE timestamp < ?", (cutoff_date_str,))
        deleted_count = cursor.rowcount
        
        print(f"[SUCCESS] Deleted {deleted_count} old records from '{table_name}'")
        return True
        
    except sqlite3.Error as e:
        print(f"[ERROR] Failed to delete records from '{table_name}': {e}")
        return False


def main():
    try:
        # Connect to the SQLite database
        print("[INFO] Connecting to database...")
        conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
        cursor = conn.cursor()
        
        # Check database connection
        cursor.execute("SELECT sqlite_version()")
        version = cursor.fetchone()[0]
        print(f"[INFO] Connected to SQLite version: {version}")

        # GET RTC TIME from SQLite
        print("[INFO] Getting timestamp from database...")
        
        # First check if timestamp_table exists
        if not table_exists(cursor, "timestamp_table"):
            print("[ERROR] timestamp_table does not exist!")
            return False

        cursor.execute("SELECT * FROM timestamp_table LIMIT 1")
        row = cursor.fetchone()

        if not row:
            print("[ERROR] No timestamp found in timestamp_table.")
            return False

        rtc_time_str = row[1]  # Assuming timestamp is stored as TEXT (YYYY-MM-DD HH:MM:SS)
        print(f"[INFO] Last recorded timestamp: {rtc_time_str}")

        # Convert last_updated to a datetime object
        try:
            last_updated = datetime.datetime.strptime(rtc_time_str, "%Y-%m-%d %H:%M:%S")
        except ValueError as e:
            print(f"[ERROR] Invalid timestamp format: {e}")
            return False

        # Calculate the cutoff date (60 days before last_updated)
        cutoff_date = last_updated - datetime.timedelta(days=60)
        cutoff_date_str = cutoff_date.strftime("%Y-%m-%d %H:%M:%S")

        print(f"[INFO] Deleting records older than: {cutoff_date_str}")

        # List of tables to delete old data from
        tables_to_clean = [
            "data_NPM", 
            "data_NPM_5channels", 
            "data_BME280", 
            "data_envea",
            "data_WIND", 
            "data_MPPT", 
            "data_NOISE",
            "data_MHZ19"
        ]

        # Check which tables actually exist
        existing_tables = []
        missing_tables = []
        
        for table in tables_to_clean:
            if table_exists(cursor, table):
                existing_tables.append(table)
                record_count = get_table_count(cursor, table)
                print(f"[INFO] Table '{table}' exists with {record_count} records")
            else:
                missing_tables.append(table)
                print(f"[WARNING] Table '{table}' does not exist - skipping")

        if missing_tables:
            print(f"[INFO] Missing tables: {', '.join(missing_tables)}")
        
        if not existing_tables:
            print("[WARNING] No tables found to clean!")
            return True

        # Loop through existing tables and delete old data
        successful_deletions = 0
        failed_deletions = 0
        
        for table in existing_tables:
            if delete_old_records(cursor, table, cutoff_date_str):
                successful_deletions += 1
            else:
                failed_deletions += 1

        # Commit changes before running VACUUM
        print("[INFO] Committing changes...")
        conn.commit()
        print("[SUCCESS] Changes committed successfully!")

        # Only run VACUUM if at least some deletions were successful
        if successful_deletions > 0:
            print("[INFO] Running VACUUM to optimize database space...")
            try:
                cursor.execute("VACUUM")
                print("[SUCCESS] Database optimized successfully!")
            except sqlite3.Error as e:
                print(f"[WARNING] VACUUM failed: {e}")

        # Summary
        print(f"\n[SUMMARY]")
        print(f"Tables processed successfully: {successful_deletions}")
        print(f"Tables with errors: {failed_deletions}")
        print(f"Tables skipped (missing): {len(missing_tables)}")
        
        if failed_deletions == 0:
            print("[SUCCESS] Old data flushed successfully!")
            return True
        else:
            print("[WARNING] Some operations failed - check logs above")
            return False

    except sqlite3.Error as e:
        print(f"[ERROR] Database error: {e}")
        return False
    except Exception as e:
        print(f"[ERROR] Unexpected error: {e}")
        return False
    finally:
        # Always close the database connection
        if 'conn' in locals():
            conn.close()
            print("[INFO] Database connection closed")


if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)