-- ══════════════════════════════════════════════════════════════════════════════
-- KILLERPORTRAIT.LUA — Killer-NPC 3D-Portrait für Death-Overlay
-- Modul: KillerPortrait | Interface: 11508
--
-- Features:
--   • Zeigt animiertes 3D-Modell des Killers im Death-Popup
--   • Nutzt DNL's source_id (NPC CreatureID) für ModelScene:SetCreature()
--   • Für eigenen Tod: PlayerModel zeigt eigenen Charakter
--   • Graceful fallback: Klassen-Icon wenn kein 3D-Modell verfügbar
--   • Leichte Rotation-Animation (kontinuierlich)
-- ══════════════════════════════════════════════════════════════════════════════

local addonName, addon = ...
local GDL = _G["GuildDeathLog"]

-- ── Modul ─────────────────────────────────────────────────────────────────────
local KillerPortrait = {}
GDL:RegisterModule("KillerPortrait", KillerPortrait)

-- ── Shared Frame-Pool (ModelScene ist teuer — wiederverwenden) ────────────────
local _modelFrame    = nil   -- Das Eine ModelScene-Frame (Singleton)
local _playerModel   = nil   -- PlayerModel für eigenen Charakter-Preview
local _rotTicker     = nil   -- Rotations-Ticker
local _currentYaw    = 0

local ROT_SPEED      = 0.008  -- Radiant pro Frame (~0.5°/Frame)
local DEFAULT_ZOOM   = 4.5

-- ── ModelScene erstellen ──────────────────────────────────────────────────────
local function CreateModelScene(parent)
    -- Versuche ModelScene (bevorzugt, hat bessere Kamera-Kontrolle)
    local ok, frame = pcall(CreateFrame, "ModelScene", "GDLKillerModelScene", parent)
    if ok and frame then
        frame:SetSize(160, 200)
        -- Kamera-Setup
        local cameraId = frame.GetNumActiveCameras and frame:GetNumActiveCameras() or 0
        return frame, "modelscene"
    end

    -- Fallback: DressUpModel (hat SetCreature)
    local ok2, dressup = pcall(CreateFrame, "DressUpModel", "GDLKillerModel", parent)
    if ok2 and dressup then
        dressup:SetSize(160, 200)
        return dressup, "dressup"
    end

    return nil, nil
end

-- ── Fallback-Portrait: Klassen-Icon ──────────────────────────────────────────
local function ShowClassIconFallback(parent, classId, x, y, size)
    local icons = {
        [1]  = "Interface\\Icons\\ClassIcon_Warrior",
        [2]  = "Interface\\Icons\\ClassIcon_Paladin",
        [3]  = "Interface\\Icons\\ClassIcon_Hunter",
        [4]  = "Interface\\Icons\\ClassIcon_Rogue",
        [5]  = "Interface\\Icons\\ClassIcon_Priest",
        [7]  = "Interface\\Icons\\ClassIcon_Shaman",
        [8]  = "Interface\\Icons\\ClassIcon_Mage",
        [9]  = "Interface\\Icons\\ClassIcon_Warlock",
        [11] = "Interface\\Icons\\ClassIcon_Druid",
    }
    local tex = parent:CreateTexture(nil, "ARTWORK")
    tex:SetSize(size or 64, size or 64)
    tex:SetPoint("TOPLEFT", parent, "TOPLEFT", x or 10, y or -10)
    tex:SetTexture(icons[classId] or "Interface\\Icons\\INV_Misc_QuestionMark")
    tex:SetTexCoord(0.08, 0.92, 0.08, 0.92)
    return tex
end

-- ── NPC-Modell anzeigen ───────────────────────────────────────────────────────
function KillerPortrait:ShowNPC(parent, creatureId, point, relPoint, offX, offY)
    if not creatureId or creatureId == 0 then return false end

    -- ModelScene initialisieren
    if not _modelFrame then
        _modelFrame, _modelType = CreateModelScene(parent)
    end

    if not _modelFrame then return false end

    _modelFrame:SetParent(parent)
    _modelFrame:ClearAllPoints()
    _modelFrame:SetPoint(point or "TOPLEFT", parent, relPoint or "TOPLEFT", offX or 0, offY or 0)
    _modelFrame:SetSize(160, 200)

    -- Kreatur-Modell setzen
    local success = false
    if _modelFrame.SetCreature then
        local ok = pcall(function()
            _modelFrame:SetCreature(creatureId)
            success = true
        end)
        if not ok then success = false end
    end

    if success then
        -- Kamera-Zoom
        if _modelFrame.SetCameraDistance then
            _modelFrame:SetCameraDistance(DEFAULT_ZOOM)
        elseif _modelFrame.SetRotation then
            _modelFrame:SetRotation(0)
        end

        -- Rotations-Ticker starten
        if _rotTicker then _rotTicker:Cancel() end
        _currentYaw = 0
        _rotTicker = C_Timer.NewTicker(0.033, function()
            _currentYaw = _currentYaw + ROT_SPEED
            if _currentYaw > (2 * math.pi) then _currentYaw = 0 end
            if _modelFrame and _modelFrame.SetRotation then
                pcall(_modelFrame.SetRotation, _modelFrame, _currentYaw)
            end
        end)

        _modelFrame:Show()
        return true
    end

    _modelFrame:Hide()
    return false
