# GermanysAllStar - AI Agent Rules & Best Practices

## ⚠️ WICHTIG: Diese Datei VOR JEDER ÄNDERUNG lesen!

Diese Datei enthält alle wichtigen Regeln, Strukturen und Best Practices für die Entwicklung dieses WoW-Addons.
**Jeder AI-Agent MUSS diese Datei lesen, bevor Code-Änderungen vorgenommen werden.**

Für eine vollständige Architektur-Analyse und Roadmap siehe: `ARCHITECTURE_AUDIT.md`

---

## 📁 Projektstruktur

### Core-System
- `Core/Bootstrap.lua` - Addon-Initialisierung (minimal: Events, Slash-Commands, Init-Sequenz)
- `Core/Utilities.lua` - Zentrale Hilfsfunktionen (ParseItemID, SafeInt, Debug, GetGuildInfo, etc.)
- `Core/Permissions.lua` - Zugriffskontrolle (AmIOfficer, HasAppAccess, SetPermission, etc.)
- `Core/VersionControl.lua` - Versionsverwaltung und Sync-Berechtigungen
- `Core/UI/` - **ZENTRALES UI-SYSTEM** (siehe unten)

### Netzwerk / Sync-System
- `Core/NetworkManager.lua` - **ZENTRALER SYNC-ORCHESTRATOR** (siehe unten)
- `Core/NetworkAdapter_Hub.lua` - Hub-Adapter (Posts, Comments, Reactions, Deletes)
- `Core/NetworkAdapter_RaidPlanner.lua` - Raidplaner-Adapter (Raids, Signups, Deletes)
- `Core/NetworkAdapter_GuildStock.lua` - GSP-Adapter (Recipes, Enchants, Bank, Logs)
- `Core/NetworkAdapter_VersionControl.lua` - VC-Adapter (Versions-Broadcast)
- `Core/NetworkAdapter_Permissions.lua` - Permissions-Adapter (Zugriffs-Sync)

### Module
- `Modules/Raidplaner/` - Raidplaner (Kalender, Anmeldungen, Planner)
- `Modules/GuildStockPlanner/` - Rezeptverwaltung, Enchants, Farm-Liste
- `Modules/GuildStocks/` - Read-only Bestandsübersicht

### SavedVariables (3 getrennte)
- `GermanysAllStarDB` - Hub-Daten (Posts, Permissions, UI-Scale, Versions)
- `GuildStockPlannerDB` - GSP-Daten (Rezepte, Enchants, Bank, Logs)
- `GermanysAllStarRaidplanerDB` - Raidplaner-Daten (Raids, Signups, eigene SV seit v2.1)

---

## 🌐 Netzwerk-System (ZENTRAL & VERBINDLICH)

### ⚠️ KRITISCH: Immer den NetworkManager nutzen!

**NIEMALS** direkt `C_ChatInfo.SendAddonMessage()` aufrufen!
**NIEMALS** eigene `CHAT_MSG_ADDON`-Listener oder Send-Queues erstellen!
**IMMER** den zentralen `NetworkManager` über die Adapter nutzen.

### Architektur

```
          ┌──────────────┐
          │ NetworkManager│  Ein OnUpdate (Send), Ein CHAT_MSG_ADDON (Receive)
          └──────┬───────┘
     ┌───────┬───┼───┬──────────┐
     │       │   │   │          │
  Hub-Adap. RP-Adap. GSP-Adap. VC-Adap.  Perm-Adap.
     │       │   │   │          │
  Hub/Sync  RP/Sync GSP/Sync  VC.lua    Permissions
  (Facade)  (Facade) (Facade)
```

### Nachrichten senden (über Adapter)

```lua
-- RICHTIG: Live-Update über den NetworkManager senden
local NM = ADDON.NetworkManager
NM:QueueAdapterLiveUpsert("hub", "post", postData)     -- Live-Upsert
NM:QueueAdapterLiveDelete("hub", "postDelete", postId, time()) -- Live-Delete

-- RICHTIG: Modul-Wire über Adapter queuen
NM:QueueModuleWire("hub", "live", wireBody)             -- GUILD broadcast
NM:QueueModuleWire("hub", "full", wireBody, nil, target) -- WHISPER an target

-- FALSCH: Direkt senden
C_ChatInfo.SendAddonMessage("GASHUB", data, "GUILD")  -- ❌ NIEMALS!
```

