package api

import (
	"context"
	"fmt"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"

	appsettings "github.com/prism/proxy/internal/settings"
	"github.com/prism/proxy/internal/store"
)

func (s *Server) getSettings(c *gin.Context) {
	settings, err := s.app.Store.GetSettings(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	safe := make(map[string]string)
	for k, v := range settings {
		if k == appsettings.KeyAdminPassword || k == appsettings.KeyProxyAuthPass {
			safe[k] = ""
			continue
		}
		safe[k] = v
	}
	c.JSON(http.StatusOK, appsettings.Display(safe))
}

func (s *Server) putSettings(c *gin.Context) {
	var req map[string]string
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	if pw, ok := req[appsettings.KeyAdminPassword]; ok && pw != "" {
		hash, err := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}
		req[appsettings.KeyAdminPassword] = string(hash)
	} else {
		delete(req, appsettings.KeyAdminPassword)
	}
	if err := normalizeProxyAuthSettings(c.Request.Context(), s.app.Store, req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	appsettings.NormalizeSubmit(req)
	if err := s.app.Store.SetSettings(c.Request.Context(), req); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	allSettings, _ := s.app.Store.GetSettings(c.Request.Context())
	applyGeoSettings(s.app.DataDir, allSettings)
	base, secret, _ := s.app.MihomoAPIBase(c.Request.Context())
	s.health.UpdateAPIBase(base, secret)
	s.metrics.UpdateAPIBase(base, secret)
	s.syncMihomoClient(c.Request.Context())
	_ = s.app.ReloadEngine(c.Request.Context())
	c.JSON(http.StatusOK, gin.H{"ok": true})
}

func normalizeProxyAuthSettings(ctx context.Context, st *store.Store, req map[string]string) error {
	user, hasUser := req["proxy_auth_user"]
	pass, hasPass := req["proxy_auth_pass"]
	if !hasUser && !hasPass {
		return nil
	}
	user = strings.TrimSpace(user)
	if user == "" {
		req["proxy_auth_user"] = ""
		req["proxy_auth_pass"] = ""
		return nil
	}
	if strings.Contains(user, ":") {
		return fmt.Errorf("代理用户名不能包含冒号")
	}
	req["proxy_auth_user"] = user
	if !hasPass || pass == "" {
		current, err := st.GetSettings(ctx)
		if err != nil {
			return err
		}
		if existing := current["proxy_auth_pass"]; existing != "" {
			delete(req, "proxy_auth_pass")
			return nil
		}
		return fmt.Errorf("请填写代理密码")
	}
	req["proxy_auth_pass"] = pass
	return nil
}
