
const { entrypoints, storage } = require("uxp");

const _id = Symbol("_id");
const _root = Symbol("_root");
const _attachment = Symbol("_attachment");
const _menuItems = Symbol("_menuItems");

function getLocalFileSystem() {
    return storage.localFileSystem;
}

function getEntryPath(entry) {
    if (!entry) {
        return "";
    }
    if (typeof entry.path === "string" && entry.path.trim()) {
        return entry.path;
    }
    if (typeof entry.nativePath === "string" && entry.nativePath.trim()) {
        return entry.nativePath;
    }
    if (typeof entry.url === "string" && entry.url.trim()) {
        return entry.url;
    }
    return "";
}

async function ensureDirectoryByPath(localFileSystem, preferredPath) {
    const normalizedPath = typeof preferredPath === "string" ? preferredPath.trim() : "";
    if (!normalizedPath || typeof localFileSystem.getEntryWithUrl !== "function") {
        return null;
    }
    try {
        return await localFileSystem.getEntryWithUrl(normalizedPath);
    } catch (error) {
        console.warn("[sdpppX gallery] getEntryWithUrl failed", error);
        return null;
    }
}

async function ensureDefaultGalleryDirectory(localFileSystem, folderName) {
    const parentFactories = [localFileSystem.getDataFolder, localFileSystem.getTemporaryFolder];
    for (const factory of parentFactories) {
        if (typeof factory !== "function") {
            continue;
        }
        try {
            const parent = await factory.call(localFileSystem);
            if (!parent || typeof parent.createFolder !== "function") {
                continue;
            }
            const entry = await parent.createFolder(folderName, { overwrite: false }).catch(async () => {
                if (typeof parent.getEntry === "function") {
                    return await parent.getEntry(folderName).catch(() => null);
                }
                return null;
            });
            if (entry) {
                return entry;
            }
        } catch (error) {
            console.warn("[sdpppX gallery] create default gallery folder failed", error);
        }
    }
    return null;
}

async function resolveGalleryDirectory({ preferredPath, folderName }) {
    const localFileSystem = getLocalFileSystem();
    const existing = await ensureDirectoryByPath(localFileSystem, preferredPath);
    if (existing) {
        return existing;
    }
    return await ensureDefaultGalleryDirectory(localFileSystem, folderName || "sdppp-gallery");
}

function getDateFolderName(date = new Date()) {
    const year = String(date.getFullYear());
    const month = String(date.getMonth() + 1).padStart(2, "0");
    const day = String(date.getDate()).padStart(2, "0");
    return `${year}-${month}-${day}`;
}

async function ensureChildFolder(parent, folderName) {
    if (!parent || typeof parent.createFolder !== "function") {
        return null;
    }
    try {
        return await parent.createFolder(folderName, { overwrite: false });
    } catch (error) {
        if (typeof parent.getEntry === "function") {
            return await parent.getEntry(folderName).catch(() => null);
        }
        console.warn("[sdpppX gallery] create child folder failed", error);
        return null;
    }
}

async function getDatedGalleryDirectory(directory, targetDateFolder) {
    const dateFolderName = typeof targetDateFolder === "string" && targetDateFolder.trim() ? targetDateFolder.trim() : getDateFolderName();
    const datedDirectory = await ensureChildFolder(directory, dateFolderName);
    return datedDirectory || directory;
}

async function deleteEntryIfPossible(entry) {
    if (!entry || typeof entry.delete !== "function") {
        return;
    }
    try {
        await entry.delete();
    } catch (error) {
        console.warn("[sdpppX gallery] delete old asset failed", error);
    }
}

async function writeGalleryDataUrl({ dataUrl, fileName, preferredPath, folderName }) {
    if (typeof dataUrl !== "string" || !dataUrl.trim()) {
        return { ok: false, error: "图片数据为空" };
    }

    const directory = await resolveGalleryDirectory({ preferredPath, folderName });
    if (!directory || typeof directory.createFile !== "function") {
        return { ok: false, error: "图库目录不可写" };
    }

    const targetDirectory = await getDatedGalleryDirectory(directory, getDateFolderName());
    if (!targetDirectory || typeof targetDirectory.createFile !== "function") {
        return { ok: false, error: "日期图库目录不可写" };
    }

    const targetFileName = typeof fileName === "string" && fileName.trim() ? fileName.trim() : `gallery-${Date.now()}.png`;
    const fileEntry = await targetDirectory.createFile(targetFileName, { overwrite: true });
    if (!fileEntry || typeof fileEntry.write !== "function") {
        return { ok: false, error: "无法写入图库文件" };
    }

    await fileEntry.write(dataUrl, { append: false });
    return {
        ok: true,
        assetFileUri: getEntryPath(fileEntry),
        assetFileName: fileEntry.name || targetFileName,
        galleryPath: getEntryPath(targetDirectory),
    };
}

