package identity

import (
	"encoding/json"
	"net/http"
	"strings"

	"aigateway.local/core/internal/platform/apiresponse"
)

// registerSocialAdmin 注册扫码登录身份源的管理端点。
func (h *ManagementHTTPHandler) registerSocialAdmin() {
	h.mux.HandleFunc("GET /api/v1/admin/social-providers", h.listSocialProviders)
	h.mux.HandleFunc("POST /api/v1/admin/social-providers", h.createSocialProvider)
	h.mux.HandleFunc("PUT /api/v1/admin/social-providers/{kind}", h.updateSocialProvider)
	h.mux.HandleFunc("DELETE /api/v1/admin/social-providers/{kind}", h.deleteSocialProvider)
}

type socialProviderInput struct {
	Code                string  `json:"code"`
	DisplayName         string  `json:"display_name"`
	ClientID            string  `json:"client_id"`
	AgentID             string  `json:"agent_id"`
	Secret              *string `json:"secret"`
	RedirectURI         string  `json:"redirect_uri"`
	PortalReturnURL     string  `json:"portal_return_url"`
	AutoProvision       bool    `json:"auto_provision"`
	DefaultDepartmentID *string `json:"default_department_id"`
	Enabled             bool    `json:"enabled"`
}

func (h *ManagementHTTPHandler) decodeSocialProvider(w http.ResponseWriter, r *http.Request, creating bool) (socialProviderInput, SocialProvider, bool) {
	var input socialProviderInput
	decoder := json.NewDecoder(http.MaxBytesReader(w, r.Body, 1<<20))
	decoder.DisallowUnknownFields()
	if decoder.Decode(&input) != nil {
		apiresponse.Error(w, 400, "请求格式无效")
		return input, SocialProvider{}, false
	}
	input.Code = strings.ToLower(strings.TrimSpace(input.Code))
	input.DisplayName = strings.TrimSpace(input.DisplayName)
	input.ClientID = strings.TrimSpace(input.ClientID)
	input.AgentID = strings.TrimSpace(input.AgentID)
	if input.Code == "" || input.DisplayName == "" || input.ClientID == "" ||
		(creating && input.Secret == nil) || (input.Secret != nil && strings.TrimSpace(*input.Secret) == "") {
		apiresponse.Error(w, 400, "身份源代码、名称、AppID 或 AppSecret 无效")
		return input, SocialProvider{}, false
	}
	redirectURI, err := validateAbsoluteURL(input.RedirectURI)
	if err != nil || strings.Contains(redirectURI, "#") {
		apiresponse.Error(w, 400, "回调 URL 无效")
		return input, SocialProvider{}, false
	}
	returnURL, err := validateAbsoluteURL(input.PortalReturnURL)
	if err != nil {
		apiresponse.Error(w, 400, "门户返回 URL 无效")
		return input, SocialProvider{}, false
	}
	if input.DefaultDepartmentID != nil && *input.DefaultDepartmentID != "" {
		department, err := h.service.repository.GetDepartment(r.Context(), *input.DefaultDepartmentID)
		if err != nil || !department.Active {
			apiresponse.Error(w, 400, "默认部门不存在或已停用")
			return input, SocialProvider{}, false
		}
	}
	return input, SocialProvider{Code: input.Code, DisplayName: input.DisplayName, ClientID: input.ClientID, AgentID: input.AgentID,
		RedirectURI: redirectURI, PortalReturnURL: returnURL, AutoProvision: input.AutoProvision,
		DefaultDepartmentID: input.DefaultDepartmentID, Enabled: input.Enabled}, true
}

func (h *ManagementHTTPHandler) setSocialCredentials(record *SocialProvider, secret string) error {
	payload, _ := json.Marshal(socialCredentials{Secret: secret})
	encrypted, version, err := h.service.idpCipher.Encrypt(payload)
	if err != nil {
		return err
	}
	record.EncryptedCredentials, record.CredentialKEKVersion = encrypted, version
	return nil
}

