# AI Asistan Chat Mimarisi

Chat widget'ının katmanları, veri akışı ve bileşenleri.

---

## 1. Katman Diyagramı

```
┌─────────────────────────────────────────────────────────────────────────────┐
│  FRONTEND                                                                   │
│  chat-widget.blade.php                                                      │
│  • UI: floating buton, pencere, mesaj alanı, input, PDF butonu             │
│  • Aktif harita: mainDropzone / mainTitle / CHARTS → chart_key              │
│  • Mesaj: sendMessageToAI() → showLoadingMessage() → fetch(SSE)             │
│  • SSE: getReader() → parse data: → enqueueText() → processQueue() (daktilo) │
└──────────────────────────────────┬──────────────────────────────────────────┘
                                   │
                                   │ POST /ai-asistan/mesaj-gonder
                                   │ Accept: text/event-stream
                                   │ Body: { message, conversation_history, chart_key, date, lat, lon, ... }
                                   ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  CONTROLLER                                                                 │
│  AIAsistanController::sendMessage()                                         │
│  • Validasyon → Konuşma geçmişi (DB veya request)                            │
│  • Panel params: user_chart_id → DB | request params → pageBuilder          │
│  • Chart key eşleşme → chartData (chart_type, person_a/b)                   │
│  • RAG: VectorSearchService::search() → ragContext                          │
│  • Kullanıcı mesajı DB → StreamedResponse → sendMessageStream()            │
│  • Her chunk: echo data: {"chunk":"..."} → flush                             │
│  • Stream bitince: AI cevabı DB (AiConversation assistant)                   │
└──────────────────────────────────┬──────────────────────────────────────────┘
                                   │
                                   ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  OPENAI SERVICE                                                             │
│  OpenAIService                                                               │
│  • buildSystemContent(): Astro Bilge + protokol + harita tipi + JSON + RAG   │
│  • sendMessageStream(): OpenAI API (stream: true) → chunk'lar onChunk ile    │
└──────────────────────────────────┬──────────────────────────────────────────┘
                                   │
                                   ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  DIŞ SERVİSLER                                                              │
│  ChartPageBuilderService (haritalar) · VectorSearchService (RAG) · OpenAI   │
└─────────────────────────────────────────────────────────────────────────────┘
```

---

## 2. Frontend (Chat Widget)

**Dosya:** `resources/views/frontend/ai-asistan/chat-widget.blade.php`

| Bileşen | Açıklama |
|--------|----------|
| **HTML** | Floating buton, chat penceresi, mesaj alanı, PDF butonu, textarea, gönder butonu. |
| **State** | `conversationHistory`, `isLoading`, `currentActiveChartKey`, `welcomeMessageShown`, `lastLongResponse`, `currentChartTitle`, `cachedTargetDate`, `cachedTargetTime`. |
| **Aktif harita** | Sıra: `currentActiveChartKey` → `mainDropzone.dataset.activeKey` → `window.activeKey` → `mainTitle` + `window.CHARTS`. Fallback: `natal`. |
| **Panel params** | `chartForm` (FormData) + URL params + `cachedTargetDate/Time`. |
| **sendMessageToAI()** | Kullanıcı mesajını ekler, history günceller, `showLoadingMessage()` (üç nokta; 2 sn sonra "Astro Bilge gökleri okuyor..."), `fetch()` ile POST. |
| **SSE** | `response.body.getReader()` → satır satır `data:` parse → `payload.chunk` → `enqueueText()` → `processQueue()` (daktilo + imleç). İlk chunk’ta `removeLoadingMessage()`, streaming div göster. |
| **Bitiş** | `payload.done` → imleci kaldır, `conversationHistory` ve PDF (`lastLongResponse`) güncelle. |

**Route:** `POST /ai-asistan/mesaj-gonder` → `ai-asistan.send-message`

---

## 3. Controller (AI Asistan)

**Dosya:** `app/Http/Controllers/Frontend/AIAsistanController.php`

| Adım | Açıklama |
|------|----------|
| **Validasyon** | `message`, `conversation_history`, `chart_key`, `user_chart_id`, `date`, `time`, `lat`, `lon`, `city`, `timezone`. |
| **Konuşma geçmişi** | Giriş + `user_chart_id` varsa: `AiConversation` son 20 kayıt. Yoksa: request’teki `conversation_history`. |
| **Panel parametreleri** | 1) `user_chart_id` → `UserChart::panelQuery()` (DB). 2) Request’te date/lat/lon dolu → panel params. 3) Kullanıcı varsa → son harita (DB). 4) Son çare → URL/request params. |
| **Harita üretimi** | `ChartPageBuilderService::build($panelRequest)` → `$panelData['charts']`. |
| **Chart key** | Tam / normalize / case-insensitive eşleşme; yoksa ilk harita fallback. |
| **chartData** | Seçilen haritanın `visual` (planetTable, houseTable, asteroidTable, aspectGrid) + ev doldurma. `chart_type` = `determineChartType($chartKey)`. Sinastri/kompozit/davison ise `enrichRelationshipChartData()` → `person_a`, `person_b`. |
| **RAG** | `VectorSearchService::search($message, ..., preferredChartKey: $chartKey)` → `$ragContext`. İsteğe embedding kaydı. |
| **Kullanıcı mesajı** | `AiConversation::create(..., role: user)`. |
| **Yanıt** | `StreamedResponse`: `OpenAIService::sendMessageStream(..., $chartData, $chartKey, $ragContext)`. Her chunk: `echo 'data: '.json_encode(['chunk'=>$chunk])."\n\n"`; flush. Hata: `data: {"error":"..."}`; bitiş: `data: {"done":true}`. |
| **AI cevabı** | Stream bitince `AiConversation::create(..., role: assistant, message: $fullText)`. |

