/**
 * DailyNotificationDatabase.swift
 * 
 * iOS SQLite database management for daily notifications
 * 
 * @author Matthew Raymer
 * @version 1.0.0
 */

import Foundation
import SQLite3

/**
 * SQLite database manager for daily notifications on iOS
 * 
 * This class manages the SQLite database with the three-table schema:
 * - notif_contents: keep history, fast newest-first reads
 * - notif_deliveries: track many deliveries per slot/time
 * - notif_config: generic configuration KV
 */
class DailyNotificationDatabase {
    
    // MARK: - Constants
    
    private static let TAG = "DailyNotificationDatabase"
    
    // Table names
    static let TABLE_NOTIF_CONTENTS = "notif_contents"
    static let TABLE_NOTIF_DELIVERIES = "notif_deliveries"
    static let TABLE_NOTIF_CONFIG = "notif_config"
    
    // Column names
    static let COL_CONTENTS_ID = "id"
    static let COL_CONTENTS_SLOT_ID = "slot_id"
    static let COL_CONTENTS_PAYLOAD_JSON = "payload_json"
    static let COL_CONTENTS_FETCHED_AT = "fetched_at"
    static let COL_CONTENTS_ETAG = "etag"
    
    static let COL_DELIVERIES_ID = "id"
    static let COL_DELIVERIES_SLOT_ID = "slot_id"
    static let COL_DELIVERIES_FIRE_AT = "fire_at"
    static let COL_DELIVERIES_DELIVERED_AT = "delivered_at"
    static let COL_DELIVERIES_STATUS = "status"
    static let COL_DELIVERIES_ERROR_CODE = "error_code"
    static let COL_DELIVERIES_ERROR_MESSAGE = "error_message"
    
    static let COL_CONFIG_K = "k"
    static let COL_CONFIG_V = "v"
    
    // Status values
    static let STATUS_SCHEDULED = "scheduled"
    static let STATUS_SHOWN = "shown"
    static let STATUS_ERROR = "error"
    static let STATUS_CANCELED = "canceled"
    
    // MARK: - Properties
    
    private var db: OpaquePointer?
    private let path: String
    
    // MARK: - Initialization
    
    /**
     * Initialize database with path
     * 
     * @param path Database file path
     */
    init(path: String) {
        self.path = path
        openDatabase()
    }
    
    /**
     * Open database connection
     */
    private func openDatabase() {
        if sqlite3_open(path, &db) == SQLITE_OK {
            print("\(Self.TAG): Database opened successfully at \(path)")
            createTables()
            configureDatabase()
        } else {
            print("\(Self.TAG): Error opening database: \(String(cString: sqlite3_errmsg(db)))")
        }
    }
    
