--- Shamelessly stolen from https://github.com/rmgpanw/quarto-obsidian-template thanks rmgpanw
--- Pandoc Lua filter for Obsidian-Quarto compatibility.
--- 1. Converts [[wikilinks]] to standard markdown links.
--- 2. Merges Obsidian `tags` into Quarto `categories` for the listing page.
--- Runs at render time inside Pandoc; source files are never mutated.

--- Merge tags into categories so Obsidian tags appear on Quarto listing pages.
function Meta(meta)
    if meta.tags then
        local cats = meta.categories or pandoc.MetaList({})
        -- Collect existing categories for deduplication
        local seen = {}
        for _, c in ipairs(cats) do
            seen[pandoc.utils.stringify(c)] = true
        end
        for _, t in ipairs(meta.tags) do
            local val = pandoc.utils.stringify(t)
            if not seen[val] then
                cats[#cats + 1] = t
                seen[val] = true
            end
        end
        meta.categories = cats
        return meta
    end
end

function Str(el)
    -- Match wikilinks with alias: [[target|display]]
    local target, display = el.text:match("^%[%[(.-)%|(.-)%]%]$")
    if target and display then
        local url = resolve_target(target)
        return pandoc.Link(display, url)
    end

    -- Match plain wikilinks: [[target]]
    target = el.text:match("^%[%[(.-)%]%]$")
    if target then
        local url = resolve_target(target)
        return pandoc.Link(target, url)
    end

    return nil
end

function Inlines(inlines)
    local result = pandoc.List()
    local i = 1
    while i <= #inlines do
        -- Look for a sequence starting with Str("[[")
        if inlines[i].t == "Str" and inlines[i].text:match("^%[%[") then
            -- Collect all elements until we find one ending with "]]"
            local parts = { inlines[i].text }
            local j = i + 1
            local found_end = inlines[i].text:match("%]%]$") ~= nil

            if not found_end then
                while j <= #inlines do
                    if inlines[j].t == "Str" then
                        parts[#parts + 1] = inlines[j].text
                        if inlines[j].text:match("%]%]$") then
                            found_end = true
                            j = j + 1
                            break
                        end
                    elseif inlines[j].t == "Space" or inlines[j].t == "SoftBreak" then
                        parts[#parts + 1] = " "
                    else
                        -- Non-text element breaks the wikilink sequence
                        break
                    end
                    j = j + 1
                end
            end

            if found_end then
                local combined = table.concat(parts)
                -- Try alias syntax first
                local target, display = combined:match("^%[%[(.-)%|(.-)%]%]$")
                if target and display then
                    result:insert(pandoc.Link(display, resolve_target(target)))
                    i = j
                else
                    target = combined:match("^%[%[(.-)%]%]$")
                    if target then
                        result:insert(pandoc.Link(target, resolve_target(target)))
                        i = j
                    else
                        result:insert(inlines[i])
                        i = i + 1
                    end
                end
            else
                result:insert(inlines[i])
                i = i + 1
            end
        else
            result:insert(inlines[i])
            i = i + 1
        end
    end
    return result
end

function resolve_target(target)
    -- If target already has an extension, use it as-is
    if target:match("%.[%a]+$") then
        return target
    end
    -- Append .html so links work regardless of source extension (.md or .qmd)
    return target .. ".html"
end
