package main

import (
	"fikoyt-ajan/internal/client"
	"fikoyt-ajan/internal/config"
	"fikoyt-ajan/internal/handlers"
	"fikoyt-ajan/internal/notification"
	"log"
	"sync"
	"time"

	"github.com/wailsapp/wails/v3/pkg/application"
)

// App struct - Wails v3 uygulama yapısı
type App struct {
	// Wails v3 application
	wailsApp *application.App

	// Pencereler
	debugWindow        *application.WebviewWindow
	notificationWindow *application.WebviewWindow

	// Config
	config *config.Config

	// Socket client
	socketClient *client.SocketClient

	// Handlers
	mesajHandler  *handlers.MesajHandler
	komutHandler  *handlers.KomutHandler
	sistemHandler *handlers.SistemHandler

	// Notification manager
	notificationManager *notification.Manager

	// Pencere durumu
	notificationCount  int
	windowMu           sync.Mutex
	windowVisible      bool
	lastWindowHeight   int
}

// NewApp - Yeni uygulama oluştur
func NewApp() *App {
	return &App{}
}

// SetWindows - Pencereleri ayarla ve başlat
func (a *App) SetWindows(wailsApp *application.App, debug, notif *application.WebviewWindow) {
	a.wailsApp = wailsApp
	a.debugWindow = debug
	a.notificationWindow = notif

	// Başlatma işlemlerini yap
	a.startup()
}

// startup - Uygulama başlarken çağrılır
func (a *App) startup() {
	log.Println("FikoYT Ajan başlatılıyor...")

	// Konfigürasyonu yükle
	a.config = config.YeniConfig()
	log.Printf("Sunucu: %s", a.config.SunucuURL)
	log.Printf("Ajan ID: %s", a.config.AjanId)

	// Notification manager oluştur
	a.notificationManager = notification.NewManagerV3(a.wailsApp, a.notificationWindow)
	a.notificationManager.SetWindowController(a)

	// Handler'ları oluştur
	a.mesajHandler = handlers.YeniMesajHandler(a.notificationManager)
	a.komutHandler = handlers.YeniKomutHandler()
	a.sistemHandler = handlers.YeniSistemHandler()

	// Socket client oluştur
	a.socketClient = client.YeniSocketClient(a.config, a.mesajHandler, a.komutHandler, a.sistemHandler)

	// Bildirim olaylarını socket üzerinden gönder
	a.notificationManager.SetOlayCallback(func(olay notification.BildirimOlayi) {
		// Socket bağlıysa olayı gönder
		if a.socketClient != nil && a.socketClient.Bagli() {
			eventData := map[string]interface{}{
				"ajanId":       a.config.AjanId,
				"tip":          olay.Tip,
				"bildirimId":   olay.BildirimId,
				"mesajId":      olay.MesajId,
				"baslik":       olay.Baslik,
				"icerik":       olay.Icerik,
				"bildirimTipi": olay.BildirimTipi,
				"cevap":        olay.Cevap,
				"kapatmaTipi":  olay.KapatmaTipi,
				"progress":     olay.Progress,
				"sure":         olay.Sure,
				"zaman":        olay.Zaman,
			}
			if olay.EkVeri != nil {
				eventData["ekVeri"] = olay.EkVeri
			}
			a.socketClient.Emit("FikoYT.ajan.bildirim.olay", eventData)
			log.Printf("Bildirim olayı gönderildi: %s - %s", olay.Tip, olay.BildirimId)
		}
	})

	// Socket bağlantısını başlat
	go a.baglantiyiBaslat()
}

// baglantiyiBaslat - Socket bağlantısını başlat
func (a *App) baglantiyiBaslat() {
	bekleme := 5 * time.Second
	maxBekleme := 60 * time.Second
	deneme := 0

	for {
		deneme++
		log.Printf("Bağlantı denemesi #%d...", deneme)

		err := a.socketClient.Baglan()
		if err == nil {
			log.Println("Bağlantı başarılı!")
			a.emitEvent("connection:status", map[string]interface{}{
				"connected": true,
				"message":   "Sunucuya bağlandı",
			})
			return
		}

		log.Printf("Bağlantı hatası: %v", err)
		a.emitEvent("connection:status", map[string]interface{}{
			"connected": false,
			"message":   "Bağlantı hatası: " + err.Error(),
		})

		time.Sleep(bekleme)
		bekleme = bekleme * 2
		if bekleme > maxBekleme {
			bekleme = maxBekleme
		}
	}
}

