const fs = require('fs');
const path = require('path');
const os = require('os');
const cheerio = require("cheerio");
const { queryAll, run } = require('./database');
const { scrape } = require("./headless");

const extensions = new Map();

async function loadExtensions() {
    const homeDir = os.homedir();
    const extensionsDir = path.join(homeDir, 'WaifuBoards', 'extensions');

    if (!fs.existsSync(extensionsDir)) {
        console.log("📁 Extensions directory not found, creating...");
        fs.mkdirSync(extensionsDir, { recursive: true });
    }

    try {
        const files = await fs.promises.readdir(extensionsDir);

        for (const file of files) {
            if (file.endsWith('.js')) {
                await loadExtension(file);
            }
        }

        console.log(`✅ Loaded ${extensions.size} extensions`);

        try {
            const loaded = Array.from(extensions.keys());
            const rows = await queryAll("SELECT DISTINCT ext_name FROM extension");

            for (const row of rows) {
                if (!loaded.includes(row.ext_name)) {
                    console.log(`🧹 Cleaning cached metadata for removed extension: ${row.ext_name}`);
                    await run("DELETE FROM extension WHERE ext_name = ?", [row.ext_name]);
                }
            }
        } catch (err) {
            console.error("❌ Error cleaning extension cache:", err);
        }

    } catch (err) {
        console.error("❌ Extension Scan Error:", err);
    }
}

async function loadExtension(fileName) {
    const homeDir = os.homedir();
    const extensionsDir = path.join(homeDir, 'WaifuBoards', 'extensions');
    const filePath = path.join(extensionsDir, fileName);

    if (!fs.existsSync(filePath)) {
        console.warn(`⚠️ Extension not found: ${fileName}`);
        return;
    }

    try {
        delete require.cache[require.resolve(filePath)];

        const ExtensionClass = require(filePath);

        const instance = typeof ExtensionClass === 'function'
            ? new ExtensionClass()
            : (ExtensionClass.default ? new ExtensionClass.default() : null);

        if (!instance) {
            console.warn(`⚠️ Invalid extension: ${fileName}`);
            return;
        }

        if (!["anime-board", "book-board", "image-board"].includes(instance.type)) {
            console.warn(`⚠️ Invalid extension (${instance.type}): ${fileName}`);
            return;
        }

        const name = instance.constructor.name;
        instance.__fileName = fileName;
        instance.scrape = scrape;
        instance.cheerio = cheerio;
        extensions.set(name, instance);

        console.log(`📦 Installed & loaded: ${name}`);
        return name;

    } catch (err) {
        console.warn(`⚠️ Error loading ${fileName}: ${err.message}`);
    }
}

const https = require('https');

async function saveExtensionFile(fileName, downloadUrl) {
    const homeDir = os.homedir();
    const extensionsDir = path.join(homeDir, 'WaifuBoards', 'extensions');
    const filePath = path.join(extensionsDir, fileName);
    const fullUrl = downloadUrl;

    if (!fs.existsSync(extensionsDir)) {
        fs.mkdirSync(extensionsDir, { recursive: true });
    }

    return new Promise((resolve, reject) => {
        const file = fs.createWriteStream(filePath);

        https.get(fullUrl, async (response) => {
            if (response.statusCode !== 200) {
                return reject(new Error(`Download failed: ${response.statusCode}`));
            }

            response.pipe(file);

            file.on('finish', async () => {
                file.close(async () => {
                    try {
                        const extName = fileName.replace('.js', '');

                        for (const key of extensions.keys()) {
                            if (key.toLowerCase() === extName.toLowerCase()) {
                                extensions.delete(key);
                                break;
                            }
                        }
                        await loadExtension(fileName);
                        resolve();
                    } catch (err) {
                        if (fs.existsSync(filePath)) {
                            await fs.promises.unlink(filePath);
                        }
                        reject(new Error(`Load failed, file rolled back: ${err.message}`));
                    }
                });
            });
        }).on('error', async (err) => {
            if (fs.existsSync(filePath)) {
                await fs.promises.unlink(filePath);
            }
            reject(err);
        });
    });
}

async function deleteExtensionFile(fileName) {
    const homeDir = os.homedir();
    const extensionsDir = path.join(homeDir, 'WaifuBoards', 'extensions');
    const filePath = path.join(extensionsDir, fileName);

    const extName = fileName.replace(".js", "");

    for (const key of extensions.keys()) {
        if (key.toLowerCase() === extName) {
            extensions.delete(key);
            console.log(`🗑️  Removed from memory: ${key}`);
            break;
        }
    }

    if (fs.existsSync(filePath)) {
        await fs.promises.unlink(filePath);
        console.log(`🗑️  Deleted file: ${fileName}`);
    }
}

function getExtension(name) {
    return extensions.get(name);
}

function getAllExtensions() {
    return extensions;
}

function getExtensionsList() {
    return Array.from(extensions.keys());
}

function getAnimeExtensionsMap() {
    const animeExts = new Map();
    for (const [name, ext] of extensions) {
        if (ext.type === 'anime-board') {
            animeExts.set(name, ext);
        }
    }
    return animeExts;
}

function getBookExtensionsMap() {
    const bookExts = new Map();
    for (const [name, ext] of extensions) {
        if (ext.type === 'book-board' || ext.type === 'manga-board') {
            bookExts.set(name, ext);
        }
    }
    return bookExts;
}

function getGalleryExtensionsMap() {
    const galleryExts = new Map();
    for (const [name, ext] of extensions) {
        if (ext.type === 'image-board') {
            galleryExts.set(name, ext);
        }
    }
    return galleryExts;
}

module.exports = {
    loadExtensions,
    getExtension,
    getAllExtensions,
    getExtensionsList,
    getAnimeExtensionsMap,
    getBookExtensionsMap,
    getGalleryExtensionsMap,
    saveExtensionFile,
    deleteExtensionFile
};