import sqlite3 from 'node-sqlite3-wasm';
import { app } from 'electron';

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
 */

// =============================================================================
// MIGRATIONS
// =============================================================================

const schemaVersion = 3;

/**
 * DEV ONLY - S'exécute à chaque refresh, pas besoin de version
 * Mets ta query, test, efface après
 */
const devQueries: string[] = [
    // V3 Migration: Series tables and series_*_id columns

    // Book Series
    `CREATE TABLE IF NOT EXISTS book_series (
        series_id TEXT PRIMARY KEY,
        user_id TEXT NOT NULL,
        name TEXT NOT NULL,
        hashed_name TEXT NOT NULL,
        description TEXT,
        cover_image TEXT,
        last_update INTEGER DEFAULT 0,
        FOREIGN KEY (user_id) REFERENCES erit_users(user_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_book_series_user ON book_series(user_id)`,

    // Series Books
    `CREATE TABLE IF NOT EXISTS series_books (
        series_id TEXT NOT NULL,
        book_id TEXT NOT NULL,
        book_order INTEGER NOT NULL DEFAULT 1,
        last_update INTEGER DEFAULT 0,
        PRIMARY KEY (series_id, book_id),
        FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE,
        FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_series_books_book ON series_books(book_id)`,

    // Series Characters
    `CREATE TABLE IF NOT EXISTS series_characters (
        character_id TEXT PRIMARY KEY,
        series_id TEXT NOT NULL,
        user_id TEXT NOT NULL,
        first_name TEXT NOT NULL,
        last_name TEXT,
        nickname TEXT,
        age TEXT,
        gender TEXT,
        species TEXT,
        nationality TEXT,
        status TEXT,
        category TEXT NOT NULL,
        title TEXT,
        image TEXT,
        role TEXT,
        biography TEXT,
        history TEXT,
        speech_pattern TEXT,
        catchphrase TEXT,
        residence TEXT,
        notes TEXT,
        color TEXT,
        last_update INTEGER DEFAULT 0,
        FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_series_characters_series ON series_characters(series_id)`,
    `CREATE INDEX IF NOT EXISTS idx_series_characters_user ON series_characters(user_id)`,

    // Series Characters Attributes
    `CREATE TABLE IF NOT EXISTS series_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,
        last_update INTEGER DEFAULT 0,
        FOREIGN KEY (character_id) REFERENCES series_characters(character_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_series_char_attrs_character ON series_characters_attributes(character_id)`,
    `CREATE INDEX IF NOT EXISTS idx_series_char_attrs_user ON series_characters_attributes(user_id)`,

    // Series Worlds
    `CREATE TABLE IF NOT EXISTS series_worlds (
        world_id TEXT PRIMARY KEY,
        series_id TEXT NOT NULL,
        user_id TEXT NOT NULL,
        name TEXT NOT NULL,
        hashed_name TEXT NOT NULL,
        history TEXT,
        politics TEXT,
        economy TEXT,
        religion TEXT,
        languages TEXT,
        last_update INTEGER DEFAULT 0,
        FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_series_worlds_series ON series_worlds(series_id)`,
    `CREATE INDEX IF NOT EXISTS idx_series_worlds_user ON series_worlds(user_id)`,

    // Series World Elements
    `CREATE TABLE IF NOT EXISTS series_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,
        last_update INTEGER DEFAULT 0,
        FOREIGN KEY (world_id) REFERENCES series_worlds(world_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_series_world_elements_world ON series_world_elements(world_id)`,
    `CREATE INDEX IF NOT EXISTS idx_series_world_elements_user ON series_world_elements(user_id)`,

    // Series Locations
    `CREATE TABLE IF NOT EXISTS series_locations (
        loc_id TEXT PRIMARY KEY,
        series_id TEXT NOT NULL,
        user_id TEXT NOT NULL,
        loc_name TEXT NOT NULL,
        loc_original_name TEXT NOT NULL,
        last_update INTEGER DEFAULT 0,
        FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_series_locations_series ON series_locations(series_id)`,
    `CREATE INDEX IF NOT EXISTS idx_series_locations_user ON series_locations(user_id)`,

    // Series Location Elements
    `CREATE TABLE IF NOT EXISTS series_location_elements (
        element_id TEXT PRIMARY KEY,
        location_id TEXT NOT NULL,
        user_id TEXT NOT NULL,
        element_name TEXT NOT NULL,
        original_name TEXT NOT NULL,
        element_description TEXT,
        last_update INTEGER DEFAULT 0,
        FOREIGN KEY (location_id) REFERENCES series_locations(loc_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_series_loc_elements_location ON series_location_elements(location_id)`,
    `CREATE INDEX IF NOT EXISTS idx_series_loc_elements_user ON series_location_elements(user_id)`,

    // Series Location Sub Elements
    `CREATE TABLE IF NOT EXISTS series_location_sub_elements (
        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,
        last_update INTEGER DEFAULT 0,
        FOREIGN KEY (element_id) REFERENCES series_location_elements(element_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_element ON series_location_sub_elements(element_id)`,
    `CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_user ON series_location_sub_elements(user_id)`,

    // Series Spells
    `CREATE TABLE IF NOT EXISTS series_spells (
        spell_id TEXT PRIMARY KEY,
        series_id TEXT NOT NULL,
        user_id TEXT NOT NULL,
        name TEXT NOT NULL,
        name_hash TEXT NOT NULL,
        description TEXT,
        appearance TEXT,
        tags TEXT,
        power_level TEXT,
        components TEXT,
        limitations TEXT,
        notes TEXT,
        last_update INTEGER DEFAULT 0,
        FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_series_spells_series ON series_spells(series_id)`,
    `CREATE INDEX IF NOT EXISTS idx_series_spells_user ON series_spells(user_id)`,

    // Series Spell Tags
    `CREATE TABLE IF NOT EXISTS series_spell_tags (
        tag_id TEXT PRIMARY KEY,
        series_id TEXT NOT NULL,
        user_id TEXT NOT NULL,
        name TEXT NOT NULL,
        hashed_name TEXT NOT NULL,
        color TEXT,
        last_update INTEGER DEFAULT 0,
        FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
    )`,
    `CREATE INDEX IF NOT EXISTS idx_series_spell_tags_series ON series_spell_tags(series_id)`,
    `CREATE INDEX IF NOT EXISTS idx_series_spell_tags_user ON series_spell_tags(user_id)`,

    // Add series_*_id columns to existing book tables (will fail silently if already exists)
    `ALTER TABLE book_characters ADD COLUMN series_character_id TEXT DEFAULT NULL`,
    `ALTER TABLE book_world ADD COLUMN series_world_id TEXT DEFAULT NULL`,
    `ALTER TABLE book_location ADD COLUMN series_location_id TEXT DEFAULT NULL`,
    `ALTER TABLE book_spells ADD COLUMN series_spell_id TEXT DEFAULT NULL`,

    // Removed Items (sync deletion tracking)
    `CREATE TABLE IF NOT EXISTS removed_items (
        removal_id TEXT PRIMARY KEY,
        table_name TEXT NOT NULL,
        entity_id TEXT NOT NULL,
        book_id TEXT,
        user_id TEXT NOT NULL,
        deleted_at INTEGER NOT NULL
    )`,
    `CREATE INDEX IF NOT EXISTS idx_removed_items_user ON removed_items(user_id)`,
    `CREATE INDEX IF NOT EXISTS idx_removed_items_book ON removed_items(book_id)`,
    `CREATE INDEX IF NOT EXISTS idx_removed_items_deleted_at ON removed_items(deleted_at)`,
    `CREATE UNIQUE INDEX IF NOT EXISTS idx_removed_items_entity ON removed_items(table_name, entity_id)`,
];