func (h *ManagementHTTPHandler) socialProviderView(record SocialProvider) map[string]any {
	configured := false
	if plaintext, err := h.service.idpCipher.Decrypt(record.EncryptedCredentials, record.CredentialKEKVersion); err == nil {
		var credentials socialCredentials
		configured = json.Unmarshal(plaintext, &credentials) == nil && credentials.Secret != ""
	}
	return map[string]any{"id": record.ID, "code": record.Code, "kind": record.Kind, "display_name": record.DisplayName,
		"client_id": record.ClientID, "agent_id": record.AgentID, "secret_configured": configured,
		"redirect_uri": record.RedirectURI, "portal_return_url": record.PortalReturnURL,
		"auto_provision": record.AutoProvision, "default_department_id": record.DefaultDepartmentID,
		"enabled": record.Enabled, "revision": record.Revision, "created_at": record.CreatedAt, "updated_at": record.UpdatedAt}
}

func (h *ManagementHTTPHandler) listSocialProviders(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.requirePermission(w, r); !ok {
		return
	}
	records, err := h.service.repository.ListSocialProviders(r.Context())
	if err != nil {
		h.writeError(w, err)
		return
	}
	items := make([]map[string]any, 0, len(records))
	for _, record := range records {
		items = append(items, h.socialProviderView(record))
	}
	apiresponse.OK(w, items)
}

func (h *ManagementHTTPHandler) createSocialProvider(w http.ResponseWriter, r *http.Request) {
	actor, ok := h.requirePermission(w, r)
	if !ok {
		return
	}
	kind := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("kind")))
	if !socialKindSupported(kind) {
		apiresponse.Error(w, 400, "扫码登录平台必须是 wecom/dingtalk/feishu")
		return
	}
	input, record, ok := h.decodeSocialProvider(w, r, true)
	if !ok {
		return
	}
	if kind == "wecom" && input.AgentID == "" {
		apiresponse.Error(w, 400, "企业微信身份源需要 AgentID")
		return
	}
	if err := h.setSocialCredentials(&record, strings.TrimSpace(*input.Secret)); err != nil {
		h.writeError(w, err)
		return
	}
	record.Kind = kind
	created, err := h.service.repository.SaveSocialProvider(r.Context(), record, actor.ID, true, true)
	if err != nil {
		h.writeError(w, err)
		return
	}
	apiresponse.OK(w, h.socialProviderView(created))
}

func (h *ManagementHTTPHandler) updateSocialProvider(w http.ResponseWriter, r *http.Request) {
	actor, ok := h.requirePermission(w, r)
	if !ok {
		return
	}
	kind := strings.ToLower(strings.TrimSpace(r.PathValue("kind")))
	if !socialKindSupported(kind) {
		apiresponse.Error(w, 400, "扫码登录平台必须是 wecom/dingtalk/feishu")
		return
	}
	existing, err := h.service.repository.GetSocialProviderByKind(r.Context(), kind)
	if err != nil {
		h.writeError(w, err)
		return
	}
	input, record, ok := h.decodeSocialProvider(w, r, false)
	if !ok {
		return
	}
	if kind == "wecom" && input.AgentID == "" {
		apiresponse.Error(w, 400, "企业微信身份源需要 AgentID")
		return
	}
	record.ID = existing.ID
	record.Kind = kind
	replace := input.Secret != nil
	if replace {
		if err := h.setSocialCredentials(&record, strings.TrimSpace(*input.Secret)); err != nil {
			h.writeError(w, err)
			return
		}
	}
	updated, err := h.service.repository.SaveSocialProvider(r.Context(), record, actor.ID, false, replace)
	if err != nil {
		h.writeError(w, err)
		return
	}
	apiresponse.OK(w, h.socialProviderView(updated))
}

func (h *ManagementHTTPHandler) deleteSocialProvider(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.requirePermission(w, r); !ok {
		return
	}
	if err := h.service.repository.DeleteSocialProvider(r.Context(), r.PathValue("kind")); err != nil {
		h.writeError(w, err)
		return
	}
	apiresponse.OK(w, map[string]bool{"deleted": true})
}
