package api

import (
	"errors"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"

	"account/internal/model"
)

func (h *handler) getSandboxBinding(c *gin.Context) {
	if _, ok := h.requireAdminPermission(c, permissionAdminSettingsRead); !ok {
		return
	}

	if h.db == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "database_not_configured"})
		return
	}

	var binding model.SandboxBinding
	if err := h.db.WithContext(c.Request.Context()).First(&binding).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			c.JSON(http.StatusOK, gin.H{"address": "", "name": ""})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed_to_query_binding", "message": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"address":   binding.AgentID,
		"updatedAt": binding.UpdatedAt.UnixMilli(),
	})
}

func (h *handler) bindSandboxNode(c *gin.Context) {
	adminUser, ok := h.requireAdminPermission(c, permissionAdminSettingsWrite)
	if !ok {
		return
	}
	if h.isReadOnlyAccount(adminUser) {
		respondError(c, http.StatusForbidden, "read_only_account", "demo account is read-only")
		return
	}

	if h.db == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "database_not_configured"})
		return
	}

	var req struct {
		Address string `json:"address"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_request", "message": err.Error()})
		return
	}

	agentID := strings.TrimSpace(req.Address)

	err := h.db.WithContext(c.Request.Context()).Transaction(func(tx *gorm.DB) error {
		// Clear existing bindings (enforce 1-to-1 for now as per frontend)
		if err := tx.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&model.SandboxBinding{}).Error; err != nil {
			return err
		}

		if agentID != "" {
			newBinding := model.SandboxBinding{
				AgentID: agentID,
			}
			if err := tx.Create(&newBinding).Error; err != nil {
				return err
			}
		}
		return nil
	})

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed_to_save_binding", "message": err.Error()})
		return
	}

	// Update the in-memory registry if available
	if h.agentRegistry != nil {
		// Enforce 1-to-1 binding: clear then set.
		h.agentRegistry.ClearSandboxAgents()
		if agentID != "" {
			h.agentRegistry.SetSandboxAgent(agentID, true)
		}
	}

	c.JSON(http.StatusOK, gin.H{"message": "sandbox node bound successfully", "address": agentID})
}