end

-- ── Eigenen Charakter anzeigen (bei eigenem Tod) ──────────────────────────────
function KillerPortrait:ShowPlayer(parent, point, relPoint, offX, offY)
    if not _playerModel then
        local ok, pm = pcall(CreateFrame, "PlayerModel", "GDLPlayerPortrait", parent)
        if ok and pm then
            _playerModel = pm
            _playerModel:SetSize(160, 200)
        end
    end

    if not _playerModel then return false end

    _playerModel:SetParent(parent)
    _playerModel:ClearAllPoints()
    _playerModel:SetPoint(point or "TOPLEFT", parent, relPoint or "TOPLEFT", offX or 0, offY or 0)

    local ok = pcall(function()
        _playerModel:SetUnit("player")
        _playerModel:SetRotation(math.pi)   -- Von vorne
        _playerModel:SetCameraDistance(DEFAULT_ZOOM)
    end)

    if ok then
        _playerModel:Show()
        return true
    end
    return false
end

-- ── Cleanup ───────────────────────────────────────────────────────────────────
function KillerPortrait:Hide()
    if _rotTicker then
        _rotTicker:Cancel()
        _rotTicker = nil
    end
    if _modelFrame then _modelFrame:Hide() end
    if _playerModel then _playerModel:Hide() end
end

-- ── Death-Overlay Integration ─────────────────────────────────────────────────
-- Wird aus UIOverlay.lua:ShowOverlay() aufgerufen
-- Gibt den genutzten Frame zurück (nil wenn Fallback auf Icon)
function KillerPortrait:AttachToOverlay(overlayFrame, deathData)
    local db = GuildDeathLogDB
    if not (db and db.settings and db.settings.killer3DPortrait ~= false) then
        return nil  -- opt-out
    end

    if deathData.isSelf then
        -- Eigener Tod: eigenes Charakter-Modell
        local ok = KillerPortrait:ShowPlayer(overlayFrame, "RIGHT", "RIGHT", -10, 20)
        if ok then return _playerModel end
    elseif deathData.killerId and deathData.killerId > 0 then
        -- Killer-NPC-Modell
        local ok = KillerPortrait:ShowNPC(overlayFrame, deathData.killerId, "RIGHT", "RIGHT", -10, 20)
        if ok then return _modelFrame end
    end

    -- Fallback: Klassen-Icon rechts oben im Overlay
    if deathData.classId then
        return ShowClassIconFallback(overlayFrame, deathData.classId, -80, -10, 64)
    end

    return nil
end

-- ── Debuff/Stat-Info unter Portrait ──────────────────────────────────────────
-- Zeigt Killer-Name + NPC-Typ unter dem 3D-Modell
function KillerPortrait:AddKillerLabel(overlayFrame, deathData)
    if not deathData then return end

    local killer = deathData.killer or "Unbekannt"
    local killerId = deathData.killerId

    local label = overlayFrame:CreateFontString(nil, "OVERLAY")
    label:SetFont("Fonts\\FRIZQT__.TTF", 10, "OUTLINE")
    label:SetTextColor(0.9, 0.3, 0.1)
    label:SetShadowOffset(1, -1)
    label:SetShadowColor(0, 0, 0, 1)
    label:SetPoint("BOTTOMRIGHT", overlayFrame, "BOTTOMRIGHT", -8, 8)
    label:SetJustifyH("CENTER")

    if killerId and killerId > 0 then
        label:SetText(string.format("☠ %s\n|cff888888#%d|r", killer, killerId))
    else
        label:SetText(string.format("☠ %s", killer))
    end

    return label
end

-- ── Glow-Effekt für Killer-Bereich ────────────────────────────────────────────
function KillerPortrait:AddGlowBorder(overlayFrame, r, g, b)
    r, g, b = r or 0.8, g or 0.1, b or 0.0

    local glow = overlayFrame:CreateTexture(nil, "BACKGROUND", nil, -1)
    glow:SetPoint("TOPRIGHT", overlayFrame, "TOPRIGHT", 0, 0)
    glow:SetSize(180, 240)
    glow:SetTexture("Interface\\SpellActivationOverlay\\IconAlert")
    glow:SetBlendMode("ADD")
    glow:SetVertexColor(r, g, b, 0.3)

    -- Puls-Animation
    local ag = glow:CreateAnimationGroup()
    ag:SetLooping("BOUNCE")
    local alpha = ag:CreateAnimation("Alpha")
    alpha:SetFromAlpha(0.15)
    alpha:SetToAlpha(0.45)
    alpha:SetDuration(1.2)
    alpha:SetSmoothing("IN_OUT")
    ag:Play()

    return glow
end

-- ── Settings-Default ──────────────────────────────────────────────────────────
function KillerPortrait:Initialize()
    if KillerPortrait._initialized then return end
    KillerPortrait._initialized = true
    C_Timer.After(0.5, function()
        local db = GuildDeathLogDB
        if db and db.settings and db.settings.killer3DPortrait == nil then
            db.settings.killer3DPortrait = true   -- default an
        end
    end)
end

KillerPortrait:Initialize()