    /**
     * Create database tables
     */
    private func createTables() {
        // Create notif_contents table
        let createContentsTable = """
            CREATE TABLE IF NOT EXISTS \(Self.TABLE_NOTIF_CONTENTS)(
                \(Self.COL_CONTENTS_ID) INTEGER PRIMARY KEY AUTOINCREMENT,
                \(Self.COL_CONTENTS_SLOT_ID) TEXT NOT NULL,
                \(Self.COL_CONTENTS_PAYLOAD_JSON) TEXT NOT NULL,
                \(Self.COL_CONTENTS_FETCHED_AT) INTEGER NOT NULL,
                \(Self.COL_CONTENTS_ETAG) TEXT,
                UNIQUE(\(Self.COL_CONTENTS_SLOT_ID), \(Self.COL_CONTENTS_FETCHED_AT))
            );
        """
        
        // Create notif_deliveries table
        let createDeliveriesTable = """
            CREATE TABLE IF NOT EXISTS \(Self.TABLE_NOTIF_DELIVERIES)(
                \(Self.COL_DELIVERIES_ID) INTEGER PRIMARY KEY AUTOINCREMENT,
                \(Self.COL_DELIVERIES_SLOT_ID) TEXT NOT NULL,
                \(Self.COL_DELIVERIES_FIRE_AT) INTEGER NOT NULL,
                \(Self.COL_DELIVERIES_DELIVERED_AT) INTEGER,
                \(Self.COL_DELIVERIES_STATUS) TEXT NOT NULL DEFAULT '\(Self.STATUS_SCHEDULED)',
                \(Self.COL_DELIVERIES_ERROR_CODE) TEXT,
                \(Self.COL_DELIVERIES_ERROR_MESSAGE) TEXT
            );
        """
        
        // Create notif_config table
        let createConfigTable = """
            CREATE TABLE IF NOT EXISTS \(Self.TABLE_NOTIF_CONFIG)(
                \(Self.COL_CONFIG_K) TEXT PRIMARY KEY,
                \(Self.COL_CONFIG_V) TEXT NOT NULL
            );
        """
        
        // Create indexes
        let createContentsIndex = """
            CREATE INDEX IF NOT EXISTS notif_idx_contents_slot_time 
            ON \(Self.TABLE_NOTIF_CONTENTS)(\(Self.COL_CONTENTS_SLOT_ID), \(Self.COL_CONTENTS_FETCHED_AT) DESC);
        """
        
        // Execute table creation
        executeSQL(createContentsTable)
        executeSQL(createDeliveriesTable)
        executeSQL(createConfigTable)
        executeSQL(createContentsIndex)
        
        print("\(Self.TAG): Database tables created successfully")
    }
    
    /**
     * Configure database settings
     */
    private func configureDatabase() {
        // Enable WAL mode
        executeSQL("PRAGMA journal_mode=WAL")
        
        // Set synchronous mode
        executeSQL("PRAGMA synchronous=NORMAL")
        
        // Set busy timeout
        executeSQL("PRAGMA busy_timeout=5000")
        
        // Enable foreign keys
        executeSQL("PRAGMA foreign_keys=ON")
        
        // Set user version
        executeSQL("PRAGMA user_version=1")
        
        print("\(Self.TAG): Database configured successfully")
    }
    
    /**
     * Execute SQL statement
     * 
     * @param sql SQL statement to execute
     */
    func executeSQL(_ sql: String) {
        var statement: OpaquePointer?
        
        if sqlite3_prepare_v2(db, sql, -1, &statement, nil) == SQLITE_OK {
            if sqlite3_step(statement) == SQLITE_DONE {
                print("\(Self.TAG): SQL executed successfully: \(sql)")
            } else {
                print("\(Self.TAG): SQL execution failed: \(String(cString: sqlite3_errmsg(db)))")
            }
        } else {
            print("\(Self.TAG): SQL preparation failed: \(String(cString: sqlite3_errmsg(db)))")
        }
        
        sqlite3_finalize(statement)
    }
    
    // MARK: - Public Methods
    
    /**
     * Close database connection
     */
    func close() {
        if sqlite3_close(db) == SQLITE_OK {
            print("\(Self.TAG): Database closed successfully")
        } else {
            print("\(Self.TAG): Error closing database: \(String(cString: sqlite3_errmsg(db)))")
        }
    }
    
    /**
     * Get database path
     * 
     * @return Database file path
     */
    func getPath() -> String {
        return path
    }
    
    /**
     * Check if database is open
     * 
     * @return true if database is open
     */
    func isOpen() -> Bool {
        return db != nil
    }
    
    /**
     * Save notification content to database
     * 
     * @param content Notification content to save
     */
    func saveNotificationContent(_ content: NotificationContent) {
        // TODO: Implement database persistence
        // For Phase 1, storage uses UserDefaults primarily
        print("\(Self.TAG): saveNotificationContent called for \(content.id)")
    }
    
    /**
     * Delete notification content from database
     * 
     * @param id Notification ID
     */
    func deleteNotificationContent(id: String) {
        // TODO: Implement database deletion
        print("\(Self.TAG): deleteNotificationContent called for \(id)")
    }
    
    /**
     * Clear all notifications from database
     */
    func clearAllNotifications() {
        // TODO: Implement database clearing
        print("\(Self.TAG): clearAllNotifications called")
    }
}