### Sync-Regeln

1. **Live-Updates** → Einzelnachricht via `GUILD` (für alle sichtbar)
2. **Full-Sync** → Via `WHISPER` an den anfragenden Spieler (nicht GUILD-Broadcast!)
3. **HELLO** → Leichtgewichtiger Fingerprint-Vergleich via `GUILD` (alle 5 Min.)
4. **SYNC_OK** → Bestätigung nach Full-Sync via `GUILD` (für Rück-Sync bei Mismatch)
5. **Tombstones** → Immer im Full-Sync mitsenden (bidirektionale Propagation!)

### Neuen Adapter erstellen (Muster)

```lua
local _, ADDON = ...
local NM = ADDON.NetworkManager

local MyAdapter = {}
MyAdapter.moduleKey = "mymodule"
MyAdapter.prefix    = "MYPREFIX"

-- NMDebug: Modul-spezifischer Debug-Wrapper
local function NMDebug(...)
    if ADDON.Debug then ADDON:Debug("[MyModule]", ...) end
end

-- Helper: NM-Exporte nutzen, NICHT lokal duplizieren
local function MyName() return NM.MyName() end
local function StripRealm(name) return NM.StripRealm(name) end

-- Pflicht: BuildHelloWire, DecodeLegacyMessage, QueueFullSync
function MyAdapter:BuildHelloWire(opts)
    return "HI:" .. fingerprint .. ":" .. timestamp
end

function MyAdapter:DecodeLegacyMessage(stripped, sender)
    -- Alte Formate parsen
end

function MyAdapter:QueueFullSync(sender, reason)
    -- Full-Sync via WHISPER an sender
    NM:QueueModuleWire(self.moduleKey, "full", data, nil, sender) -- sender = target!
end

-- Registrierung
function MyAdapter:Register()
    if NM then NM:RegisterAdapter(self) end
end
```

### Wichtige NM-Funktionen

| Funktion | Zweck |
|----------|-------|
| `NM:QueueAdapterLiveUpsert(moduleKey, type, entity)` | Live-Update senden |
| `NM:QueueAdapterLiveDelete(moduleKey, type, id, ts)` | Live-Delete senden |
| `NM:QueueModuleWire(moduleKey, prio, wire, dedupeKey, target)` | Raw Wire senden |
| `NM:StartHello(moduleKey, opts)` | HELLO initiieren |
| `NM:ScheduleModuleSync(moduleKey, opts)` | Periodischen Sync planen |
| `NM:GetMetrics()` | Diagnose-Metriken abrufen |
| `NM:GetQueueDepth()` | Queue-Tiefe abfragen |
| `NM.StripRealm(name)` | Realm vom Spielernamen entfernen |
| `NM.MyName()` | Eigenen Spielernamen (ohne Realm) abrufen |

---

## 🎨 UI-Design-System (ZENTRAL & VERBINDLICH)

### ⚠️ KRITISCH: Immer das zentrale UI-System nutzen!

**NIEMALS** lokale Backdrop-Definitionen oder Theme-Duplikate erstellen!
**NIEMALS** lokale `ApplyBackdrop()`- oder `MakeMovable()`-Funktionen erstellen!
**IMMER** das zentrale System in `Core/UI/` verwenden.

### Zentrale UI-Dateien (Lade-Reihenfolge wichtig!)

1. `Core/UI/Backdrops.lua` - Backdrop-Definitionen
2. `Core/UI/Colors.lua` - Farb-Tokens
3. `Core/UI/Layout.lua` - Layout-Konstanten
4. `Core/UI/Scale.lua` - UI-Skalierung (persistiert per Character)
5. `Core/UI/Theme.lua` - Theme-Funktionen + zentrale UI-Helper

### Zugriff auf das UI-System

```lua
local UI = ADDON.UI
local Colors = UI.Colors
local Layout = UI.Layout
```

### Verfügbare Backdrop-Varianten

