-- LrShutdownPlugin hook.  Runs when the plugin is being
-- disabled, reloaded, or removed via Plug-in Manager, and on
-- LR quit.  Cleans up the external helper process and any
-- leftover IPC scratch state so we don't orphan resources.
--
-- The top-level code of this file runs OUTSIDE any LrTasks
-- context.  `LrTasks.execute` and the yielding `LrFileUtils`
-- operations (file iteration, delete) cannot run here
-- directly — they yield, and yielding outside a task errors
-- with "We can only wait from within a task."  Prior version
-- wrapped the body in pcall hoping to catch that; pcall
-- doesn't actually catch yield errors in Lua 5.1, so the
-- wrap was cosmetic and cleanup silently never ran.  The
-- user-visible consequence was a zombie helper surviving
-- every LR quit/reload.  See bugs.md
-- "Shutdown cleanup errors..." entry and CLAUDE.md on
-- pcall + yielding.
--
-- Wrapping the work in an LrTasks.startAsyncTask gives it a
-- task context.  Caveat: LR does not guarantee it will wait
-- for spawned tasks before unloading the plugin, so this
-- cleanup is best-effort.  In the worst case — LR yanks the
-- rug before the task runs — the helper survives to the next
-- launch, where Launcher.start's startup probe notices it's
-- alive and attaches (no duplicate spawn, no lost work).
-- The process eventually gets reaped either by the next
-- Close Everything click or the user's terminal.

local LrTasks = import 'LrTasks'
local LrFileUtils = import 'LrFileUtils'
local LrPathUtils = import 'LrPathUtils'

local Log = require 'Log'
local Platform = require 'Platform'
local Launcher = require 'Launcher'

Log.line('shutdown', 'LrShutdownPlugin fired')

LrTasks.startAsyncTask(function()
    -- Port-based kill: works for both compiled-binary and
    -- `go run` paths, and cross-platform via Platform.
    -- Pull the port from Launcher so we don't drift from the
    -- canonical value (Shutdown previously hardcoded the
    -- literal and would have silently missed a port change).
    local port = Launcher.HELPER_PORT
    LrTasks.execute(Platform.killByPortCmd(port))
    Log.line('shutdown', 'helper killed (by port)', tostring(port))

    -- Portable file cleanup through the LR SDK.  No shell-
    -- specific rm / del.  Missing files are no-ops.
    for _, name in ipairs({
        'helper.stdout', 'helper.log', 'heartbeat.json',
    }) do
        LrFileUtils.delete(LrPathUtils.child(
            Platform.scratchRoot, name))
    end
    -- req-*.json / resp-*.json: glob via LrFileUtils.files
    -- iterator (portable) and delete matches.
    if LrFileUtils.exists(Platform.scratchRoot) then
        for path in LrFileUtils.files(Platform.scratchRoot) do
            local leaf = LrPathUtils.leafName(path)
            if leaf:match('^req%-') or leaf:match('^resp%-') then
                LrFileUtils.delete(path)
            end
        end
    end
    Log.line('shutdown', 'cleanup complete')
end)
