const sqlite3 = require('sqlite3').verbose();
const os = require("os");
const path = require("path");
const fs = require("fs");
const {ensureUserDataDB, ensureAnilistSchema, ensureExtensionsTable, ensureCacheTable, ensureFavoritesDB, ensureLocalLibrarySchema } = require('./schemas');

const databases = new Map();

const DEFAULT_PATHS = {
    anilist: path.join(os.homedir(), "WaifuBoards", 'anilist_anime.db'),
    favorites: path.join(os.homedir(), "WaifuBoards", "favorites.db"),
    cache: path.join(os.homedir(), "WaifuBoards", "cache.db"),
    userdata: path.join(os.homedir(), "WaifuBoards", "user_data.db"),
    local_library: path.join(os.homedir(), "WaifuBoards", "local_library.db")
};

function initDatabase(name = 'anilist', dbPath = null, readOnly = false) {
    if (databases.has(name)) {
        return databases.get(name);
    }

    const finalPath = dbPath || DEFAULT_PATHS[name] || DEFAULT_PATHS.anilist;

    if (name === "favorites") {
        ensureFavoritesDB(finalPath)
            .catch(err => console.error("Error creando favorites:", err));
    }

    if (name === "cache") {
        const dir = path.dirname(finalPath);
        if (!fs.existsSync(dir)) {
            fs.mkdirSync(dir, { recursive: true });
        }
    }

    if (name === "userdata") {
        ensureUserDataDB(finalPath)
            .catch(err => console.error("Error creando userdata:", err));
    }

    const mode = readOnly ? sqlite3.OPEN_READONLY : (sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE);

    const db = new sqlite3.Database(finalPath, mode, (err) => {
        if (err) {
            console.error(`Database Error (${name}):`, err.message);
        } else {
            console.log(`Connected to ${name} database at ${finalPath}`);
        }
    });

    databases.set(name, db);

    if (name === "local_library") {
        ensureLocalLibrarySchema(db)
            .catch(err => console.error("Error creating local library schema:", err));
    }

    if (name === "anilist") {
        ensureAnilistSchema(db)
            .then(() => ensureExtensionsTable(db))
            .catch(err => console.error("Error creating anilist schema:", err));
    }

    if (name === "cache") {
        ensureCacheTable(db)
            .catch(err => console.error("Error creating cache table:", err));
    }

    return db;
}

function getDatabase(name = 'anilist') {
    if (!databases.has(name)) {
        const readOnly = (name === 'anilist');
        return initDatabase(name, null, readOnly);
    }
    return databases.get(name);
}

function queryOne(sql, params = [], dbName = 'anilist') {
    return new Promise((resolve, reject) => {
        getDatabase(dbName).get(sql, params, (err, row) => {
            if (err) reject(err);
            else resolve(row);
        });
    });
}

function queryAll(sql, params = [], dbName = 'anilist') {
    return new Promise((resolve, reject) => {
        getDatabase(dbName).all(sql, params, (err, rows) => {
            if (err) reject(err);
            else resolve(rows || []);
        });
    });
}

function run(sql, params = [], dbName = 'anilist') {
    return new Promise((resolve, reject) => {
        getDatabase(dbName).run(sql, params, function(err) {
            if (err) reject(err);
            else resolve({ changes: this.changes, lastID: this.lastID });
        });
    });
}

function closeDatabase(name = null) {
    if (name) {
        const db = databases.get(name);
        if (db) {
            db.close();
            databases.delete(name);
            console.log(`Closed ${name} database`);
        }
    } else {
        for (const [dbName, db] of databases) {
            db.close();
            console.log(`Closed ${dbName} database`);
        }
        databases.clear();
    }
}

module.exports = {
    initDatabase,
    getDatabase,
    queryOne,
    queryAll,
    run,
    closeDatabase
};