package handler

import (
	"crypto/subtle"
	"encoding/json"
	"io"
	"net/http"
	"strings"
	"time"

	"aijianzhan/platform/internal/authx"
	"aijianzhan/platform/internal/license"
	"aijianzhan/platform/internal/svc"

	"github.com/zeromicro/go-zero/rest/httpx"
)

func requireLicenseSecret(svcCtx *svc.ServiceContext, r *http.Request) error {
	want := strings.TrimSpace(svcCtx.Config.License.ControlSecret)
	if want == "" {
		want = strings.TrimSpace(svcCtx.Config.Auth.IssueSecret)
	}
	if want == "" {
		return errMsg("未配置 License.ControlSecret")
	}
	got := strings.TrimSpace(r.Header.Get("X-License-Secret"))
	if got == "" {
		got = strings.TrimSpace(r.URL.Query().Get("secret"))
	}
	if subtle.ConstantTimeCompare([]byte(got), []byte(want)) != 1 {
		return errMsg("invalid license control secret")
	}
	return nil
}

type errMsg string

func (e errMsg) Error() string { return string(e) }

func licenseStatusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if svcCtx.License == nil || !svcCtx.License.Enabled() {
			httpx.OkJson(w, map[string]any{"enabled": false, "message": "本实例未启用授权租约"})
			return
		}
		httpx.OkJson(w, svcCtx.License.Status(time.Now()))
	}
}

func licenseRenewHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := requireLicenseSecret(svcCtx, r); err != nil {
			authx.WriteError(w, http.StatusUnauthorized, err.Error())
			return
		}
		if svcCtx.License == nil || !svcCtx.License.Enabled() {
			authx.WriteError(w, http.StatusBadRequest, "license 未启用")
			return
		}
		var body struct {
			NotAfter string `json:"not_after"`
			Note     string `json:"note"`
			By       string `json:"by"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		na, err := license.ParseNotAfter(body.NotAfter)
		if err != nil || na.IsZero() {
			authx.WriteError(w, http.StatusBadRequest, "not_after 无效")
			return
		}
		by := strings.TrimSpace(body.By)
		if by == "" {
			by = "remote"
		}
		lease, err := svcCtx.License.Renew(na, by, body.Note)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		httpx.OkJson(w, map[string]any{"ok": true, "lease": lease, "status": svcCtx.License.Status(time.Now())})
	}
}

func licenseExtendHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := requireLicenseSecret(svcCtx, r); err != nil {
			authx.WriteError(w, http.StatusUnauthorized, err.Error())
			return
		}
		if svcCtx.License == nil || !svcCtx.License.Enabled() {
			authx.WriteError(w, http.StatusBadRequest, "license 未启用")
			return
		}
		var body struct {
			Days int    `json:"days"`
			Note string `json:"note"`
			By   string `json:"by"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		if body.Days <= 0 {
			body.Days = license.DefaultExtensionMaxDays
		}
		by := strings.TrimSpace(body.By)
		if by == "" {
			by = "remote"
		}
		lease, err := svcCtx.License.Extend(body.Days, by, body.Note)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		httpx.OkJson(w, map[string]any{"ok": true, "lease": lease, "status": svcCtx.License.Status(time.Now())})
	}
}

func licensePutLeaseHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := requireLicenseSecret(svcCtx, r); err != nil {
			authx.WriteError(w, http.StatusUnauthorized, err.Error())
			return
		}
		if svcCtx.License == nil || !svcCtx.License.Enabled() {
			authx.WriteError(w, http.StatusBadRequest, "license 未启用")
			return
		}
		var body struct {
			Customer         string `json:"customer"`
			NotAfter         string `json:"not_after"`
			ExtensionsUsed   int    `json:"extensions_used"`
			ExtensionsMax    int    `json:"extensions_max"`
			ExtensionMaxDays int    `json:"extension_max_days"`
			Note             string `json:"note"`
			By               string `json:"by"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		na, err := license.ParseNotAfter(body.NotAfter)
		if err != nil || na.IsZero() {
			authx.WriteError(w, http.StatusBadRequest, "not_after 无效")
			return
		}
		by := strings.TrimSpace(body.By)
		if by == "" {
			by = "watchdog"
		}
		lease, err := svcCtx.License.PutLease(&license.Lease{
			Customer:         body.Customer,
			NotAfter:         na,
			ExtensionsUsed:   body.ExtensionsUsed,
			ExtensionsMax:    body.ExtensionsMax,
			ExtensionMaxDays: body.ExtensionMaxDays,
			Note:             body.Note,
		}, by)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		httpx.OkJson(w, map[string]any{"ok": true, "lease": lease, "status": svcCtx.License.Status(time.Now())})
	}
}

func licenseImportHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := requireLicenseSecret(svcCtx, r); err != nil {
			authx.WriteError(w, http.StatusUnauthorized, err.Error())
			return
		}
		if svcCtx.License == nil || !svcCtx.License.Enabled() {
			authx.WriteError(w, http.StatusBadRequest, "license 未启用")
			return
		}
		raw, err := io.ReadAll(r.Body)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		by := strings.TrimSpace(r.URL.Query().Get("by"))
		if by == "" {
			by = "offline"
		}
		lease, err := svcCtx.License.ImportSigned(raw, by)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		httpx.OkJson(w, map[string]any{"ok": true, "lease": lease, "status": svcCtx.License.Status(time.Now())})
	}
}
