import { createElectronStorageAdapter } from './storageAdapter';
// Lazy-load Node.js modules using require() for Electron renderer compatibility
let os = null;
let path = null;
let pathToFileURL = null;
let nodeFsPromises = null;
const ensureNodeModules = () => {
    if (os && path && pathToFileURL && nodeFsPromises) {
        return;
    }
    if (typeof window === 'undefined' || typeof window.require !== 'function') {
        throw new Error('Node.js modules are not available. Ensure nodeIntegration is enabled in Electron.');
    }
    const req = window.require;
    os = req('node:os');
    path = req('node:path');
    const urlModule = req('node:url');
    pathToFileURL = urlModule.pathToFileURL;
    nodeFsPromises = req('node:fs/promises');
};
const uploadAttachment = async (payload) => {
    const { sourceUrl } = await persistAttachment(payload);
    return { sourceUrl };
};
export const attachmentCallbackHandler = async (payload) => {
    return uploadAttachment(payload);
};
let storageAdapter = null;
const getStorageAdapter = () => {
    if (!storageAdapter) {
        storageAdapter = createElectronStorageAdapter();
    }
    return storageAdapter;
};
export const electronStorage = {
    createAdapter: createElectronStorageAdapter,
    get adapter() {
        return getStorageAdapter();
    },
    attachmentCallbackHandler
};
let cachedFsPromises = null;
let storageDirPromise = null;
const LOG_PREFIX = '[electron-storage]';
const getRendererRequire = () => {
    if (typeof window !== 'undefined' && typeof window.require === 'function') {
        return window.require;
    }
    return null;
};
const getFsPromises = () => {
    ensureNodeModules();
    if (nodeFsPromises && typeof nodeFsPromises.mkdir === 'function') {
        return nodeFsPromises;
    }
    if (!cachedFsPromises) {
        const rendererRequire = getRendererRequire();
        if (!rendererRequire) {
            throw new Error('fs/promises is not available in this renderer environment');
        }
        cachedFsPromises = rendererRequire('node:fs/promises');
    }
    return cachedFsPromises;
};
const collectHomeDirCandidates = () => {
    ensureNodeModules();
    const results = [];
    const insert = (value) => {
        if (value && typeof value === 'string' && value.trim().length > 0) {
            results.push(value);
        }
    };
    try {
        if (typeof os.homedir === 'function') {
            insert(os.homedir());
        }
    }
    catch (error) {
        console.debug(LOG_PREFIX, 'os.homedir() failed', error);
    }
    if (typeof process !== 'undefined' && process.env) {
        insert(process.env.HOME);
        insert(process.env.USERPROFILE);
        const homedrive = process.env.HOMEDRIVE;
        const homepath = process.env.HOMEPATH;
        if (homedrive && homepath) {
            insert(path.join(homedrive, homepath));
        }
    }
    if (typeof window !== 'undefined') {
        const override = window.__MCP_HOME_DIR__;
        if (typeof override === 'string') {
            insert(override);
        }
    }
    return results;
};
const resolveDefaultStorageDir = () => {
    ensureNodeModules();
    const candidates = collectHomeDirCandidates();
    const baseDir = candidates.find((candidate) => candidate !== '/' && candidate !== '.');
    if (baseDir) {
        return path.join(baseDir, '.mcp-desktop', 'files');
    }
    let cwdFallback = '.';
    if (typeof process !== 'undefined' && typeof process.cwd === 'function') {
        try {
            cwdFallback = process.cwd();
        }
        catch (error) {
            console.debug(LOG_PREFIX, 'process.cwd() failed', error);
        }
    }
    return path.resolve(cwdFallback, '.mcp-desktop', 'files');
};
const ensureStorageDirectory = async () => {
    ensureNodeModules();
    if (!storageDirPromise) {
        storageDirPromise = (async () => {
            const fs = getFsPromises();
            const storageDir = path.resolve(resolveDefaultStorageDir());
            await fs.mkdir(storageDir, { recursive: true });
            return storageDir;
        })().catch((error) => {
            storageDirPromise = null;
            throw error;
        });
    }
    return storageDirPromise;
};
const persistAttachment = async (payload) => {
    ensureNodeModules();
    const fs = getFsPromises();
    const storageDir = await ensureStorageDirectory();
    const buffer = extractPayloadBuffer(payload);
    if (payload.size && payload.size !== buffer.length) {
        throw new Error('Uploaded file size does not match declared size');
    }
    const fileId = sanitizeComponent(payload.id);
    const fileName = sanitizeFileName(payload.name);
    const fileDir = path.join(storageDir, fileId);
    await fs.mkdir(fileDir, { recursive: true });
    const filePath = safeJoin(fileDir, fileName);
    await fs.writeFile(filePath, buffer);
    const metadata = {
        mimeType: payload.mimeType,
        originalName: payload.name,
        size: buffer.length,
        uploadedAt: new Date().toISOString()
    };
    await fs.writeFile(`${filePath}.meta.json`, JSON.stringify(metadata, null, 2));
    const sourceUrl = pathToFileURL(filePath).toString();
    return { sourceUrl };
};
const extractPayloadBuffer = (payload) => {
    if (payload.dataUrl) {
        return decodeDataUrl(payload.dataUrl);
    }
    throw new Error('Attachment payload is missing dataUrl data');
};
const decodeDataUrl = (dataUrl) => {
    const [, base64Data] = dataUrl.split(',');
    if (!base64Data) {
        throw new Error('Invalid dataUrl payload');
    }
    return Buffer.from(base64Data, 'base64');
};
const sanitizeComponent = (value) => {
    return value.replace(/[^a-zA-Z0-9-_]/g, '_');
};
const sanitizeFileName = (value) => {
    const normalized = value.replace(/\\/g, '/').split('/').pop() ?? 'file';
    return normalized.replace(/[^a-zA-Z0-9._-]/g, '_');
};
const safeJoin = (base, target) => {
    ensureNodeModules();
    const resolved = path.resolve(base, target);
    if (!resolved.startsWith(base)) {
        throw new Error('Invalid file path');
    }
    return resolved;
};