- `"main"` - Hauptfenster (Frame mit Rahmen)
- `"inset"` - Inset-Bereiche (Content-Container)
- `"cell"` - Zellen (Kalender-Zellen, Tabellen-Zellen)
- `"button"` - Buttons
- `"card"` - Karten (z.B. Hub-App-Karten)
- `"row"` - Zebra-Reihen (ohne Rahmen, für Tabellen)

### Theme anwenden

```lua
-- RICHTIG: Zentrale Theme-Funktion nutzen
UI:ApplyTheme(frame, "main")  -- Variante: "main", "inset", "cell", etc.

-- FALSCH: Lokale Backdrop-Definitionen
local BD_MAIN = { bgFile = "..." }  -- ❌ NIEMALS!
frame:SetBackdrop(BD_MAIN)  -- ❌ NIEMALS!
```

### Farben verwenden

Alle verfügbaren Color-Tokens stehen in `Core/UI/Colors.lua`. Wichtige Tokens:

| Token | Verwendung |
|-------|-----------|
| `Colors.bgMain` | Hauptfenster-Hintergrund |
| `Colors.bgInset` | Inset-Bereiche |
| `Colors.bgElevated` | Erhöhte Bereiche, Cards, Headers |
| `Colors.bgInput` | Input-Felder, Suchleisten |
| `Colors.bgHover` | Hover-Zustand |
| `Colors.bgWarning` | Warnungs-Hintergrund |
| `Colors.gold` | Gold-Akzent (Titel, Überschriften) |
| `Colors.white` | Standard-Text |
| `Colors.textMuted` | Gedämpfter Text |
| `Colors.borderLight` | Neutraler Rahmen |
| `Colors.borderSubtle` | Dezenter Rahmen |
| `Colors.borderWarm` | Warmer Akzent-Rahmen |
| `Colors.borderInput` | Input-Feld-Rahmen |

```lua
-- RICHTIG: Zentrale Farb-Tokens nutzen
frame:SetBackdropColor(unpack(Colors.bgMain))
label:SetTextColor(unpack(Colors.gold))

-- FALSCH: Hardcoded Farben
frame:SetBackdropColor(0.04, 0.04, 0.07, 1.00)  -- ❌ NIEMALS!
```

### Layout-Konstanten verwenden

```lua
-- RICHTIG: Zentrale Layout-Konstanten
local padding = Layout.spacing.M
local rowHeight = Layout.rowHeight.normal

-- FALSCH: Hardcoded Werte
local padding = 12  -- ❌ NIEMALS!
```

### Zentrale UI-Helper nutzen

```lua
-- Movable Frames (IMMER die zentrale Funktion!)
UI:MakeMovable(frame)              -- ✅

-- FALSCH: Eigene MakeMovable-Funktion
local function MakeMovable(f) ... end  -- ❌ NIEMALS!

-- Inset erstellen
local inset = UI:CreateInset(parent)

-- Button erstellen
local btn = UI:CreateButtonRed(parent, 100, 24, "Text", onClick)

-- Logo-Watermark
UI:CreateLogoWatermark(parent)

-- Header mit Logo
UI:CreateHeaderWithLogo(parent, "Titel")
```

### Frame-Lifecycle: Kein SetParent(nil)!

```lua
-- RICHTIG: Frames in hidden Container reparenten
local orphanContainer = CreateFrame("Frame", nil, UIParent)
orphanContainer:Hide()

child:Hide()
child:SetParent(orphanContainer)  -- ✅ Reparent statt nil

-- FALSCH: Frame-Leaks durch SetParent(nil)
child:SetParent(nil)  -- ❌ NIEMALS! Erzeugt Memory-Leaks in WoW!
```

### Opake Hintergründe (Transparenz-Problem gelöst)

- **ALLE** Backdrops verwenden `"Interface\\Buttons\\WHITE8x8"` (NICHT Tooltip-Background!)
- **ALLE** Frames haben `SetAlpha(1.0)` für volle Opazität
- Hintergrundfarben sind dunkel (0.04-0.12 RGB), aber vollständig opak

### Beispiel: Neues Fenster erstellen