async function moveGalleryAssetToDateFolder({ assetFileUri, preferredPath, folderName, targetDateFolder }) {
    const normalizedPath = typeof assetFileUri === "string" ? assetFileUri.trim() : "";
    if (!normalizedPath) {
        return { ok: false, error: "图库文件路径为空" };
    }

    const localFileSystem = getLocalFileSystem();
    if (typeof localFileSystem.getEntryWithUrl !== "function") {
        return { ok: false, error: "无法访问图库文件" };
    }

    try {
        const sourceEntry = await localFileSystem.getEntryWithUrl(normalizedPath);
        if (!sourceEntry || typeof sourceEntry.read !== "function") {
            return { ok: false, error: "图库文件不存在" };
        }

        const directory = await resolveGalleryDirectory({ preferredPath, folderName });
        if (!directory) {
            return { ok: false, error: "图库目录不可用" };
        }

        const targetDirectory = await getDatedGalleryDirectory(directory, targetDateFolder);
        if (!targetDirectory || typeof targetDirectory.createFile !== "function") {
            return { ok: false, error: "目标日期目录不可写" };
        }

        const nextFileName = sourceEntry.name || `gallery-${Date.now()}.png`;
        const nextFileEntry = await targetDirectory.createFile(nextFileName, { overwrite: true });
        if (!nextFileEntry || typeof nextFileEntry.write !== "function") {
            return { ok: false, error: "无法写入目标日期目录" };
        }

        const dataUrl = await sourceEntry.read();
        await nextFileEntry.write(dataUrl, { append: false });
        await deleteEntryIfPossible(sourceEntry);

        return {
            ok: true,
            moved: true,
            assetFileUri: getEntryPath(nextFileEntry),
            assetFileName: nextFileEntry.name || nextFileName,
            galleryPath: getEntryPath(targetDirectory),
        };
    } catch (error) {
        return { ok: false, error: error instanceof Error ? error.message : String(error) };
    }
}

async function readGalleryDataUrl({ assetFileUri }) {
    const normalizedPath = typeof assetFileUri === "string" ? assetFileUri.trim() : "";
    if (!normalizedPath) {
        return { ok: false, error: "图库文件路径为空" };
    }

    const localFileSystem = getLocalFileSystem();
    if (typeof localFileSystem.getEntryWithUrl !== "function") {
        return { ok: false, error: "无法读取图库文件" };
    }

    try {
        const entry = await localFileSystem.getEntryWithUrl(normalizedPath);
        if (!entry || typeof entry.read !== "function") {
            return { ok: false, error: "图库文件不存在" };
        }
        const dataUrl = await entry.read();
        return typeof dataUrl === "string"
            ? { ok: true, dataUrl }
            : { ok: false, error: "图库文件内容无效" };
    } catch (error) {
        return { ok: false, error: error instanceof Error ? error.message : String(error) };
    }
}

class PanelController {
    constructor({ id, menuItems } = {}) {
        this[_id] = null;
        this[_root] = null;
        this[_attachment] = null;
        this[_menuItems] = [];

        this[_id] = id;
        this[_menuItems] = menuItems || [];
        this.menuItems = this[_menuItems].map(menuItem => ({
            id: menuItem.id,
            label: menuItem.label,
            enabled: menuItem.enabled || true,
            checked: menuItem.checked || false
        }));

        ["create", "show", "hide", "destroy", "invokeMenu"].forEach(fn => this[fn] = this[fn].bind(this));
    }

    create() {
        this[_root] = document.getElementById("root");
        this[_root].style.overflowY = "hidden";
        this[_root].style.overflowX = "hidden";

        globalThis.sdpppX.__start__(this[_root]);

        return this[_root];
    }

    show(event) {
        if (!this[_root]) this.create();
        this[_attachment] = event;
    }

    hide() {
        if (this[_attachment] && this[_root]) {
            this[_attachment].removeChild(this[_root]);
            this[_attachment] = null;
        }
    }

    destroy() { }

    invokeMenu(id) {
        const menuItem = this[_menuItems].find(c => c.id === id);
        if (menuItem) {
            const handler = menuItem.oninvoke;
            if (handler) {
                handler();
            }
        }
    }
}

entrypoints.setup({
    plugin: {
        create(plugin) {
        },
        destroy() {
        }
    },
    panels: {
        'sd-ppp': new PanelController({
            id: "sd-ppp", menuItems: [
                {
                    id: "sd-ppp-log",
                    label: "查看日志",
                    enabled: true,
                    checked: false,
                    oninvoke: async () => {
                        const logContent = globalThis.sdpppX.__getLogs__().join('\n');
                        
                        try {
                            const localFileSystem = storage.localFileSystem;
                            const pluginDataFolder = await localFileSystem.getTemporaryFolder();
                            const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
                            const logFileName = `sdppp-log-${timestamp}.txt`;
                            const logFile = await pluginDataFolder.createFile(`${logFileName}`, { type: "file", overwrite: true});
                            
                            alert(`日志已保存到文件: ${logFile.nativePath}\n\n\n`);
                            await logFile.write(logContent, {append: false});
                        } catch (error) {
                            console.error('写入日志文件失败:', error);
                        }
                    }
                }
            ]
        }),
    }
});
