package handler

import (
	"crypto/subtle"
	"database/sql"
	"errors"
	"net/http"

	"mengyamonitor-backend-server/internal/config"
	"mengyamonitor-backend-server/internal/model"
	"mengyamonitor-backend-server/internal/store"

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

type Admin struct {
	Store *store.Store
	Cfg   *config.Config
}

func (h *Admin) Auth(c *gin.Context) {
	var in model.AuthInput
	if err := c.ShouldBindJSON(&in); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid body"})
		return
	}
	if subtle.ConstantTimeCompare([]byte(in.Token), []byte(h.Cfg.AdminToken)) != 1 {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ok": true})
}

func (h *Admin) ListServers(c *gin.Context) {
	list, err := h.Store.ListAll(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": list})
}

func (h *Admin) CreateServer(c *gin.Context) {
	var in model.CreateServerInput
	if err := c.ShouldBindJSON(&in); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid body"})
		return
	}
	s, err := h.Store.Create(c.Request.Context(), in)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusCreated, gin.H{"data": s})
}

func (h *Admin) UpdateServer(c *gin.Context) {
	id := c.Param("id")
	var in model.UpdateServerInput
	if err := c.ShouldBindJSON(&in); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid body"})
		return
	}
	s, err := h.Store.Update(c.Request.Context(), id, in)
	if errors.Is(err, sql.ErrNoRows) {
		c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
		return
	}
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": s})
}

func (h *Admin) DeleteServer(c *gin.Context) {
	id := c.Param("id")
	if err := h.Store.Delete(c.Request.Context(), id); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ok": true})
}

func (h *Admin) Reorder(c *gin.Context) {
	var in model.ReorderInput
	if err := c.ShouldBindJSON(&in); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid body"})
		return
	}
	if err := h.Store.Reorder(c.Request.Context(), in.IDs); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ok": true})
}
