package http

import (
	"encoding/json"
	"errors"
	"io"
	"log/slog"
	stdhttp "net/http"
	"strings"

	"qycw/go-server/internal/bootstrap"
	licenseclient "qycw/go-server/internal/license"
	"qycw/go-server/internal/response"
)

const maxLicenseCodeLength = 255

type activateLicenseRequest struct {
	LicenseCode string `json:"licenseCode"`
}

func activateLicense(app *bootstrap.App, logger *slog.Logger) stdhttp.HandlerFunc {
	return func(w stdhttp.ResponseWriter, r *stdhttp.Request) {
		if app == nil || app.LicenseManager == nil {
			response.Detail(w, stdhttp.StatusServiceUnavailable, "授权服务暂时不可用")
			return
		}

		var request activateLicenseRequest
		decoder := json.NewDecoder(io.LimitReader(r.Body, 4*1024))
		decoder.DisallowUnknownFields()
		if err := decoder.Decode(&request); err != nil {
			response.Detail(w, stdhttp.StatusBadRequest, "请求参数无效")
			return
		}
		code := strings.TrimSpace(request.LicenseCode)
		if code == "" || len(code) > maxLicenseCodeLength {
			response.Detail(w, stdhttp.StatusBadRequest, "授权码无效")
			return
		}

		backendURL := app.Config.BackendURL
		if backendURL == "" {
			scheme := "http"
			if r.TLS != nil {
				scheme = "https"
			}
			if r.Host != "" {
				backendURL = scheme + "://" + r.Host
			}
		}
		if licenseclient.NormalizeBackendURL(backendURL) == "" {
			response.Detail(w, stdhttp.StatusBadRequest, "无法确定后端地址，请在配置中设置 PUBLIC_BACKEND_URL")
			return
		}
		if err := app.LicenseManager.Activate(r.Context(), code, backendURL); err != nil {
			if logger != nil {
				logger.Warn("authorization activation failed", "error", err)
			}
			writeActivationError(w, err)
			return
		}

		response.OK(w, map[string]any{"configured": true})
	}
}

func writeActivationError(w stdhttp.ResponseWriter, err error) {
	if errors.Is(err, licenseclient.ErrUnavailable) {
		response.Detail(w, stdhttp.StatusBadRequest, "授权码无效或不可用")
		return
	}
	var persistenceError *licenseclient.PersistenceError
	if errors.As(err, &persistenceError) {
		response.Detail(w, stdhttp.StatusInternalServerError, "授权状态保存失败")
		return
	}
	var httpError *licenseclient.HTTPError
	if errors.As(err, &httpError) {
		switch httpError.StatusCode {
		case stdhttp.StatusBadRequest, stdhttp.StatusUnauthorized, stdhttp.StatusForbidden:
			response.Detail(w, stdhttp.StatusBadRequest, "授权码无效或不可用")
		case stdhttp.StatusConflict:
			response.Detail(w, stdhttp.StatusConflict, "授权实例数量已达上限")
		default:
			response.Detail(w, stdhttp.StatusBadGateway, "授权服务暂时不可用")
		}
		return
	}
	response.Detail(w, stdhttp.StatusBadGateway, "授权服务暂时不可用")
}