const isDev:boolean = !app.isPackaged;

function columnExists(db: Database, table: string, column: string): boolean {
    const result = db.all(`PRAGMA table_info(${table})`) as { name: string }[];
    return result?.some((row) => row.name === column) ?? false;
}

function addColumn(db: Database, table: string, column: string, type: string): void {
    if (!columnExists(db, table, column)) {
        db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${type}`);
    }
}

function getDbVersion(db: Database): number {
    const result = db.get('PRAGMA user_version') as { user_version: number } | undefined;
    return result?.user_version ?? 0;
}

function setDbVersion(db: Database, version: number): void {
    db.exec(`PRAGMA user_version = ${version}`);
}

/**
 * Check if old _schema_version table exists
 */
function hasOldSchemaTable(db: Database): boolean {
    const result = db.get(`
        SELECT name FROM sqlite_master
        WHERE type='table' AND name='_schema_version'
    `) as { name: string } | undefined;
    return !!result;
}

/**
 * Get version from old _schema_version table
 */
function getOldSchemaVersion(db: Database): number {
    try {
        const result = db.get('SELECT version FROM _schema_version LIMIT 1') as { version: number } | undefined;
        return result?.version ?? 0;
    } catch {
        return 0;
    }
}

/**
 * Migrate from old _schema_version table to PRAGMA user_version
 * Old system: v3 = all migrations done (book_tools created, NOT NULL fixes applied)
 * New system: v1 = equivalent starting point
 */
function migrateFromOldSystem(db: Database): void {
    const oldVersion = getOldSchemaVersion(db);

    // Old v3 means all previous migrations were done
    // Map to new system: old v3 = new v1
    if (oldVersion >= 3) {
        setDbVersion(db, schemaVersion);
    }

    // Add last_update column to book_tools if missing (was added after v3)
    addColumn(db, 'book_tools', 'last_update', 'INTEGER DEFAULT 0');

    // Add spells_enabled column to book_tools if missing
    addColumn(db, 'book_tools', 'spells_enabled', 'INTEGER NOT NULL DEFAULT 0');

    // Add new character fields if missing
    addColumn(db, 'book_characters', 'nickname', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_characters', 'age', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_characters', 'gender', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_characters', 'species', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_characters', 'nationality', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_characters', 'status', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_characters', 'speech_pattern', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_characters', 'catchphrase', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_characters', 'residence', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_characters', 'notes', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_characters', 'color', 'TEXT DEFAULT NULL');

    // Create book_spell_tags table if missing
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_spell_tags (
            tag_id TEXT PRIMARY KEY,
            book_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            name TEXT NOT NULL,
            name_hash TEXT NOT NULL,
            color TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_spell_tags_book ON book_spell_tags(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_spell_tags_user ON book_spell_tags(user_id)`);

    // Create book_spells table if missing
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_spells (
            spell_id TEXT PRIMARY KEY,
            book_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            name TEXT NOT NULL,
            name_hash TEXT NOT NULL,
            description TEXT,
            appearance TEXT,
            tags TEXT,
            power_level TEXT,
            components TEXT,
            limitations TEXT,
            notes TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_book ON book_spells(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_user ON book_spells(user_id)`);

    // Create series tables (v3)
    db.exec(`CREATE TABLE IF NOT EXISTS book_series (series_id TEXT PRIMARY KEY, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, description TEXT, cover_image TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (user_id) REFERENCES erit_users(user_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_book_series_user ON book_series(user_id)`);

    db.exec(`CREATE TABLE IF NOT EXISTS series_books (series_id TEXT NOT NULL, book_id TEXT NOT NULL, book_order INTEGER NOT NULL DEFAULT 1, last_update INTEGER DEFAULT 0, PRIMARY KEY (series_id, book_id), FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_books_book ON series_books(book_id)`);

    db.exec(`CREATE TABLE IF NOT EXISTS series_characters (character_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, first_name TEXT NOT NULL, last_name TEXT, nickname TEXT, age TEXT, gender TEXT, species TEXT, nationality TEXT, status TEXT, category TEXT NOT NULL, title TEXT, image TEXT, role TEXT, biography TEXT, history TEXT, speech_pattern TEXT, catchphrase TEXT, residence TEXT, notes TEXT, color TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_series ON series_characters(series_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_user ON series_characters(user_id)`);

    db.exec(`CREATE TABLE IF NOT EXISTS series_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, last_update INTEGER DEFAULT 0, FOREIGN KEY (character_id) REFERENCES series_characters(character_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_character ON series_characters_attributes(character_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_user ON series_characters_attributes(user_id)`);

    db.exec(`CREATE TABLE IF NOT EXISTS series_worlds (world_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, history TEXT, politics TEXT, economy TEXT, religion TEXT, languages TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_series ON series_worlds(series_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_user ON series_worlds(user_id)`);

    db.exec(`CREATE TABLE IF NOT EXISTS series_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, last_update INTEGER DEFAULT 0, FOREIGN KEY (world_id) REFERENCES series_worlds(world_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_world ON series_world_elements(world_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_user ON series_world_elements(user_id)`);

    db.exec(`CREATE TABLE IF NOT EXISTS series_locations (loc_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, loc_name TEXT NOT NULL, loc_original_name TEXT NOT NULL, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_series ON series_locations(series_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_user ON series_locations(user_id)`);

    db.exec(`CREATE TABLE IF NOT EXISTS series_location_elements (element_id TEXT PRIMARY KEY, location_id TEXT NOT NULL, user_id TEXT NOT NULL, element_name TEXT NOT NULL, original_name TEXT NOT NULL, element_description TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (location_id) REFERENCES series_locations(loc_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_location ON series_location_elements(location_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_user ON series_location_elements(user_id)`);

    db.exec(`CREATE TABLE IF NOT EXISTS series_location_sub_elements (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, last_update INTEGER DEFAULT 0, FOREIGN KEY (element_id) REFERENCES series_location_elements(element_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_element ON series_location_sub_elements(element_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_user ON series_location_sub_elements(user_id)`);

    db.exec(`CREATE TABLE IF NOT EXISTS series_spells (spell_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, name_hash TEXT NOT NULL, description TEXT, appearance TEXT, tags TEXT, power_level TEXT, components TEXT, limitations TEXT, notes TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_series ON series_spells(series_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_user ON series_spells(user_id)`);

    db.exec(`CREATE TABLE IF NOT EXISTS series_spell_tags (tag_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, color TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_series ON series_spell_tags(series_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_user ON series_spell_tags(user_id)`);

    // Add series_*_id columns to existing book tables (v3)
    addColumn(db, 'book_characters', 'series_character_id', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_world', 'series_world_id', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_location', 'series_location_id', 'TEXT DEFAULT NULL');
    addColumn(db, 'book_spells', 'series_spell_id', 'TEXT DEFAULT NULL');

    // Removed Items (sync deletion tracking)
    db.exec(`
        CREATE TABLE IF NOT EXISTS removed_items (
            removal_id TEXT PRIMARY KEY,
            table_name TEXT NOT NULL,
            entity_id TEXT NOT NULL,
            book_id TEXT,
            user_id TEXT NOT NULL,
            deleted_at INTEGER NOT NULL,
            removed_time INTEGER NOT NULL DEFAULT 0
        )
    `);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_removed_items_user ON removed_items(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_removed_items_book ON removed_items(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_removed_items_deleted_at ON removed_items(deleted_at)`);
    db.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_removed_items_entity ON removed_items(table_name, entity_id)`);

    // Drop old schema version table
    db.exec('DROP TABLE IF EXISTS _schema_version');
}

export function runMigrations(db: Database): void {
    // DEV: run test queries (skip errors silently)
    if (isDev && devQueries.length > 0) {
        for (const query of devQueries) {
            try {
                db.exec(query);
            } catch (_) { /* ignore */ }
        }
    }

    // PROD only: versioned migrations
    if (isDev) return;

    // Migrate from old _schema_version system to PRAGMA user_version
    if (hasOldSchemaTable(db)) {
        migrateFromOldSystem(db);
        return; // Migration done, no need to continue
    }

    const currentVersion = getDbVersion(db);
    if (currentVersion >= schemaVersion) return;

    // v1 - book_tools table + spell book tables (for fresh DBs or DBs without old system)
    if (currentVersion < 1) {
        // Book Tools
        db.exec(`
            CREATE TABLE IF NOT EXISTS book_tools (
                book_id TEXT NOT NULL,
                user_id TEXT NOT NULL,
                characters_enabled INTEGER NOT NULL DEFAULT 0,
                worlds_enabled INTEGER NOT NULL DEFAULT 0,
                locations_enabled INTEGER NOT NULL DEFAULT 0,
                spells_enabled INTEGER NOT NULL DEFAULT 0,
                last_update INTEGER DEFAULT 0,
                UNIQUE (book_id, user_id),
                FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
            );
        `);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_book_tools_book ON book_tools(book_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_book_tools_user ON book_tools(user_id)`);

        // Book Spell Tags
        db.exec(`
            CREATE TABLE IF NOT EXISTS book_spell_tags (
                tag_id TEXT PRIMARY KEY,
                book_id TEXT NOT NULL,
                user_id TEXT NOT NULL,
                name TEXT NOT NULL,
                name_hash TEXT NOT NULL,
                color TEXT,
                last_update INTEGER DEFAULT 0,
                FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
            );
        `);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_spell_tags_book ON book_spell_tags(book_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_spell_tags_user ON book_spell_tags(user_id)`);

        // Book Spells
        db.exec(`
            CREATE TABLE IF NOT EXISTS book_spells (
                spell_id TEXT PRIMARY KEY,
                book_id TEXT NOT NULL,
                user_id TEXT NOT NULL,
                name TEXT NOT NULL,
                name_hash TEXT NOT NULL,
                description TEXT,
                appearance TEXT,
                tags TEXT,
                power_level TEXT,
                components TEXT,
                limitations TEXT,
                notes TEXT,
                last_update INTEGER DEFAULT 0,
                FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
            );
        `);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_book ON book_spells(book_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_user ON book_spells(user_id)`);
    }

    // v2 - Add new character fields (nickname, age, gender, species, nationality, status, etc.)
    if (currentVersion < 2) {
        addColumn(db, 'book_characters', 'nickname', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_characters', 'age', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_characters', 'gender', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_characters', 'species', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_characters', 'nationality', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_characters', 'status', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_characters', 'speech_pattern', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_characters', 'catchphrase', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_characters', 'residence', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_characters', 'notes', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_characters', 'color', 'TEXT DEFAULT NULL');
    }

    // v3 - Add series tables and series_*_id columns to existing book tables
    if (currentVersion < 3) {
        // Create series tables first (order matters for foreign keys)

        // Book Series (main series table)
        db.exec(`CREATE TABLE IF NOT EXISTS book_series (series_id TEXT PRIMARY KEY, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, description TEXT, cover_image TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (user_id) REFERENCES erit_users(user_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_book_series_user ON book_series(user_id)`);

        // Series Books (link series to books with order)
        db.exec(`CREATE TABLE IF NOT EXISTS series_books (series_id TEXT NOT NULL, book_id TEXT NOT NULL, book_order INTEGER NOT NULL DEFAULT 1, last_update INTEGER DEFAULT 0, PRIMARY KEY (series_id, book_id), FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_books_book ON series_books(book_id)`);

        // Series Characters
        db.exec(`CREATE TABLE IF NOT EXISTS series_characters (character_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, first_name TEXT NOT NULL, last_name TEXT, nickname TEXT, age TEXT, gender TEXT, species TEXT, nationality TEXT, status TEXT, category TEXT NOT NULL, title TEXT, image TEXT, role TEXT, biography TEXT, history TEXT, speech_pattern TEXT, catchphrase TEXT, residence TEXT, notes TEXT, color TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_series ON series_characters(series_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_user ON series_characters(user_id)`);

        // Series Characters Attributes
        db.exec(`CREATE TABLE IF NOT EXISTS series_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, last_update INTEGER DEFAULT 0, FOREIGN KEY (character_id) REFERENCES series_characters(character_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_character ON series_characters_attributes(character_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_user ON series_characters_attributes(user_id)`);

        // Series Worlds
        db.exec(`CREATE TABLE IF NOT EXISTS series_worlds (world_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, history TEXT, politics TEXT, economy TEXT, religion TEXT, languages TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_series ON series_worlds(series_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_user ON series_worlds(user_id)`);

        // Series World Elements
        db.exec(`CREATE TABLE IF NOT EXISTS series_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, last_update INTEGER DEFAULT 0, FOREIGN KEY (world_id) REFERENCES series_worlds(world_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_world ON series_world_elements(world_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_user ON series_world_elements(user_id)`);

        // Series Locations
        db.exec(`CREATE TABLE IF NOT EXISTS series_locations (loc_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, loc_name TEXT NOT NULL, loc_original_name TEXT NOT NULL, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_series ON series_locations(series_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_user ON series_locations(user_id)`);

        // Series Location Elements
        db.exec(`CREATE TABLE IF NOT EXISTS series_location_elements (element_id TEXT PRIMARY KEY, location_id TEXT NOT NULL, user_id TEXT NOT NULL, element_name TEXT NOT NULL, original_name TEXT NOT NULL, element_description TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (location_id) REFERENCES series_locations(loc_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_location ON series_location_elements(location_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_user ON series_location_elements(user_id)`);

        // Series Location Sub Elements
        db.exec(`CREATE TABLE IF NOT EXISTS series_location_sub_elements (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, last_update INTEGER DEFAULT 0, FOREIGN KEY (element_id) REFERENCES series_location_elements(element_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_element ON series_location_sub_elements(element_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_user ON series_location_sub_elements(user_id)`);

        // Series Spells
        db.exec(`CREATE TABLE IF NOT EXISTS series_spells (spell_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, name_hash TEXT NOT NULL, description TEXT, appearance TEXT, tags TEXT, power_level TEXT, components TEXT, limitations TEXT, notes TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_series ON series_spells(series_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_user ON series_spells(user_id)`);

        // Series Spell Tags
        db.exec(`CREATE TABLE IF NOT EXISTS series_spell_tags (tag_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, color TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_series ON series_spell_tags(series_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_user ON series_spell_tags(user_id)`);

        // Add series_*_id columns to existing book tables
        addColumn(db, 'book_characters', 'series_character_id', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_world', 'series_world_id', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_location', 'series_location_id', 'TEXT DEFAULT NULL');
        addColumn(db, 'book_spells', 'series_spell_id', 'TEXT DEFAULT NULL');

        // Removed Items (sync deletion tracking)
        db.exec(`
            CREATE TABLE IF NOT EXISTS removed_items (
                removal_id TEXT PRIMARY KEY,
                table_name TEXT NOT NULL,
                entity_id TEXT NOT NULL,
                book_id TEXT,
                user_id TEXT NOT NULL,
                deleted_at INTEGER NOT NULL,
                removed_time INTEGER NOT NULL DEFAULT 0
            )
        `);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_removed_items_user ON removed_items(user_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_removed_items_book ON removed_items(book_id)`);
        db.exec(`CREATE INDEX IF NOT EXISTS idx_removed_items_deleted_at ON removed_items(deleted_at)`);
        db.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_removed_items_entity ON removed_items(table_name, entity_id)`);
    }

    setDbVersion(db, schemaVersion);
}

/**
 * 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');

    // 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,
            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,
            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,
            last_update INTEGER DEFAULT 0
        );
    `);

    // 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,
            last_update 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,
            last_update 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,
            last_update 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,
            words_count INTEGER NOT NULL,
            time_on_it INTEGER NOT NULL DEFAULT 0,
            last_update 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,
            goal TEXT,
            last_update 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,
            nickname TEXT,
            age TEXT,
            gender TEXT,
            species TEXT,
            nationality TEXT,
            status TEXT,
            category TEXT NOT NULL,
            title TEXT,
            image TEXT,
            role TEXT,
            biography TEXT,
            history TEXT,
            speech_pattern TEXT,
            catchphrase TEXT,
            residence TEXT,
            notes TEXT,
            color TEXT,
            series_character_id TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE,
            FOREIGN KEY (series_character_id) REFERENCES series_characters(character_id) ON DELETE SET NULL
        );
    `);

    // 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,
            last_update 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,
            last_update 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,
            atmosphere TEXT,
            writing_style TEXT,
            themes TEXT,
            symbolism TEXT,
            motifs TEXT,
            narrative_voice TEXT,
            pacing TEXT,
            intended_audience TEXT,
            key_messages TEXT,
            last_update 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,
            last_update 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,
            last_update 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,
            series_location_id TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE,
            FOREIGN KEY (series_location_id) REFERENCES series_locations(loc_id) ON DELETE SET NULL
        );
    `);

    // 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,
            last_update 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,
            series_world_id TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE,
            FOREIGN KEY (series_world_id) REFERENCES series_worlds(world_id) ON DELETE SET NULL
        );
    `);

    // 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,
            last_update 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,
            summary TEXT,
            serie_id INTEGER,
            desired_release_date TEXT,
            desired_word_count INTEGER,
            words_count INTEGER,
            cover_image TEXT,
            last_update 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
        );
    `);

    // 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,
            erite_points INTEGER NOT NULL DEFAULT 100,
            stripe_customer_id TEXT,
            credits_balance REAL 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,
            last_update 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,
            last_update 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,
            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,
            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
        );
    `);

    // Book Tools
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_tools (
            book_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            characters_enabled INTEGER NOT NULL DEFAULT 0,
            worlds_enabled INTEGER NOT NULL DEFAULT 0,
            locations_enabled INTEGER NOT NULL DEFAULT 0,
            spells_enabled INTEGER NOT NULL DEFAULT 0,
            last_update INTEGER DEFAULT 0,
            UNIQUE (book_id, user_id),
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book Spell Tags
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_spell_tags (
            tag_id TEXT PRIMARY KEY,
            book_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            name TEXT NOT NULL,
            name_hash TEXT NOT NULL,
            color TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Book Spells
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_spells (
            spell_id TEXT PRIMARY KEY,
            book_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            name TEXT NOT NULL,
            name_hash TEXT NOT NULL,
            description TEXT,
            appearance TEXT,
            tags TEXT,
            power_level TEXT,
            components TEXT,
            limitations TEXT,
            notes TEXT,
            series_spell_id TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE,
            FOREIGN KEY (series_spell_id) REFERENCES series_spells(spell_id) ON DELETE SET NULL
        );
    `);

    // =============================================================================
    // SERIES TABLES
    // =============================================================================

    // Book Series (main series table)
    db.exec(`
        CREATE TABLE IF NOT EXISTS book_series (
            series_id TEXT PRIMARY KEY,
            user_id TEXT NOT NULL,
            name TEXT NOT NULL,
            hashed_name TEXT NOT NULL,
            description TEXT,
            cover_image TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (user_id) REFERENCES erit_users(user_id) ON DELETE CASCADE
        );
    `);

    // Series Books (link series to books with order)
    db.exec(`
        CREATE TABLE IF NOT EXISTS series_books (
            series_id TEXT NOT NULL,
            book_id TEXT NOT NULL,
            book_order INTEGER NOT NULL DEFAULT 1,
            last_update INTEGER DEFAULT 0,
            PRIMARY KEY (series_id, book_id),
            FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE,
            FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
        );
    `);

    // Series Characters
    db.exec(`
        CREATE TABLE IF NOT EXISTS series_characters (
            character_id TEXT PRIMARY KEY,
            series_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            first_name TEXT NOT NULL,
            last_name TEXT,
            nickname TEXT,
            age TEXT,
            gender TEXT,
            species TEXT,
            nationality TEXT,
            status TEXT,
            category TEXT NOT NULL,
            title TEXT,
            image TEXT,
            role TEXT,
            biography TEXT,
            history TEXT,
            speech_pattern TEXT,
            catchphrase TEXT,
            residence TEXT,
            notes TEXT,
            color TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
        );
    `);

    // Series Characters Attributes
    db.exec(`
        CREATE TABLE IF NOT EXISTS series_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,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (character_id) REFERENCES series_characters(character_id) ON DELETE CASCADE
        );
    `);

    // Series Worlds
    db.exec(`
        CREATE TABLE IF NOT EXISTS series_worlds (
            world_id TEXT PRIMARY KEY,
            series_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            name TEXT NOT NULL,
            hashed_name TEXT NOT NULL,
            history TEXT,
            politics TEXT,
            economy TEXT,
            religion TEXT,
            languages TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
        );
    `);

    // Series World Elements
    db.exec(`
        CREATE TABLE IF NOT EXISTS series_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,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (world_id) REFERENCES series_worlds(world_id) ON DELETE CASCADE
        );
    `);

    // Series Locations
    db.exec(`
        CREATE TABLE IF NOT EXISTS series_locations (
            loc_id TEXT PRIMARY KEY,
            series_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            loc_name TEXT NOT NULL,
            loc_original_name TEXT NOT NULL,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
        );
    `);

    // Series Location Elements
    db.exec(`
        CREATE TABLE IF NOT EXISTS series_location_elements (
            element_id TEXT PRIMARY KEY,
            location_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            element_name TEXT NOT NULL,
            original_name TEXT NOT NULL,
            element_description TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (location_id) REFERENCES series_locations(loc_id) ON DELETE CASCADE
        );
    `);

    // Series Location Sub Elements
    db.exec(`
        CREATE TABLE IF NOT EXISTS series_location_sub_elements (
            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,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (element_id) REFERENCES series_location_elements(element_id) ON DELETE CASCADE
        );
    `);

    // Series Spells
    db.exec(`
        CREATE TABLE IF NOT EXISTS series_spells (
            spell_id TEXT PRIMARY KEY,
            series_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            name TEXT NOT NULL,
            name_hash TEXT NOT NULL,
            description TEXT,
            appearance TEXT,
            tags TEXT,
            power_level TEXT,
            components TEXT,
            limitations TEXT,
            notes TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
        );
    `);

    // Series Spell Tags
    db.exec(`
        CREATE TABLE IF NOT EXISTS series_spell_tags (
            tag_id TEXT PRIMARY KEY,
            series_id TEXT NOT NULL,
            user_id TEXT NOT NULL,
            name TEXT NOT NULL,
            hashed_name TEXT NOT NULL,
            color TEXT,
            last_update INTEGER DEFAULT 0,
            FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
        );
    `);

    // Removed Items (sync deletion tracking)
    db.exec(`
        CREATE TABLE IF NOT EXISTS removed_items (
            removal_id TEXT PRIMARY KEY,
            table_name TEXT NOT NULL,
            entity_id TEXT NOT NULL,
            book_id TEXT,
            user_id TEXT NOT NULL,
            deleted_at INTEGER NOT NULL,
            removed_time INTEGER NOT NULL DEFAULT 0
        )
    `);

    // Create indexes for better performance
    createIndexes(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)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_ai_conversations_user ON ai_conversations(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_ai_messages_conversation ON ai_messages_history(conversation_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_chapters_book ON book_chapters(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_chapter_content_chapter ON book_chapter_content(chapter_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_characters_book ON book_characters(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_character_attrs_character ON book_characters_attributes(character_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_world_book ON book_world(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_world_elements_world ON book_world_elements(world_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_book_tools_book ON book_tools(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_book_tools_user ON book_tools(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_spell_tags_book ON book_spell_tags(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_spell_tags_user ON book_spell_tags(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_book ON book_spells(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_user ON book_spells(user_id)`);

    // Series tables indexes
    db.exec(`CREATE INDEX IF NOT EXISTS idx_book_series_user ON book_series(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_books_book ON series_books(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_series ON series_characters(series_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_user ON series_characters(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_character ON series_characters_attributes(character_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_user ON series_characters_attributes(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_series ON series_worlds(series_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_user ON series_worlds(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_world ON series_world_elements(world_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_user ON series_world_elements(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_series ON series_locations(series_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_user ON series_locations(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_location ON series_location_elements(location_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_user ON series_location_elements(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_element ON series_location_sub_elements(element_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_user ON series_location_sub_elements(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_series ON series_spells(series_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_user ON series_spells(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_series ON series_spell_tags(series_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_user ON series_spell_tags(user_id)`);
    // Removed items indexes
    db.exec(`CREATE INDEX IF NOT EXISTS idx_removed_items_user ON removed_items(user_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_removed_items_book ON removed_items(book_id)`);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_removed_items_deleted_at ON removed_items(deleted_at)`);
    db.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_removed_items_entity ON removed_items(table_name, entity_id)`);
}

/**
 * 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 { name: string }[];

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

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

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