package handlers

import (
	"log"
	"medi-wol/internal/database"
	"medi-wol/internal/models"
	"medi-wol/internal/ping"
	"medi-wol/internal/wol"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
)

// PCHandler verwaltet die HTTP-Anfragen für PC-Operationen
type PCHandler struct {
	db          *database.DB
	wolService  *wol.Service
	pingService *ping.PingService
}

// NewPCHandler erstellt einen neuen PC-Handler
func NewPCHandler(db *database.DB, wolService *wol.Service) *PCHandler {
	return &PCHandler{
		db:          db,
		wolService:  wolService,
		pingService: ping.NewPingService(),
	}
}

// Index zeigt die Hauptseite an
func (h *PCHandler) Index(c *gin.Context) {
	c.HTML(http.StatusOK, "index.html", gin.H{
		"title": "Medi-WOL - Wake-on-LAN Manager",
	})
}

// Logs zeigt die Logs-Seite an
func (h *PCHandler) Logs(c *gin.Context) {
	c.HTML(http.StatusOK, "logs.html", gin.H{
		"title": "Medi-WOL - Logs",
	})
}

// GetAllPCs gibt alle gespeicherten PCs zurück
func (h *PCHandler) GetAllPCs(c *gin.Context) {
	pcs, err := h.db.GetAllPCs()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.PCResponse{
			Success: false,
			Message: "Fehler beim Laden der PCs: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, models.PCResponse{
		Success: true,
		PCs:     pcs,
	})
}

// CreatePC erstellt einen neuen PC-Eintrag
func (h *PCHandler) CreatePC(c *gin.Context) {
	var req models.CreatePCRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, models.PCResponse{
			Success: false,
			Message: "Ungültige Anfrage: " + err.Error(),
		})
		return
	}

	// MAC-Adresse validieren
	if !wol.ValidateMAC(req.MAC) {
		c.JSON(http.StatusBadRequest, models.PCResponse{
			Success: false,
			Message: "Ungültige MAC-Adresse",
		})
		return
	}

	// Standardwert für Autostart-Cron setzen, falls nicht angegeben
	if req.AutostartCron == "" {
		req.AutostartCron = "30 7 * * Mon-Fri"
	}

	// PC erstellen
	pc, err := h.db.CreatePC(req.Name, req.MAC, req.IP, req.AutostartCron, req.AutostartEnabled)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.PCResponse{
			Success: false,
			Message: "Fehler beim Erstellen des PCs: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusCreated, models.PCResponse{
		Success: true,
		Message: "PC erfolgreich erstellt",
		PC:      pc,
	})
}

// UpdatePC aktualisiert einen bestehenden PC-Eintrag
func (h *PCHandler) UpdatePC(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.PCResponse{
			Success: false,
			Message: "Ungültige PC-ID",
		})
		return
	}

	var req models.UpdatePCRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, models.PCResponse{
			Success: false,
			Message: "Ungültige Anfrage: " + err.Error(),
		})
		return
	}

	// MAC-Adresse validieren
	if !wol.ValidateMAC(req.MAC) {
		c.JSON(http.StatusBadRequest, models.PCResponse{
			Success: false,
			Message: "Ungültige MAC-Adresse",
		})
		return
	}

	// Standardwert für Autostart-Cron setzen, falls nicht angegeben
	if req.AutostartCron == "" {
		req.AutostartCron = "30 7 * * Mon-Fri"
	}

	// PC aktualisieren
	pc, err := h.db.UpdatePC(id, req.Name, req.MAC, req.IP, req.AutostartCron, req.AutostartEnabled)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.PCResponse{
			Success: false,
			Message: "Fehler beim Aktualisieren des PCs: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, models.PCResponse{
		Success: true,
		Message: "PC erfolgreich aktualisiert",
		PC:      pc,
	})
}

// DeletePC löscht einen PC-Eintrag
func (h *PCHandler) DeletePC(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.PCResponse{
			Success: false,
			Message: "Ungültige PC-ID",
		})
		return
	}

	err = h.db.DeletePC(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.PCResponse{
			Success: false,
			Message: "Fehler beim Löschen des PCs: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, models.PCResponse{
		Success: true,
		Message: "PC erfolgreich gelöscht",
	})
}

// WakePC sendet ein Wake-on-LAN Paket
func (h *PCHandler) WakePC(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.PCResponse{
			Success: false,
			Message: "Ungültige PC-ID",
		})
		return
	}

	// PC aus der Datenbank holen
	pc, err := h.db.GetPCByID(id)
	if err != nil {
		c.JSON(http.StatusNotFound, models.PCResponse{
			Success: false,
			Message: "PC nicht gefunden",
		})
		return
	}

	// Wake-on-LAN Paket senden
	err = h.wolService.WakePC(pc.MAC)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.PCResponse{
			Success: false,
			Message: "Fehler beim Senden des Wake-on-LAN Pakets: " + err.Error(),
		})
		return
	}

	// Log-Eintrag erstellen
	_, logErr := h.db.CreateLog(pc.ID, pc.Name, pc.MAC, "button")
	if logErr != nil {
		// Log-Fehler nicht an den Benutzer weitergeben, nur intern protokollieren
		log.Printf("Fehler beim Erstellen des Log-Eintrags: %v", logErr)
	}

	c.JSON(http.StatusOK, models.PCResponse{
		Success: true,
		Message: "Wake-on-LAN Paket erfolgreich gesendet an " + pc.Name,
	})
}

// GetPCStatus gibt den Online-Status aller PCs zurück
func (h *PCHandler) GetPCStatus(c *gin.Context) {
	pcs, err := h.db.GetAllPCs()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.PCResponse{
			Success: false,
			Message: "Fehler beim Laden der PCs: " + err.Error(),
		})
		return
	}

	// Online-Status für alle PCs überprüfen
	var statusList []models.PCStatus
	for _, pc := range pcs {
		online := h.pingService.IsOnline(pc.IP)
		statusList = append(statusList, models.PCStatus{
			ID:               pc.ID,
			Name:             pc.Name,
			MAC:              pc.MAC,
			IP:               pc.IP,
			Online:           online,
			AutostartCron:    pc.AutostartCron,
			AutostartEnabled: pc.AutostartEnabled,
		})
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"status":  statusList,
	})
}

// GetAllLogs gibt alle Log-Einträge zurück
func (h *PCHandler) GetAllLogs(c *gin.Context) {
	logs, err := h.db.GetAllLogs()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.LogResponse{
			Success: false,
			Message: "Fehler beim Laden der Logs: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, models.LogResponse{
		Success: true,
		Logs:    logs,
	})
}

// GetLogsByPCID gibt alle Log-Einträge für einen bestimmten PC zurück
func (h *PCHandler) GetLogsByPCID(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.LogResponse{
			Success: false,
			Message: "Ungültige PC-ID",
		})
		return
	}

	logs, err := h.db.GetLogsByPCID(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.LogResponse{
			Success: false,
			Message: "Fehler beim Laden der Logs: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, models.LogResponse{
		Success: true,
		Logs:    logs,
	})
}

// GetRecentLogsByPCID gibt die letzten 5 Log-Einträge für einen bestimmten PC zurück
func (h *PCHandler) GetRecentLogsByPCID(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.LogResponse{
			Success: false,
			Message: "Ungültige PC-ID",
		})
		return
	}

	logs, err := h.db.GetRecentLogsByPCID(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.LogResponse{
			Success: false,
			Message: "Fehler beim Laden der Logs: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, models.LogResponse{
		Success: true,
		Logs:    logs,
	})
}
