const BLOG_ROOT_ID = "__BLOG_ROOT_ID__";
const UNPUBLISHED_ROOT_ID = "__UNPUBLISHED_ROOT_ID__";
const BLOG_GENERATOR_ID = "__BLOG_GENERATOR_ID__";

const entity = api.originEntity;
if (!entity) return;

function findOrCreateChild(parentId, title, iconClass) {
    const parent = api.getNote(parentId);
    let child = parent.getChildNotes().find(n => n.title === title);
    if (!child) {
        const created = api.createTextNote(parentId, title, "");
        child = created.note ? created.note : created;
        if (iconClass) child.setLabel("iconClass", iconClass);
        child.save();
        return { noteId: child.noteId, created: true };
    }
    if (child.hasLabel("blogCategory") && iconClass && child.getLabelValue("iconClass") !== iconClass) {
        child.setLabel("iconClass", iconClass);
        child.save();
    }
    return { noteId: child.noteId, created: false };
}

function mirrorPath(note, sourceRootId, targetRootId) {
    const chain = [];
    let current = note;
    let guard = 0;
    while (current && guard++ < 20) {
        const parents = current.getParentNotes().filter(p => p.noteId === sourceRootId || p.hasAncestor(sourceRootId));
        if (parents.length === 0) break;
        const parent = parents[0];
        if (parent.noteId === sourceRootId) break;
        chain.unshift(parent);
        current = parent;
    }
    let target = targetRootId;
    const createdIds = [];
    for (const folder of chain) {
        const res = findOrCreateChild(target, folder.title, folder.getLabelValue("iconClass"));
        if (res.created) createdIds.push(res.noteId);
        target = res.noteId;
    }
    return { target, createdIds };
}

function blogParentsOf(note) {
    return note.getParentNotes().filter(p => p.noteId === BLOG_ROOT_ID || p.hasAncestor(BLOG_ROOT_ID));
}

function runGenerator() {
    const gen = api.getNote(BLOG_GENERATOR_ID);
    if (gen) gen.executeScript();
}

function slugify(s) {
    return String(s).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
}

function ensureAlias(note) {
    if (note.getLabelValue("shareAlias")) return;
    const base = slugify(note.title) || "post";
    let alias = base;
    let i = 2;
    while (api.getNotesWithLabel("shareAlias", alias).some(n => n.noteId !== note.noteId)) {
        alias = base + "-" + i++;
    }
    note.setLabel("shareAlias", alias);
    note.save();
    api.log("blog_publish_manager: assigned shareAlias '" + alias + "' to '" + note.title + "'");
}

if (entity.type === "label" && entity.name === "publish") {
    const note = api.getNote(entity.noteId);
    if (!note) return;

    const isPublished = note.getLabelValue("publish") === "true";
    if (isPublished) ensureAlias(note);
    const underBlog = note.hasAncestor(BLOG_ROOT_ID);
    const underUnpublished = note.hasAncestor(UNPUBLISHED_ROOT_ID);

    if (isPublished && underUnpublished && !underBlog) {
        const res = mirrorPath(note, UNPUBLISHED_ROOT_ID, BLOG_ROOT_ID);
        api.ensureNoteIsPresentInParent(note.noteId, res.target);
        for (const id of res.createdIds) {
            api.getNote(id).setLabel("blogCategory", "");
        }
        api.log("blog_publish_manager: cloned note '" + note.title + "' to blog");
        runGenerator();
    } else if (!isPublished && underBlog) {
        if (underUnpublished) {
            for (const p of blogParentsOf(note)) {
                api.ensureNoteIsAbsentFromParent(note.noteId, p.noteId);
            }
            api.log("blog_publish_manager: removed clone of '" + note.title + "' from blog");
        } else {
            const res = mirrorPath(note, BLOG_ROOT_ID, UNPUBLISHED_ROOT_ID);
            api.ensureNoteIsPresentInParent(note.noteId, res.target);
            for (const p of blogParentsOf(note)) {
                api.ensureNoteIsAbsentFromParent(note.noteId, p.noteId);
            }
            api.log("blog_publish_manager: moved note '" + note.title + "' back to unpublished");
        }
        runGenerator();
    }
}