**Yardımcı metodlar:**  
`determineChartType($chartKey)` → natal | sinastri | kompozit | davison | transit | progress | solar_return | draconic.  
`enrichRelationshipChartData($chartData, $charts, $chartKey, $chartType)` → `person_a`, `person_b` (natal_a/natal_b varsa).

---

## 4. OpenAIService

**Dosya:** `app/Services/OpenAIService.php`

| Metod | Açıklama |
|-------|----------|
| **buildSystemContent($chartData, $chartKey, $ragContext)** | Astro Bilge kimliği, KATI FORMAT/DİL kuralları, AKTİF HARİTA TİPİ (chart_type), HARİTA ODAĞI. Harita tipine göre talimatlar (sinastri: iki kişi etkileşimi; kompozit, davison, transit, progress, solar_return, draconic). RAG özeti. `formatChartDataForContext()` ile harita JSON’u (gezegenler, evler, asteroidler; sinastri/kompozit için kisi_a, kisi_b). ÖNEMLİ NOKTALAR, VERİ PROTOKOLÜ. |
| **formatChartDataForContext()** | planetTable/houseTable/asteroidTable → burç adı, deg_formatted, house. `chart_type`; varsa `kisi_a` / `kisi_b`. |
| **sendMessage()** | Tek istek: buildSystemContent + history + user message → OpenAI POST (stream yok). Cevap metni veya hata. |
| **sendMessageStream()** | Aynı system + history + user message, `stream: true`. SSE parse → delta content `$onChunk` ile döner; sonunda birleşik metin (veya hata/false). |

---

## 5. Veri Akışı (Tek Mesaj)

1. Kullanıcı yazar, Gönder’e basar.
2. **Frontend:** Aktif harita key + panel params → `sendMessageToAI()` → loading → `fetch(POST, message, conversation_history, chart_key, ...panelParams)`.
3. **Controller:** Validasyon → geçmiş (DB veya request) → panel params → `pageBuilder->build()` → chart key eşleşmesi → chartData (chart_type, person_a/b) → RAG → kullanıcı mesajı DB → StreamedResponse başlar.
4. **Controller:** `sendMessageStream()`; her chunk `data: {"chunk":"..."}\n\n` flush.
5. **OpenAI:** System (Astro Bilge + harita tipi + JSON + RAG) + history + user message ile stream.
6. **Frontend:** SSE okuyor → ilk chunk’ta loading kalkar, streaming div açılır → chunk’lar daktilo ile yazılır → `done` → history ve PDF güncellenir.
7. **Controller:** Stream bitince AiConversation (assistant) kaydı.

---

## 6. SSE Formatı

| Olay | Format |
|------|--------|
| Mesaj parçası | `data: {"chunk": "metin parçası"}\n\n` |
| Hata | `data: {"error": "hata mesajı"}\n\n` |
| Bitiş | `data: {"done": true}\n\n` |

Frontend: `chunk` biriktirir, daktilo ile gösterir; `done` ile turu kapatır, history/PDF günceller.

---

## 7. Dosya Özeti

| Dosya | Rol |
|-------|-----|
| `resources/views/frontend/ai-asistan/chat-widget.blade.php` | Chat UI, JS, SSE + daktilo. |
| `app/Http/Controllers/Frontend/AIAsistanController.php` | Giriş: validasyon, harita, RAG, stream, DB. |
| `app/Services/OpenAIService.php` | System prompt, harita context, OpenAI (normal + stream). |
| `app/Services/Chart/ChartPageBuilderService.php` | Panel → tüm haritalar (natal, sinastri, transit vb.). |
| `app/Services/VectorSearchService.php` | RAG arama + embedding. |
| `app/Models/AiConversation.php` | Konuşma kayıtları (user/assistant). |
| `routes/web.php` | `ai-asistan.send-message`, `ai-asistan.pdf-olustur`. |
| `public/frontend/css/chatgpt/ai-assistant.css` | Widget, imleç, loading stilleri. |
