import sqlite3 from 'node-sqlite3-wasm';

type Database = sqlite3.Database;

/**
 * SQLite schema based on the MySQL erit_main_db schema
 * All tables use snake_case naming to match the server database
 * Data is encrypted before storage and decrypted on retrieval
 */

export const SCHEMA_VERSION = 1;

/**
 * Initialize the local SQLite database with all required tables
 * @param db - SQLite database instance
 */
export function initializeSchema(db: Database): void {
    // Enable foreign keys
    db.exec('PRAGMA foreign_keys = ON');

    // Create sync metadata table (tracks last sync times)
    db.exec(`
        CREATE TABLE IF NOT EXISTS _sync_metadata (
            table_name TEXT PRIMARY KEY,
            last_sync_at INTEGER NOT NULL,
            last_push_at INTEGER,
            pending_changes INTEGER DEFAULT 0
        );
    `);

    // Create pending changes queue (for offline operations)
    db.exec(`
        CREATE TABLE IF NOT EXISTS _pending_changes (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            table_name TEXT NOT NULL,
            operation TEXT NOT NULL, -- 'INSERT', 'UPDATE', 'DELETE'
            record_id TEXT NOT NULL,
            data TEXT, -- JSON data for INSERT/UPDATE
            created_at INTEGER NOT NULL,
            retry_count INTEGER DEFAULT 0
        );
    `);

    // AI Conversations
    db.exec(`
        CREATE TABLE IF NOT EXISTS ai_conversations (
            conversation_id TEXT PRIMARY KEY,
            book_id TEXT NOT NULL,
            mode TEXT NOT NULL,
            title TEXT NOT NULL,
            start_date INTEGER NOT NULL,
            status INTEGER NOT NULL,
            user_id TEXT NOT NULL,
            summary TEXT,
            convo_meta TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // AI Messages History
    db.exec(`
        CREATE TABLE IF NOT EXISTS ai_messages_history (
            message_id TEXT PRIMARY KEY,
            conversation_id TEXT NOT NULL,
            role TEXT NOT NULL,
            message TEXT NOT NULL,
            message_date INTEGER NOT NULL,
            meta_message TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (conversation_id) REFERENCES ai_conversations(conversation_id) ON DELETE CASCADE
        );
    `);

    // Book Acts
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_acts (
            act_id INTEGER PRIMARY KEY,
            title TEXT NOT NULL
        );
    `);

    // Book Act Summaries
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_act_summaries (
            act_sum_id TEXT PRIMARY KEY,
            book_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            act_index INTEGER NOT NULL,
            summary TEXT,
            meta_acts TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book AI Guide Line
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_ai_guide_line (
            user_id TEXT NOT NULL,
            book_id TEXT NOT NULL,
            global_resume TEXT,
            themes TEXT,
            verbe_tense INTEGER,
            narrative_type INTEGER,
            langue INTEGER,
            dialogue_type INTEGER,
            tone TEXT,
            atmosphere TEXT,
            current_resume TEXT,
            meta TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            PRIMARY KEY (user_id, book_id),
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book Chapters
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_chapters (
            chapter_id TEXT PRIMARY KEY,
            book_id TEXT NOT NULL,
            author_id TEXT NOT NULL,
            title TEXT NOT NULL,
            hashed_title TEXT,
            words_count INTEGER,
            chapter_order INTEGER,
            meta_chapter TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book Chapter Content
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_chapter_content (
            content_id TEXT PRIMARY KEY,
            chapter_id TEXT NOT NULL,
            author_id TEXT NOT NULL,
            version INTEGER NOT NULL DEFAULT 2,
            content TEXT NOT NULL,
            words_count INTEGER NOT NULL,
            meta_chapter_content TEXT NOT NULL,
            time_on_it INTEGER NOT NULL DEFAULT 0,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (chapter_id) REFERENCES book_chapters(chapter_id) ON DELETE CASCADE
        );
    `);

    // Book Chapter Infos
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_chapter_infos (
            chapter_info_id TEXT PRIMARY KEY,
            chapter_id TEXT,
            act_id INTEGER,
            incident_id TEXT,
            plot_point_id TEXT,
            book_id TEXT,
            author_id TEXT,
            summary TEXT NOT NULL,
            goal TEXT NOT NULL,
            meta_chapter_info TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (chapter_id) REFERENCES book_chapters(chapter_id) ON DELETE CASCADE,
            FOREIGN KEY (incident_id) REFERENCES book_incidents(incident_id) ON DELETE CASCADE,
            FOREIGN KEY (plot_point_id) REFERENCES book_plot_points(plot_point_id) ON DELETE CASCADE
        );
    `);

    // Book Characters
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_characters (
            character_id TEXT PRIMARY KEY,
            book_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            first_name TEXT NOT NULL,
            last_name TEXT,
            category TEXT NOT NULL,
            title TEXT,
            image TEXT,
            role TEXT,
            biography TEXT,
            history TEXT,
            char_meta TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book Character Attributes
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_characters_attributes (
            attr_id TEXT PRIMARY KEY,
            character_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            attribute_name TEXT NOT NULL,
            attribute_value TEXT NOT NULL,
            attr_meta TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (character_id) REFERENCES book_characters(character_id) ON DELETE CASCADE
        );
    `);

    // Book Character Relations
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_characters_relations (
            rel_id INTEGER PRIMARY KEY,
            character_id INTEGER NOT NULL,
            char_name TEXT NOT NULL,
            type TEXT NOT NULL,
            description TEXT NOT NULL,
            history TEXT NOT NULL,
            synced INTEGER DEFAULT 0
        );
    `);

    // Book Guide Line
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_guide_line (
            user_id TEXT NOT NULL,
            book_id TEXT NOT NULL,
            tone TEXT NOT NULL,
            atmosphere TEXT NOT NULL,
            writing_style TEXT NOT NULL,
            themes TEXT NOT NULL,
            symbolism TEXT NOT NULL,
            motifs TEXT NOT NULL,
            narrative_voice TEXT NOT NULL,
            pacing TEXT NOT NULL,
            intended_audience TEXT NOT NULL,
            key_messages TEXT NOT NULL,
            meta_guide_line TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            PRIMARY KEY (user_id, book_id),
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book Incidents
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_incidents (
            incident_id TEXT PRIMARY KEY,
            author_id TEXT NOT NULL,
            book_id TEXT NOT NULL,
            title TEXT NOT NULL,
            hashed_title TEXT NOT NULL,
            summary TEXT,
            meta_incident TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book Issues
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_issues (
            issue_id TEXT PRIMARY KEY,
            author_id TEXT NOT NULL,
            book_id TEXT NOT NULL,
            name TEXT NOT NULL,
            hashed_issue_name TEXT NOT NULL,
            meta_issue TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book Location
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_location (
            loc_id TEXT PRIMARY KEY,
            book_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            loc_name TEXT NOT NULL,
            loc_original_name TEXT NOT NULL,
            loc_meta TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book Plot Points
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_plot_points (
            plot_point_id TEXT PRIMARY KEY,
            title TEXT NOT NULL,
            hashed_title TEXT NOT NULL,
            summary TEXT,
            linked_incident_id TEXT,
            author_id TEXT NOT NULL,
            book_id TEXT NOT NULL,
            meta_plot TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book World
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_world (
            world_id TEXT PRIMARY KEY,
            name TEXT NOT NULL,
            hashed_name TEXT NOT NULL,
            author_id TEXT NOT NULL,
            book_id TEXT NOT NULL,
            history TEXT,
            politics TEXT,
            economy TEXT,
            religion TEXT,
            languages TEXT,
            meta_world TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book World Elements
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_world_elements (
            element_id TEXT PRIMARY KEY,
            world_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            element_type INTEGER NOT NULL,
            name TEXT NOT NULL,
            original_name TEXT NOT NULL,
            description TEXT,
            meta_element TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (world_id) REFERENCES book_world(world_id) ON DELETE CASCADE
        );
    `);

    // Erit Books
    db.exec(`
        CREATE TABLE IF NOT EXISTS erit_books (
            book_id TEXT PRIMARY KEY,
            type TEXT NOT NULL,
            author_id TEXT NOT NULL,
            title TEXT NOT NULL,
            hashed_title TEXT NOT NULL,
            sub_title TEXT,
            hashed_sub_title TEXT NOT NULL,
            summary TEXT NOT NULL,
            serie_id INTEGER,
            desired_release_date TEXT,
            desired_word_count INTEGER,
            words_count INTEGER,
            cover_image TEXT,
            book_meta TEXT,
            synced INTEGER DEFAULT 0
        );
    `);

    // Erit Book Series
    db.exec(`
        CREATE TABLE IF NOT EXISTS erit_book_series (
            serie_id INTEGER PRIMARY KEY,
            name TEXT NOT NULL,
            author_id INTEGER NOT NULL
        );
    `);

    // Erit Editor Settings
    db.exec(`
        CREATE TABLE IF NOT EXISTS erit_editor (
            user_id TEXT,
            type TEXT NOT NULL,
            text_size INTEGER NOT NULL,
            text_intent INTEGER NOT NULL,
            interline TEXT NOT NULL,
            paper_width INTEGER NOT NULL,
            theme TEXT NOT NULL,
            focus INTEGER NOT NULL,
            synced INTEGER DEFAULT 0
        );
    `);

    // Erit Users
    db.exec(`
        CREATE TABLE IF NOT EXISTS erit_users (
            user_id TEXT PRIMARY KEY,
            first_name TEXT NOT NULL,
            last_name TEXT NOT NULL,
            username TEXT NOT NULL,
            email TEXT NOT NULL,
            origin_email TEXT NOT NULL,
            origin_username TEXT NOT NULL,
            author_name TEXT,
            origin_author_name TEXT,
            plateform TEXT NOT NULL,
            social_id TEXT,
            user_group INTEGER NOT NULL DEFAULT 4,
            password TEXT,
            term_accepted INTEGER NOT NULL DEFAULT 0,
            verify_code TEXT,
            reg_date INTEGER NOT NULL,
            account_verified INTEGER NOT NULL DEFAULT 0,
            user_meta TEXT NOT NULL,
            erite_points INTEGER NOT NULL DEFAULT 100,
            stripe_customer_id TEXT,
            credits_balance REAL DEFAULT 0,
            synced INTEGER DEFAULT 0
        );
    `);

    // Location Element
    db.exec(`
        CREATE TABLE IF NOT EXISTS location_element (
            element_id TEXT PRIMARY KEY,
            location TEXT NOT NULL,
            user_id TEXT NOT NULL,
            element_name TEXT NOT NULL,
            original_name TEXT NOT NULL,
            element_description TEXT,
            element_meta TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (location) REFERENCES book_location(loc_id) ON DELETE CASCADE
        );
    `);

    // Location Sub Element
    db.exec(`
        CREATE TABLE IF NOT EXISTS location_sub_element (
            sub_element_id TEXT PRIMARY KEY,
            element_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            sub_elem_name TEXT NOT NULL,
            original_name TEXT NOT NULL,
            sub_elem_description TEXT,
            sub_elem_meta TEXT NOT NULL,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (element_id) REFERENCES location_element(element_id) ON DELETE CASCADE
        );
    `);

    // User Keys
    db.exec(`
        CREATE TABLE IF NOT EXISTS user_keys (
            user_id TEXT NOT NULL,
            brand TEXT NOT NULL,
            key TEXT NOT NULL,
            actif INTEGER NOT NULL DEFAULT 1,
            synced INTEGER DEFAULT 0,
            FOREIGN KEY (user_id) REFERENCES erit_users(user_id) ON DELETE CASCADE
        );
    `);

    // User Last Chapter
    db.exec(`
        CREATE TABLE IF NOT EXISTS user_last_chapter (
            user_id TEXT NOT NULL,
            book_id TEXT NOT NULL,
            chapter_id TEXT NOT NULL,
            version INTEGER NOT NULL,
            synced INTEGER DEFAULT 0,
            PRIMARY KEY (user_id, book_id),
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE,
            FOREIGN KEY (chapter_id) REFERENCES book_chapters(chapter_id) ON DELETE CASCADE
        );
    `);

    // Create indexes for better performance
    createIndexes(db);

    // Initialize sync metadata for all tables
    initializeSyncMetadata(db);
}

/**
 * Create indexes for frequently queried columns
 */
function createIndexes(db: Database): void {
    db.exec(`
        CREATE INDEX IF NOT EXISTS idx_ai_conversations_book ON ai_conversations(book_id);
        CREATE INDEX IF NOT EXISTS idx_ai_conversations_user ON ai_conversations(user_id);
        CREATE INDEX IF NOT EXISTS idx_ai_messages_conversation ON ai_messages_history(conversation_id);
        CREATE INDEX IF NOT EXISTS idx_chapters_book ON book_chapters(book_id);
        CREATE INDEX IF NOT EXISTS idx_chapter_content_chapter ON book_chapter_content(chapter_id);
        CREATE INDEX IF NOT EXISTS idx_characters_book ON book_characters(book_id);
        CREATE INDEX IF NOT EXISTS idx_character_attrs_character ON book_characters_attributes(character_id);
        CREATE INDEX IF NOT EXISTS idx_world_book ON book_world(book_id);
        CREATE INDEX IF NOT EXISTS idx_world_elements_world ON book_world_elements(world_id);
        CREATE INDEX IF NOT EXISTS idx_pending_changes_table ON _pending_changes(table_name);
        CREATE INDEX IF NOT EXISTS idx_pending_changes_created ON _pending_changes(created_at);
    `);
}

/**
 * Initialize sync metadata for all tables
 */
function initializeSyncMetadata(db: Database): void {
    const tables = [
        'ai_conversations', 'ai_messages_history', 'book_acts', 'book_act_summaries',
        'book_ai_guide_line', 'book_chapters', 'book_chapter_content', 'book_chapter_infos',
        'book_characters', 'book_characters_attributes', 'book_guide_line', 'book_incidents',
        'book_issues', 'book_location', 'book_plot_points', 'book_world', 'book_world_elements',
        'erit_books', 'erit_editor', 'erit_users', 'location_element', 'location_sub_element',
        'user_keys', 'user_last_chapter'
    ];

    for (const table of tables) {
        db.run(`
            INSERT OR IGNORE INTO _sync_metadata (table_name, last_sync_at, pending_changes)
            VALUES (?, 0, 0)
        `, [table]);
    }
}

/**
 * Drop all tables (for testing/reset)
 */
export function dropAllTables(db: Database): void {
    const tables = db.all(`
        SELECT name FROM sqlite_master
        WHERE type='table' AND name NOT LIKE 'sqlite_%'
    `, []) as unknown as { name: string }[];

    db.exec('PRAGMA foreign_keys = OFF');

    for (const { name } of tables) {
        db.exec(`DROP TABLE IF EXISTS ${name}`);
    }

    db.exec('PRAGMA foreign_keys = ON');
}
