local addonName, ns = ...
-- ApiVault Reports workflow panel for AppShell. Added in v1.3.5 Interface Clarity Phase 4.
-- Copyable report hub only. No runtime source file reads and no protected/secure execution.
local ApiVault = ns

ApiVault.ReportsPanel = ApiVault.ReportsPanel or {}
local Panel = ApiVault.ReportsPanel

local function trim(value)
    value = tostring(value or "")
    return (value:gsub("^%s+", ""):gsub("%s+$", ""))
end

local function append(lines, value)
    table.insert(lines, tostring(value or ""))
end

local function createText(parent, template)
    local fs = parent:CreateFontString(nil, "OVERLAY", template or "GameFontNormal")
    fs:SetJustifyH("LEFT")
    fs:SetJustifyV("TOP")
    return fs
end

local function createBackdropFrame(name, parent)
    return CreateFrame("Frame", name, parent, BackdropTemplateMixin and "BackdropTemplate" or nil)
end

local function setBackdrop(frame)
    if not frame.SetBackdrop then return end
    frame:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true,
        tileSize = 16,
        edgeSize = 12,
        insets = { left = 4, right = 4, top = 4, bottom = 4 },
    })
    frame:SetBackdropColor(0.02, 0.02, 0.03, 0.86)
end

local function createButton(parent, label, width, anchor, x, y, onClick)
    local button = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
    button:SetSize(width or 100, 22)
    if anchor and anchor.GetObjectType then
        button:SetPoint("LEFT", anchor, "RIGHT", x or 6, y or 0)
    else
        button:SetPoint("TOPLEFT", parent, "TOPLEFT", x or 20, y or -20)
    end
    button:SetText(label)
    button:SetScript("OnClick", onClick)
    return button
end

function Panel:Clear(parent)
    if parent.ApiVaultReportsChildren then
        for _, child in ipairs(parent.ApiVaultReportsChildren) do
            if child.Hide then child:Hide() end
            if child.SetParent then child:SetParent(nil) end
        end
    end
    parent.ApiVaultReportsChildren = {}
end

function Panel:Add(parent, child)
    parent.ApiVaultReportsChildren = parent.ApiVaultReportsChildren or {}
    table.insert(parent.ApiVaultReportsChildren, child)
    return child
end

function Panel:GetInput()
    return trim(self.input and self.input:GetText() or "")
end

function Panel:SetOutput(text)
    if self.output then
        if ApiVault.CapOutputText then text = ApiVault:CapOutputText(text) end
        self.output:SetText(tostring(text or ""))
        self.output:SetCursorPosition(0)
    end
end

function Panel:EmptyState()
    if ApiVault.EmptyState and ApiVault.EmptyState.Build then
        return ApiVault.EmptyState:Build("Reports V2", {
            "Copyable report hub for session exports, addon reports, error reports, audit output and developer checklists.",
            "Policy badges: [COPYABLE] [READ-ONLY] [INSPECT-ONLY] [NO-RUNTIME-FILE-READS]",
        }, {
            "No report type has been selected yet.",
            "Some report modules may be unavailable depending on TOC load order.",
        }, {
            "Type an addon name or filter when needed.",
            "Click Session Export, Addon Report, Error Report or a checklist button.",
            "Use Select Output, then Ctrl+C to copy.",
        })
    end
    return "Reports V2\n\nSelect a report type."
end

function Panel:BuildSessionExport()
    if ApiVault.DeveloperSessionExport and ApiVault.DeveloperSessionExport.BuildReport then
        return ApiVault.DeveloperSessionExport:BuildReport()
    end
    return "Session export unavailable."
end