// emitEvent - Tüm pencerelere event gönder
func (a *App) emitEvent(name string, data interface{}) {
	// Debug window'a gönder
	if a.debugWindow != nil {
		a.debugWindow.EmitEvent(name, data)
	}
	// Notification window'a gönder
	if a.notificationWindow != nil {
		a.notificationWindow.EmitEvent(name, data)
	}
}

// === Frontend'den çağrılabilir Go fonksiyonları ===

// GetConnectionStatus - Bağlantı durumunu getir
func (a *App) GetConnectionStatus() map[string]interface{} {
	if a.socketClient == nil {
		return map[string]interface{}{
			"connected": false,
			"message":   "Socket client başlatılmadı",
		}
	}
	return map[string]interface{}{
		"connected": a.socketClient.Bagli(),
		"message":   a.socketClient.Durum(),
	}
}

// GetSystemInfo - Sistem bilgilerini getir
func (a *App) GetSystemInfo() map[string]interface{} {
	if a.sistemHandler == nil {
		return nil
	}
	bilgi, err := a.sistemHandler.BilgiTopla()
	if err != nil {
		return nil
	}
	return map[string]interface{}{
		"hostname":    bilgi.Hostname,
		"os":          bilgi.OS,
		"platform":    bilgi.Platform,
		"cpuModel":    bilgi.CPUModel,
		"cpuKullanim": bilgi.CPUKullanim,
		"ramYuzde":    bilgi.RAMYuzde,
		"uptime":      bilgi.Uptime,
	}
}

// Reconnect - Yeniden bağlan
func (a *App) Reconnect() {
	if a.socketClient != nil {
		a.socketClient.YenidenBaglan()
	}
}

// GetConfig - Konfigürasyonu getir
func (a *App) GetConfig() map[string]interface{} {
	if a.config == nil {
		return nil
	}
	return map[string]interface{}{
		"sunucuUrl": a.config.SunucuURL,
		"ajanId":    a.config.AjanId,
		"ajanAd":    a.config.AjanAd,
	}
}

// DismissNotification - Bildirimi kapat (kullanıcı tarafından)
func (a *App) DismissNotification(id string) {
	if a.notificationManager != nil {
		a.notificationManager.DismissManual(id)
	}
}

// DismissNotificationAuto - Bildirimi otomatik kapat (timeout)
func (a *App) DismissNotificationAuto(id string) {
	if a.notificationManager != nil {
		a.notificationManager.Dismiss(id)
	}
}

// === Test Bildirim Metodları ===

// TestToast - Test toast bildirimi göster
func (a *App) TestToast(level string, title string, message string) string {
	if a.notificationManager == nil {
		return ""
	}
	var lvl notification.NotificationLevel
	switch level {
	case "success":
		lvl = notification.LevelSuccess
	case "warning":
		lvl = notification.LevelWarning
	case "error":
		lvl = notification.LevelError
	default:
		lvl = notification.LevelInfo
	}
	return a.notificationManager.ShowToast(title, message, lvl)
}

// TestProgress - Test progress bildirimi göster
func (a *App) TestProgress(title string, message string) string {
	if a.notificationManager == nil {
		return ""
	}
	return a.notificationManager.ShowProgress(title, message, 0)
}

// TestDialog - Test dialog bildirimi göster
func (a *App) TestDialog(title string, message string) string {
	if a.notificationManager == nil {
		return ""
	}
	return a.notificationManager.ShowDialog(title, message, []string{"Evet", "Hayir"}, nil)
}

// ClearNotifications - Tüm bildirimleri temizle
func (a *App) ClearNotifications() {
	if a.notificationManager != nil {
		a.notificationManager.Clear()
	}
}

// HandleNotificationAction - Bildirim aksiyonunu işle
func (a *App) HandleNotificationAction(id string, action string) {
	if a.notificationManager != nil {
		a.notificationManager.HandleAction(id, action)
	}
}

// === Pencere Yönetimi ===