```lua
local _, ADDON = ...
local UI = ADDON.UI
local Colors = UI.Colors

-- Hauptfenster erstellen
local mainFrame = CreateFrame("Frame", "MyAddonFrame", UIParent, "BackdropTemplate")
mainFrame:SetSize(800, 600)
UI:ApplyTheme(mainFrame, "main")     -- ✅ Zentrale Theme-Funktion
UI:MakeMovable(mainFrame)            -- ✅ Zentrale MakeMovable

-- Inset-Bereich erstellen
local contentInset = UI:CreateInset(mainFrame)  -- ✅ Zentrale Helper-Funktion
contentInset:SetPoint("TOPLEFT", 10, -40)
contentInset:SetPoint("BOTTOMRIGHT", -10, 10)

-- Button erstellen
local btn = UI:CreateButtonRed(mainFrame, 100, 24, "Speichern", function()
    -- Button-Logik
end)

-- Text mit Color-Token
local label = mainFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
label:SetTextColor(unpack(Colors.gold))  -- ✅ Farb-Token
```

---

## 🔧 WoW-Addon Best Practices

### Frame-Erstellung

```lua
-- RICHTIG: BackdropTemplate für Frames mit Hintergrund
local frame = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")

-- RICHTIG: Frame-Strata und Frame-Level für Overlays
frame:SetFrameStrata("TOOLTIP")
frame:SetFrameLevel(100)

-- RICHTIG: Movable Frames über zentrale Funktion
UI:MakeMovable(frame)
```

### SavedVariables

```lua
-- In .toc definieren
## SavedVariables: GermanysAllStarDB GuildStockPlannerDB GermanysAllStarRaidplanerDB

-- In Lua: Defensive Initialisierung
local data = _G["GermanysAllStarDB"] or {}

-- Per-Gilde-Profiling (Pflicht!)
local profileKey = ADDON:GetProfileKey()  -- "RealmName::GuildName"
data.profiles = data.profiles or {}
data.profiles[profileKey] = data.profiles[profileKey] or { ... defaults ... }
```

### Addon-Messages: NUR über NetworkManager!

```lua
-- ✅ RICHTIG: Über Adapter und NetworkManager
local NM = ADDON.NetworkManager
NM:QueueModuleWire("hub", "live", MSG_POST .. ":" .. serializedPost)

-- ❌ FALSCH: Direkte SendAddonMessage-Aufrufe
C_ChatInfo.SendAddonMessage("GASHUB", data, "GUILD")  -- NIEMALS!
```

### Event-Handling

```lua
-- Events in Bootstrap.lua zentral registrieren
-- Modul-spezifische Events über die Init-Sequenz

-- Defensiv: Event-Args immer prüfen
if event == "ADDON_LOADED" and ... == "GermanysAllStar" then
    -- Initialisierung
end
```

### Error-Handling

```lua
-- pcall für fehleranfällige Operationen
local success, err = pcall(function()
    -- Potentiell fehleranfälliger Code
end)
if not success then
    ADDON:Debug("Fehler:", err)  -- ✅ Über ADDON:Debug, nicht print()
end
```

### Performance

```lua
-- Throttling: C_Timer.After statt OnUpdate wo möglich
C_Timer.After(0.2, function()
    -- Debounced Update
end)

-- OnUpdate NUR für den NetworkManager Send-Tick!
-- Alle anderen Module: C_Timer.After oder C_Timer.NewTimer verwenden

-- Debouncing für UI-Updates
local updateTimer
local function ScheduleUpdate()
    if updateTimer then return end
    updateTimer = C_Timer.NewTimer(0.1, function()
        updateTimer = nil
        -- Update-Logik
    end)
end
```

### Tombstones & Löschungen

```lua
-- IMMER Tombstones für gelöschte Daten setzen (NIEMALS nur löschen!)
profile.deletions[itemID] = time()  -- Zeitstempel als Tombstone

-- Tombstone-Compaction: Alte Tombstones bereinigen (7-30 Tage)
local RETENTION = 30 * 24 * 3600
local cutoff = time() - RETENTION
for id, ts in pairs(tombstones) do
    if ts < cutoff then tombstones[id] = nil end
end

-- Im Full-Sync: Tombstones IMMER mitsenden!
```

---

## 📝 Code-Stil & Konventionen

### Variablennamen

