package handler

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

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

	"infogenie-backend/config"
	"infogenie-backend/internal/database"
	"infogenie-backend/internal/model"
)

type AIRuntimeHandler struct{}

func NewAIRuntimeHandler() *AIRuntimeHandler { return &AIRuntimeHandler{} }

func maskAPIKey(k string) (set bool, hint string) {
	k = strings.TrimSpace(k)
	if k == "" {
		return false, ""
	}
	if len(k) <= 4 {
		return true, "****"
	}
	return true, "****" + k[len(k)-4:]
}

// GetAIRuntime 管理员读取当前 AI 上游配置（密钥脱敏）
func (h *AIRuntimeHandler) GetAIRuntime(c *gin.Context) {
	if config.Cfg == nil || strings.TrimSpace(config.Cfg.SiteAdminToken) == "" {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "admin_not_configured"})
		return
	}
	if !siteAdminTokenOK(c.GetHeader("X-Site-Admin-Token")) {
		c.JSON(http.StatusForbidden, gin.H{"error": "forbidden"})
		return
	}

	var row model.SiteAIRuntime
	_ = database.DB.First(&row, 1).Error
	keySet, keyHint := maskAPIKey(row.APIKey)
	c.JSON(http.StatusOK, gin.H{
		"api_base":          strings.TrimSpace(row.APIBase),
		"api_key_set":       keySet,
		"api_key_hint":      keyHint,
		"default_model":     strings.TrimSpace(row.DefaultModel),
		"default_provider":  strings.TrimSpace(row.DefaultProv),
	})
}

type putAIRuntimeBody struct {
	APIBase          string `json:"api_base"`
	APIKey           string `json:"api_key"`
	DefaultModel     string `json:"default_model"`
	DefaultProvider  string `json:"default_provider"`
}

// PutAIRuntime 管理员写入；api_key 留空或不传则保留原密钥
func (h *AIRuntimeHandler) PutAIRuntime(c *gin.Context) {
	if config.Cfg == nil || strings.TrimSpace(config.Cfg.SiteAdminToken) == "" {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "admin_not_configured"})
		return
	}
	if !siteAdminTokenOK(c.GetHeader("X-Site-Admin-Token")) {
		c.JSON(http.StatusForbidden, gin.H{"error": "forbidden"})
		return
	}

	var body putAIRuntimeBody
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_json"})
		return
	}

	var row model.SiteAIRuntime
	err := database.DB.First(&row, 1).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			row = model.SiteAIRuntime{ID: 1}
		} else {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "db_error"})
			return
		}
	}

	row.APIBase = strings.TrimSpace(body.APIBase)
	if strings.TrimSpace(body.DefaultModel) != "" {
		row.DefaultModel = strings.TrimSpace(body.DefaultModel)
	}
	if strings.TrimSpace(body.DefaultProvider) != "" {
		row.DefaultProv = strings.TrimSpace(body.DefaultProvider)
	} else if row.DefaultProv == "" {
		row.DefaultProv = "deepseek"
	}

	newKey := strings.TrimSpace(body.APIKey)
	if newKey != "" && !strings.Contains(newKey, "****") {
		row.APIKey = newKey
	}

	if err := database.DB.Save(&row).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "db_error"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ok": true})
}