// ShowNotificationWindow - Bildirim penceresini göster
func (a *App) ShowNotificationWindow() {
	a.windowMu.Lock()
	defer a.windowMu.Unlock()

	if a.notificationWindow == nil {
		return
	}

	// Pencereyi göster (boyut UpdateWindowSize ile ayarlanacak)
	a.notificationWindow.Show()
	log.Println("Bildirim penceresi gösterildi")
}

// UpdateWindowSize - Bildirim sayısına göre pencere boyutunu ayarla
func (a *App) UpdateWindowSize(count int) {
	if a.notificationWindow == nil {
		return
	}

	// Bildirim yoksa pencereyi gizle
	if count <= 0 {
		if a.windowVisible {
			a.notificationWindow.Hide()
			a.windowVisible = false
			log.Println("UpdateWindowSize: Pencere gizlendi")
		}
		return
	}

	// Her bildirim ~120px yüksekliğinde + 12px gap + 20px padding (üst/alt)
	notificationHeight := 120
	gap := 12
	padding := 24
	windowWidth := 420

	// Toplam yükseklik hesapla (max 5 bildirim)
	visibleCount := count
	if visibleCount > 5 {
		visibleCount = 5
	}

	windowHeight := (notificationHeight * visibleCount) + (gap * (visibleCount - 1)) + padding

	// Minimum yükseklik
	if windowHeight < 160 {
		windowHeight = 160
	}

	// Sadece yükseklik değiştiyse güncelle
	if windowHeight != a.lastWindowHeight {
		a.lastWindowHeight = windowHeight

		// Debug penceresinin ekranını kullan
		screen, err := a.debugWindow.GetScreen()
		if err == nil && screen != nil {
			workArea := screen.WorkArea
			x := workArea.X + workArea.Width - windowWidth - 16
			y := workArea.Y + workArea.Height - windowHeight - 16
			a.notificationWindow.SetSize(windowWidth, windowHeight)
			a.notificationWindow.SetPosition(x, y)
		} else {
			// Fallback: 1920x1080 varsay
			x := 1920 - windowWidth - 16
			y := 1040 - windowHeight - 16
			a.notificationWindow.SetSize(windowWidth, windowHeight)
			a.notificationWindow.SetPosition(x, y)
		}
	}

	// Pencere görünür değilse göster
	if !a.windowVisible {
		a.notificationWindow.Show()
		a.windowVisible = true
		log.Println("UpdateWindowSize: Pencere gösterildi")
	}
}

// HideNotificationWindow - Bildirim penceresini gizle
func (a *App) HideNotificationWindow() {
	a.windowMu.Lock()
	defer a.windowMu.Unlock()

	if a.notificationWindow != nil {
		a.notificationWindow.Hide()
		log.Println("Bildirim penceresi gizlendi")
	}
}

// OnNotificationAdded - Bildirim eklendiğinde çağrılır
func (a *App) OnNotificationAdded() {
	a.windowMu.Lock()
	a.notificationCount++
	count := a.notificationCount
	a.windowMu.Unlock()

	log.Printf("OnNotificationAdded: count=%d", count)
	// Not: Pencere gösterme işlemi frontend'den UpdateWindowSize ile yapılıyor
}

// OnNotificationRemoved - Bildirim kaldırıldığında çağrılır
func (a *App) OnNotificationRemoved() {
	a.windowMu.Lock()
	a.notificationCount--
	if a.notificationCount < 0 {
		a.notificationCount = 0
	}
	count := a.notificationCount
	a.windowMu.Unlock()

	if count == 0 {
		go func() {
			time.Sleep(500 * time.Millisecond)
			a.windowMu.Lock()
			if a.notificationCount == 0 {
				a.windowMu.Unlock()
				a.HideNotificationWindow()
			} else {
				a.windowMu.Unlock()
			}
		}()
	}
}

// === Mouse Event Kontrolü (Click-through için) ===

// EnableMouseEvents - Mouse event'lerini aktif et (notification üzerinde etkileşim için)
func (a *App) EnableMouseEvents() {
	if a.notificationWindow != nil {
		a.notificationWindow.SetIgnoreMouseEvents(false)
	}
}

// DisableMouseEvents - Mouse event'lerini devre dışı bırak (click-through için)
func (a *App) DisableMouseEvents() {
	if a.notificationWindow != nil {
		a.notificationWindow.SetIgnoreMouseEvents(true)
	}
}