```lua
-- Lokale Variablen: camelCase
local mainFrame, contentInset, rowHeight

-- Module-Namespace: PascalCase
ADDON.Raidplaner = {}
local RP = ADDON.Raidplaner

-- Konstanten: UPPER_SNAKE_CASE
local MAX_ENTRIES = 3
local ROW_HEIGHT = 22

-- Message-Typen: UPPER_SNAKE_CASE mit MSG_ Prefix
local MSG_HELLO = "HUB_POST_HELLO"
local MSG_POST  = "HUB_POST_DATA"
```

### Funktionen

```lua
-- Lokale Funktionen: camelCase
local function createRow(parent)
    -- ...
end

-- Öffentliche Funktionen: PascalCase (im Namespace)
function RP:ShowRaidDetail(raidId)
    -- ...
end

-- Helper-Funktionen: Zentrale aus NM/Utilities nutzen, NICHT lokal duplizieren!
local function MyName() return NM.MyName() end           -- ✅ NM-Export
local function StripRealm(n) return NM.StripRealm(n) end -- ✅ NM-Export
```

### Debug-Logging

```lua
-- Modul-spezifischer Debug-Wrapper (einzige erlaubte Duplizierung)
local function NMDebug(...)
    if ADDON.Debug then ADDON:Debug("[ModulName]", ...) end
end

-- An strategischen Stellen loggen:
NMDebug("HELLO empfangen von", sender, "(FP:", fp, ")")
NMDebug("Full-Sync gesendet an", target, "(", count, "Einträge)")
NMDebug("Merge: +", added, "neu,", updated, "aktualisiert")

-- NICHT im OnUpdate-Ticker loggen! (Spam-Gefahr)
```

### Kommentare

```lua
-- Einzeilige Kommentare für kurze Erklärungen

-- Mehrzeilige Kommentare für komplexe Logik
-- Diese Funktion berechnet die Raid-Zeit basierend auf
-- dem Datum und der Zeit-String-Repräsentation.

-- Sektionen mit Trennlinien
---------------------------------------------------------------------------
-- Funktion: CreateRaidEntry
-- Erstellt einen neuen Raid-Eintrag im Kalender
---------------------------------------------------------------------------
```

### Strukturierung einer Lua-Datei

```lua
-- 1. Imports/Namespace
local _, ADDON = ...
local UI = ADDON.UI
local Colors = UI.Colors

-- 2. Konstanten
local MAX_ENTRIES = 3
local ROW_HEIGHT = 22
local MSG_HELLO = "MY_HELLO"

-- 3. Lokale Variablen (State)
local mainFrame, contentInset

-- 4. Helper-Funktionen (lokal)
local function NMDebug(...)
    if ADDON.Debug then ADDON:Debug("[Module]", ...) end
end

-- 5. Daten-/Merge-Logik
local function MergeEntity(data, sender)
    -- ...
end

-- 6. Hauptfunktionen (öffentlich)
function Module:Initialize()
    -- ...
end
```

---

## 🚫 Häufige Fehler vermeiden

### ❌ FALSCH: Lokale Backdrop/Theme-Funktionen

```lua
-- NIEMALS lokale Wrapper erstellen!
local function ApplyBackdrop(frame, variant) ... end  -- ❌
local function MakeMovable(frame) ... end             -- ❌
```

### ✅ RICHTIG: Zentrale UI-Funktionen nutzen

```lua
UI:ApplyTheme(frame, "main")   -- ✅
UI:MakeMovable(frame)          -- ✅
```

### ❌ FALSCH: Hardcoded Farben

```lua
frame:SetBackdropColor(0.04, 0.04, 0.07, 1.00)  -- ❌
```

### ✅ RICHTIG: Farb-Tokens nutzen

```lua
frame:SetBackdropColor(unpack(Colors.bgMain))  -- ✅
```

### ❌ FALSCH: Direkte Addon-Messages

```lua
C_ChatInfo.SendAddonMessage("GASHUB", data, "GUILD")  -- ❌
```

### ✅ RICHTIG: NetworkManager nutzen

```lua
NM:QueueModuleWire("hub", "live", wireBody)  -- ✅
```

### ❌ FALSCH: Helper lokal duplizieren

```lua
local function StripRealm(name)  -- ❌ Gibt es schon in NM!
    return name:match("^([^%-]+)") or name
end
```

### ✅ RICHTIG: Zentrale Exports nutzen

```lua
local stripped = NM.StripRealm(name)  -- ✅
local me = NM.MyName()               -- ✅
```