local function formatIntegrationSummary(query)
    local lines = {}
    query = tostring(query or "")
    append(lines, "")
    append(lines, "ApiVault Integration Status")
    append(lines, "===========================")
    if query == "" then
        append(lines, "No addon selected.")
        return table.concat(lines, "\n")
    end
    local dev = ApiVault.DeveloperAPI and ApiVault.DeveloperAPI.GetAddonRecord and ApiVault.DeveloperAPI:GetAddonRecord(query) or nil
    if dev then
        append(lines, "integrated: yes")
        append(lines, "registered: " .. tostring(dev.registered))
        append(lines, "lastActivity: " .. tostring(dev.lastActivity or ""))
        append(lines, "available callbacks/data:")
        append(lines, "  status reports: " .. tostring(#(dev.statuses or {})))
        append(lines, "  SavedVariables reports: " .. tostring(#(dev.savedVariables or {})))
        append(lines, "  self-tests: " .. tostring(#(dev.selfTests or {})))
        append(lines, "  custom reports/snapshots: " .. tostring(#(dev.debugSnapshots or {})))
        append(lines, "  pending requests: " .. tostring(select(2, ApiVault.DeveloperAPI:GetRequestStats(query))))
    else
        append(lines, "integrated: no")
        append(lines, "available without integration:")
        append(lines, "  runtime metadata: yes, if the addon is installed/enabled")
        append(lines, "  SavedVariables declarations: only if detectable through runtime metadata; not authoritative")
        append(lines, "  Bug Reporter errors: yes, if captured this session or imported read-only")
        append(lines, "unavailable without integration:")
        append(lines, "  custom reports")
        append(lines, "  self-tests")
        append(lines, "  status callbacks")
        append(lines, "  SavedVariables status reports")
        append(lines, "integration instruction:")
        append(lines, "  copy ApiVault/Integrations/ApiVaultAddonShim.lua into the addon and add it near the end of the .toc")
        append(lines, "  no Lua edits are required; the shim is zero-config and ships standard callbacks")
    end
    return table.concat(lines, "\n")
end

function Panel:BuildAddonReport()
    local query = self:GetInput()
    if query == "" then
        return "No addon context.\n\nType an addon name such as StockVault, then click Addon Report."
    end
    local text
    if ApiVault.AddonLookup and ApiVault.AddonLookup.FormatAddonReport then
        text = ApiVault.AddonLookup:FormatAddonReport(query)
    else
        text = "Addon lookup unavailable."
    end
    return tostring(text or "") .. "\n" .. formatIntegrationSummary(query)
end

function Panel:BuildErrorReport()
    local filter = self:GetInput()
    local lines = {}
    append(lines, "ApiVault Error Report")
    append(lines, "=====================")
    append(lines, "Badges: [LIVE] [READ-ONLY] [ERROR-INBOX]")
    append(lines, "filter: " .. tostring(filter ~= "" and filter or "<all>"))
    append(lines, "")
    if ApiVault.ErrorInbox and ApiVault.ErrorInbox.FormatBugReporterList then
        append(lines, ApiVault.ErrorInbox:FormatBugReporterList(filter))
    elseif ApiVault.ErrorInbox and ApiVault.ErrorInbox.FormatList then
        append(lines, ApiVault.ErrorInbox:FormatList(filter))
    else
        append(lines, "Error Inbox unavailable.")
    end
    local record = ApiVault.ErrorInbox and ApiVault.ErrorInbox.GetLatestMatch and ApiVault.ErrorInbox:GetLatestMatch(filter) or nil
    if record and ApiVault.ErrorInbox and ApiVault.ErrorInbox.Explain then
        append(lines, "")
        append(lines, "------------------------------")
        append(lines, ApiVault.ErrorInbox:Explain(record))
        if ApiVault.ErrorInbox.CopyReport then
            append(lines, "")
            append(lines, "------------------------------")
            append(lines, ApiVault.ErrorInbox:CopyReport(record, "github"))
            append(lines, "")
            append(lines, "------------------------------")
            append(lines, ApiVault.ErrorInbox:CopyReport(record, "curseforge"))
        elseif ApiVault.ErrorInbox.CopyGitHubIssue then
            append(lines, "")
            append(lines, "------------------------------")
            append(lines, ApiVault.ErrorInbox:CopyGitHubIssue(record))
        end
    else
        append(lines, "")
        append(lines, "No matching error explanation available.")
        append(lines, "Possible reasons: no captured errors, filter mismatch, or bridge loaded after the error occurred.")
    end
    return table.concat(lines, "\n")
end

function Panel:BuildBugReporterSummary()
    local filter = self:GetInput()
    if ApiVault.ErrorInbox and ApiVault.ErrorInbox.FormatBugReporterSummary then
        return ApiVault.ErrorInbox:FormatBugReporterSummary(filter)
    elseif ApiVault.ErrorInbox and ApiVault.ErrorInbox.FormatBugReporterList then
        return ApiVault.ErrorInbox:FormatBugReporterList(filter)
    end
    return "Bug Reporter summary unavailable."
end

function Panel:BuildSelectedErrorExport()
    local filter = self:GetInput()
    local record
    if ApiVault.BugReporterPanelV2 and ApiVault.BugReporterPanelV2.selectedId and ApiVault.ErrorInbox and ApiVault.ErrorInbox.GetErrorById then
        record = ApiVault.ErrorInbox:GetErrorById(ApiVault.BugReporterPanelV2.selectedId)
    end
    if not record and ApiVault.ErrorInbox and ApiVault.ErrorInbox.GetLatestMatch then
        record = ApiVault.ErrorInbox:GetLatestMatch(filter)
    end
    if not record then
        return "No selected/latest matching error available. Type a filter or open /av errors and select an error first."
    end
    if ApiVault.ErrorInbox and ApiVault.ErrorInbox.CopyReport then
        return ApiVault.ErrorInbox:CopyReport(record, "markdown")
    end
    return self:BuildErrorReport()
end

function Panel:BuildFullDeveloperReport()
    local lines = {}
    append(lines, "ApiVault Full Developer Report")
    append(lines, "==============================")
    append(lines, "Version: " .. tostring(ApiVault.version or "unknown"))
    append(lines, "Interface: " .. tostring(ApiVault.interface or "unknown"))
    if ApiVault.GetClientBuildText then append(lines, "Client: " .. tostring(ApiVault:GetClientBuildText())) end
    append(lines, "")
    append(lines, "## Session")
    append(lines, self:BuildSessionExport())
    append(lines, "")
    append(lines, "## Bug Reporter")
    append(lines, self:BuildBugReporterSummary())
    append(lines, "")
    append(lines, "## Selected/latest error")
    append(lines, self:BuildSelectedErrorExport())
    append(lines, "")
    append(lines, "## UI Stability")
    if ApiVault.UIStability and ApiVault.UIStability.FormatStatus then
        append(lines, ApiVault.UIStability:FormatStatus())
    else
        append(lines, "UIStability status unavailable.")
    end
    local text = table.concat(lines, "\n")
    if ApiVault.CapOutputText then text = ApiVault:CapOutputText(text) end
    return text
end

function Panel:BuildLastAudit()
    if ApiVault.AddonAudit and ApiVault.AddonAudit.GetLastReportText then
        return ApiVault.AddonAudit:GetLastReportText()
    end
    return "No AddonAudit report available. Run /av audit first, paste code, and click Auto Detect."
end

function Panel:BuildChecklist(kind)
    if ApiVault.ChecklistExport and ApiVault.ChecklistExport.Build then
        return ApiVault.ChecklistExport:Build(kind)
    end
    return "Checklist export unavailable."
end

function Panel:BuildTaintChecklist()
    local text = self:GetInput()
    if text ~= "" and ApiVault.TaintCombatSafetyAssistant and ApiVault.TaintCombatSafetyAssistant.FormatReport then
        return ApiVault.TaintCombatSafetyAssistant:FormatReport(text)
    end
    return self:BuildChecklist("secure-checklist")
end

function Panel:BuildPackageReport()
    local text = self:GetInput()
    if text ~= "" and ApiVault.AddonPackageValidator and ApiVault.AddonPackageValidator.FormatReport then
        return ApiVault.AddonPackageValidator:FormatReport(text)
    end
    return self:BuildChecklist("toc-checklist")
end

function Panel:Run(kind)
    if kind == "session" then
        self:SetOutput(self:BuildSessionExport())
    elseif kind == "addon" then
        self:SetOutput(self:BuildAddonReport())
    elseif kind == "error" then
        self:SetOutput(self:BuildErrorReport())
    elseif kind == "bug-summary" then
        self:SetOutput(self:BuildBugReporterSummary())
    elseif kind == "selected-error" then
        self:SetOutput(self:BuildSelectedErrorExport())
    elseif kind == "full-dev" then
        self:SetOutput(self:BuildFullDeveloperReport())
    elseif kind == "last-audit" then
        self:SetOutput(self:BuildLastAudit())
    elseif kind == "api-summary" then
        self:SetOutput(self:BuildChecklist("api-summary"))
    elseif kind == "secure-checklist" then
        self:SetOutput(self:BuildTaintChecklist())
    elseif kind == "package" then
        self:SetOutput(self:BuildPackageReport())
    elseif kind == "test-checklist" then
        self:SetOutput(self:BuildChecklist("test-checklist"))
    else
        self:SetOutput(self:EmptyState())
    end
end

function Panel:SelectOutput()
    if self.output then
        self.output:SetFocus()
        self.output:HighlightText()
    end
end

function Panel:OpenLegacyExport()
    if ApiVault.ExportPanel and ApiVault.ExportPanel.OpenWithContext then
        ApiVault.ExportPanel:OpenWithContext(nil, "test-checklist")
        self:SetOutput("[LEGACY PANEL]\nOpened the standalone Export panel.\n\nReports V2 remains the primary cockpit workflow for /av reports.")
    elseif ApiVault.DeveloperMustHaveToolsPanel and ApiVault.DeveloperMustHaveToolsPanel.Open then
        ApiVault.DeveloperMustHaveToolsPanel:Open("export")
        self:SetOutput("[LEGACY PANEL]\nOpened Developer Tools session export fallback.")
    else
        self:SetOutput("Legacy export panel unavailable.")
    end
end

function Panel:Render(parent)
    self:Clear(parent)

    if ApiVault.Header and ApiVault.Header.Render then
        ApiVault.Header:Render(self, parent, "Reports V2", "Copyable report hub for session exports, addon reports, error reports, audit output and developer checklists.", {"COPYABLE", "READ-ONLY", "INSPECT-ONLY", "NO-RUNTIME-FILE-READS"})
    else
        local title = self:Add(parent, createText(parent, "GameFontHighlightLarge"))
        title:SetPoint("TOPLEFT", parent, "TOPLEFT", 20, -18)
        title:SetText("Reports V2")
    end

    local input = self:Add(parent, CreateFrame("EditBox", nil, parent, "InputBoxTemplate"))
    self.input = input
    input:SetSize(360, 24)
    input:SetPoint("TOPLEFT", parent, "TOPLEFT", 20, -90)
    input:SetAutoFocus(false)
    input:SetText("")
    input:SetScript("OnEnterPressed", function(box)
        box:ClearFocus()
        Panel:Run("addon")
    end)

    local session = self:Add(parent, createButton(parent, "Session Export", 116, input, 10, 0, function() Panel:Run("session") end))
    local addon = self:Add(parent, createButton(parent, "Addon Report", 108, session, 6, 0, function() Panel:Run("addon") end))
    local errorReport = self:Add(parent, createButton(parent, "Error Report", 104, addon, 6, 0, function() Panel:Run("error") end))
    local bugSummary = self:Add(parent, createButton(parent, "Bug Summary", 104, errorReport, 6, 0, function() Panel:Run("bug-summary") end))

    local selectedError = self:Add(parent, createButton(parent, "Selected Error", 116, nil, 20, -124, function() Panel:Run("selected-error") end))
    local fullDev = self:Add(parent, createButton(parent, "Full Dev Report", 120, selectedError, 6, 0, function() Panel:Run("full-dev") end))
    local lastAudit = self:Add(parent, createButton(parent, "Last Audit", 90, fullDev, 6, 0, function() Panel:Run("last-audit") end))
    local apiSummary = self:Add(parent, createButton(parent, "API Summary", 104, lastAudit, 6, 0, function() Panel:Run("api-summary") end))
    local secure = self:Add(parent, createButton(parent, "Secure Checklist", 124, apiSummary, 6, 0, function() Panel:Run("secure-checklist") end))
    local package = self:Add(parent, createButton(parent, "Package", 82, secure, 6, 0, function() Panel:Run("package") end))
    local test = self:Add(parent, createButton(parent, "Test Checklist", 114, package, 6, 0, function() Panel:Run("test-checklist") end))

    local selectOut = self:Add(parent, createButton(parent, "Select Output", 108, nil, 20, -154, function() Panel:SelectOutput() end))
    local clear = self:Add(parent, createButton(parent, "Clear", 70, selectOut, 6, 0, function() input:SetText(""); Panel:SetOutput(Panel:EmptyState()) end))
    self:Add(parent, createButton(parent, "Legacy Export", 108, clear, 6, 0, function() Panel:OpenLegacyExport() end))

    local bg = self:Add(parent, createBackdropFrame(nil, parent))
    bg:SetPoint("TOPLEFT", parent, "TOPLEFT", 20, -190)
    bg:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", -20, 20)
    setBackdrop(bg)

    local scroll = self:Add(parent, CreateFrame("ScrollFrame", nil, bg, "UIPanelScrollFrameTemplate"))
    scroll:SetPoint("TOPLEFT", bg, "TOPLEFT", 12, -12)
    scroll:SetPoint("BOTTOMRIGHT", bg, "BOTTOMRIGHT", -30, 12)

    local output = self:Add(parent, CreateFrame("EditBox", nil, scroll))
    self.output = output
    output:SetMultiLine(true)
    output:SetAutoFocus(false)
    output:SetFontObject(ChatFontNormal)
    output:SetWidth(720)
    output:SetText(self:EmptyState())
    output:SetScript("OnEscapePressed", function(box) box:ClearFocus() end)
    scroll:SetScrollChild(output)

    parent:SetScript("OnSizeChanged", function()
        if output and bg then output:SetWidth(math.max(520, bg:GetWidth() - 50)) end
    end)
end