### ❌ FALSCH: SetParent(nil) für Frame-Cleanup

```lua
child:SetParent(nil)  -- ❌ Memory-Leak!
```

### ✅ RICHTIG: Hidden Container für Frame-Recycling

```lua
child:SetParent(orphanContainer)  -- ✅ Kein Leak
child:Hide()
```

### ❌ FALSCH: Full-Sync an GUILD senden

```lua
NM:QueueModuleWire("hub", "full", data)  -- ❌ Geht an ALLE!
```

### ✅ RICHTIG: Full-Sync per WHISPER an Anfragenden

```lua
NM:QueueModuleWire("hub", "full", data, nil, sender)  -- ✅ Nur an sender
```

---

## 🔍 Vor Code-Änderungen prüfen

1. **UI-Änderungen?** → Nutze `Core/UI/` System (ApplyTheme, Colors, MakeMovable)
2. **Neue Farben?** → Füge zu `Core/UI/Colors.lua` hinzu, NICHT hardcoden
3. **Neue Backdrops?** → Füge zu `Core/UI/Backdrops.lua` hinzu
4. **Layout-Änderungen?** → Nutze `Core/UI/Layout.lua`
5. **Neues Modul?** → Nutze zentrale UI-Funktionen, keine Duplikate!
6. **Sync-Änderungen?** → Immer über NetworkManager + Adapter
7. **Neue Nachrichten-Typen?** → Im passenden Adapter definieren, NM queuen
8. **Daten löschen?** → Tombstone setzen, NICHT nur `= nil`
9. **Helper-Funktion?** → Prüfe ob in `Utilities.lua`, `Permissions.lua` oder `NM`-Exports vorhanden
10. **Frame-Cleanup?** → `SetParent(orphanContainer)`, NICHT `SetParent(nil)`

---

## 📚 Wichtige Referenzen

- **Architektur-Audit:** `ARCHITECTURE_AUDIT.md` (vollständige Analyse + Roadmap)
- **WoW API:** https://wowpedia.fandom.com/wiki/World_of_Warcraft_API
- **FrameXML:** https://wowpedia.fandom.com/wiki/XML/Frame
- **SavedVariables:** https://wowpedia.fandom.com/wiki/SavedVariables

### Diagnose-Commands

```
/ga              Hub öffnen/schließen
/ga debug on     Debug-Logging aktivieren
/ga debug off    Debug-Logging deaktivieren
/ga raid         Raidplaner öffnen
/ga metrics      NetworkManager-Metriken anzeigen
/ga queue        Queue-Tiefe anzeigen
/ga sessions     Aktive Sync-Sessions anzeigen
```

---

## ✅ Checkliste vor Commits

- [ ] Zentrale UI-Struktur genutzt (keine lokalen Backdrops/MakeMovable/ApplyBackdrop)
- [ ] Farb-Tokens aus `Colors.lua` verwendet (keine hardcoded RGB-Werte)
- [ ] Layout-Konstanten aus `Layout.lua` verwendet
- [ ] Alle Frames sind opak (Alpha 1.0)
- [ ] Keine Duplikate von Theme-/Helper-Funktionen
- [ ] Sync-Nachrichten über NetworkManager gesendet (kein direktes SendAddonMessage)
- [ ] Full-Sync per WHISPER an target (nicht GUILD broadcast)
- [ ] Löschungen mit Tombstones (nicht nur `= nil`)
- [ ] Tombstones im Full-Sync mitgesendet
- [ ] SYNC_OK nach Full-Sync-Empfang gesendet (für bidirektionale Propagation)
- [ ] Helper aus NM-Exports genutzt (StripRealm, MyName)
- [ ] Debug-Logging an strategischen Stellen (nicht im OnUpdate)
- [ ] SetParent(orphanContainer) statt SetParent(nil)
- [ ] Code-Stil eingehalten (camelCase/PascalCase/UPPER_SNAKE_CASE)
- [ ] Kommentare für komplexe Logik vorhanden
- [ ] Error-Handling für kritische Funktionen (pcall)

---

**Diese Datei ist verbindlich für alle AI-Agents. Bei Unsicherheit: Fragen stellen oder diese Datei erneut lesen!**
