package api

import (
	"context"
	"fmt"
	"net/http"
	"path/filepath"
	"time"

	"github.com/tidbcloud/account/commons/database"
	"github.com/tidbcloud/account/internel/svc/invite"
	"github.com/tidbcloud/account/internel/svc/token"

	"github.com/tidbcloud/account/internel/dto"

	"github.com/tidbcloud/account/central/events/publish"

	msp2 "github.com/tidbcloud/account/internel/svc/msp"
	orgsvc "github.com/tidbcloud/account/internel/svc/org"
	"github.com/tidbcloud/account/internel/svc/user"

	"github.com/google/uuid"
	"github.com/tidbcloud/account/central/jobs"
	"github.com/tidbcloud/account/thirdparty/cdn"
	"github.com/tidbcloud/account/thirdparty/jsm"

	userDao "github.com/tidbcloud/account/internel/dao/user"

	"github.com/tidbcloud/account/central/utils"
	"github.com/tidbcloud/account/commons/config"
	accountpb "github.com/tidbcloud/account/idl/pbgen/proto/account"
	"github.com/tidbcloud/account/thirdparty/account"
	"github.com/tidbcloud/tiinf/errs"

	"github.com/tidbcloud/account/internel/dao/entity"

	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"

	"github.com/gin-gonic/gin"
	"github.com/tidbcloud/account/admin/forms"
)

// @Summary CreateMspOrg
// @tags msp
// @Accept  json
// @Produce json
// @Param msp body forms.MspOrg true "CreateMspOrg"
// @Success 200 {object} forms.CreateMspOrgResp
// @Router /partner/msp/create [post]
func CreateMspOrg(c *gin.Context) {
	ctx := c.Request.Context()

	req := forms.MspOrg{}
	if err := c.ShouldBindJSON(&req); err != nil {
		tilog.Error(ctx, "ShouldBindJSON fail:", zap.Any("req", req), zap.Error(err))
		Fail(c, err, http.StatusBadRequest)
		return
	}
	tilog.Info(ctx, "CreateMspOrg start", zap.Any("req", req))
	email, _ := GetUserEmail(c)
	req.CreatedBy = email
	req.UpdatedBy = email
	svc, _ := msp2.GetMspSvc()

	mspOrg, err := svc.CreateMsp(ctx, req)
	if err != nil {
		tilog.Info(ctx, "CreateMsp fail:", zap.Any("req", req), zap.Error(err))
		Fail(c, err, http.StatusBadRequest)
		return
	}
	req.OrgId = mspOrg.ID.Uint64()

	userSvc, _ := user.GetUserSvc()
	createKeyToken, err := userSvc.CreateInviteToken(ctx, mspOrg.ID.Uint64(), mspOrg.Email, config.MspCreateKey)
	if err != nil {

		tilog.Error(ctx, "get createKeyToken fail:", zap.Any("req", req), zap.Error(err))
		Fail(c, err, http.StatusInternalServerError)
		return
	}
	registerToken, err := userSvc.CreateInviteToken(ctx, mspOrg.ID.Uint64(), mspOrg.Email, config.MspCustomerRegister)
	if err != nil {
		tilog.Error(ctx, "get registerToken fail:", zap.Any("req", req), zap.Error(err))
		Fail(c, err, http.StatusInternalServerError)
		return
	}

	param := &invite.InviteUserParam{
		EmailList:       []string{req.Email},
		OrgID:           mspOrg.ID.Uint64(),
		Role:            entity.RolePartnerAdmin,
		WithoutEmail:    true,
		WithoutAuditLog: true,
	}
	inviteSvc, _ := invite.GetInviteUserSvc()
	_, err = inviteSvc.InviteUser(ctx, param)
	if err != nil {
		tilog.Error(ctx, "CreateMsp InviteUser error", zap.Any("param", param), zap.Any("err", err))
		Fail(c, err, http.StatusInternalServerError)
		return
	}
	sessionSvc, _ := token.GetSession()
	inviteToken, err := sessionSvc.InsertUserInviteToken(database.DBConn.DB, 0, mspOrg.ID, token.InvitationVerificationMethod, mspOrg.Email, 30*24*time.Hour, true)
	if err != nil {
		tilog.Error(ctx, "CreateMspOrg failed to create user invite token", zap.Any("orgId", mspOrg.ID), zap.String("email", mspOrg.Email), zap.Error(err))
		Fail(c, err, http.StatusInternalServerError)
		return
	}

	if err := sendEmailForFirstKey(ctx, req, createKeyToken, registerToken, inviteToken); err != nil {
		tilog.Error(ctx, "sendEmail err", zap.Any("TenantID", mspOrg.ID.Uint64()), zap.Error(err))
	}
	//if err := events.PublishCreateTenantEvent(ctx, mspOrg.ID.Uint64()); err != nil {
	//	tilog.Error(ctx, "PublishCreateTenantEvent err", zap.Any("TenantID", mspOrg.ID.Uint64()), zap.Error(err))
	//}
	if err := publish.PublishOrgEvent(ctx, dto.OrgEventData{OrgId: mspOrg.ID.Uint64(), OrgEventType: entity.EntityEventTypeCreate}); err != nil {
		tilog.Error(ctx, "PublishOrgEvent err", zap.Any("TenantID", mspOrg.ID.Uint64()), zap.Error(err))
	}
	jobs.SaveSalesforceJobData(ctx, mspOrg.ID.Uint64())
	//jobs.SaveZendeskJobData(ctx, mspOrg.ID.Uint64())

	jsmClient := jsm.GetJsmClientSingleton()
	if jsmClient.IsEnable() {
		notifyCreateOrgErr := jsmClient.NotifyCreateOrgMessage(ctx, mspOrg)
		if notifyCreateOrgErr != nil {
			tilog.Error(ctx, "NotifyCreateOrgMessage err", zap.Any("TenantID", mspOrg.ID.Uint64()), zap.Error(notifyCreateOrgErr))
		}

		notifyEnableMspErr := jsmClient.NotifyEnableMspNotificationMessage(ctx, mspOrg.ID.Uint64())
		if notifyCreateOrgErr != nil {
			tilog.Error(ctx, "NotifyEnableMspNotificationMessage err", zap.Any("TenantID", mspOrg.ID.Uint64()), zap.Error(notifyEnableMspErr))
		}
	}

	resp := forms.CreateMspOrgResp{
		OrgId: mspOrg.ID.Uint64(),
	}
	tilog.Info(ctx, "CreateMspOrg  success", zap.Any("mspOrg", mspOrg))
	Success(c, resp, http.StatusOK)
}

/*func getInviteToken(ctx context.Context, orgId uint64, email string, method string) (*userDao.CreateInviteTokenResp, error) {
	var inviterToken entity.UserInviteToken
	var period time.Duration
	userSvc, _ := deps.GetUserSvc()
	if method == config.MspCreateKey {
		inviterToken = entity.UserInviteToken{
			Method:    method,
			Email:     email,
			TenantID:  entity.ID(orgId),
			BeginAt:   time.Now(),
			IsOneTime: true,
		}
		// expire 7 day
		period = 7 * 24 * time.Hour
	} else if method == config.MspCustomerRegister {
		inviterToken = entity.UserInviteToken{
			Method:    method,
			Email:     email,
			TenantID:  entity.ID(orgId),
			BeginAt:   time.Now(),
			IsOneTime: true,
		}
		// expire 1 day
		period = 1 * 24 * time.Hour
	}
	tokenResp, err := userSvc.NewUserInviteToken(ctx, inviterToken, period)
	if err != nil {
		tilog.Error(ctx, "GenUserInviteToken err", zap.Any("inviterToken", inviterToken), zap.Error(err))
		return nil, err
	}
	return tokenResp, nil
}*/

// @Summary UpdateMspOrg
// @tags msp
// @Accept  json
// @Produce json
// @Param msp body forms.MspOrg true "UpdateMspOrg"
// @Success 200 {object} forms.EmptyResponse
// @Router /partner/msp/update [post]
func UpdateMspOrg(c *gin.Context) {
	ctx := c.Request.Context()
	req := forms.MspOrg{}
	if err := c.ShouldBindJSON(&req); err != nil {
		Fail(c, err, http.StatusBadRequest)
		return
	}
	tilog.Info(ctx, "UpdateMspOrg req", zap.Any("req", req))
	if req.OrgId == 0 {
		Fail(c, errs.NewBadRequest("the msp org id is nil", nil), http.StatusBadRequest)
	}
	email, _ := GetUserEmail(c)
	req.UpdatedBy = email
	mspSvc, _ := msp2.GetMspSvc()
	err := msp2.CheckAdvertising(ctx, req.AdvertisingArr)
	if err != nil {
		Fail(c, err, http.StatusBadRequest)
		return
	}
	str, err := mspSvc.AdvertisingArrToJsonStr(ctx, req.AdvertisingArr)
	if err != nil {
		Fail(c, err, http.StatusBadRequest)
		return
	}
	mspConfig := entity.MspConfig{OrgID: entity.ID(req.OrgId), Advertising: str, Website: req.Website, LogoName: req.LogoName, Status: entity.Active}

	err = mspSvc.UpdateMspConfig(ctx, mspConfig)
	if err != nil {

		tilog.Error(ctx, "UpdateMspOrg err", zap.Any("req", req), zap.Error(err))
		Fail(c, err, http.StatusInternalServerError)
		return
	}

	Success(c, nil, http.StatusOK)
}

// @Summary GetMspByOrgId
// @tags msp
// @Accept  json
// @Produce json
// @Param org_id path string true "org_id"
// @Success 200 {object} forms.MspOrg
// @Router /partner/msp/{org_id} [get]
func GetMspByOrgId(c *gin.Context) {
	ctx := c.Request.Context()
	req := forms.GetOrgIDReq{}
	if err := c.ShouldBindUri(&req); err != nil {
		Fail(c, err, http.StatusBadRequest)
		return
	}
	orgSvc, _ := orgsvc.GetOrgSvc()
	mspSvc, _ := msp2.GetMspSvc()

	org, err := orgSvc.GetOrgByID(ctx, req.OrgID)
	if err != nil {
		Fail(c, err, http.StatusInternalServerError)
		return
	}
	mspConfig, err := mspSvc.GetMspConfigByOrgID(ctx, entity.ID(req.OrgID))

	if err != nil {

		tilog.Error(ctx, "GetMspConfigByOrgID fail:", zap.Error(err))
		Fail(c, err, http.StatusInternalServerError)
		return
	}

	if mspConfig == nil {

		msg := fmt.Sprintf("%d is not exist", req.OrgID)
		Fail(c, errs.NewBadRequest(msg, nil), http.StatusBadRequest)
		return
	}
	LogoUrl := getMspLogonUrl(mspConfig.LogoName)
	data := forms.MspOrg{
		OrgId:     org.ID.Uint64(),
		Name:      org.Name,
		Email:     org.Email,
		TimeZone:  org.TimeZone,
		Country:   org.Country,
		LogoUrl:   LogoUrl,
		Website:   mspConfig.Website,
		LogoName:  mspConfig.LogoName,
		CreatedBy: mspConfig.CreatedBy,
		UpdatedBy: mspConfig.UpdatedBy,
	}
	if mspConfig.Advertising != "" {
		advertisingArr, _ := mspSvc.JsonStrToAdvertisingArr(ctx, mspConfig.Advertising)
		data.AdvertisingArr = advertisingArr
	}
	Success(c, data, http.StatusOK)
}

// @Summary GetSignupUrl
// @tags msp
// @Accept  json
// @Produce json
// @Param org_id path string true "org_id"
// @Success 200 {string} string	"signup_url"
// @Router /partner/msp/{org_id}/signup-url [get]
func GetSignupUrl(c *gin.Context) {
	ctx := c.Request.Context()

	req := forms.GetOrgIDReq{}
	if err := c.ShouldBindUri(&req); err != nil {
		tilog.Error(ctx, "ShouldBindUri fail:", zap.Any("req", req), zap.Error(err))
		Fail(c, err, http.StatusBadRequest)
		return
	}
	tilog.Info(ctx, "GetSignupUrl start", zap.Any("req", req))
	orgSvc, _ := orgsvc.GetOrgSvc()
	mspOrg, err := orgSvc.GetOrgByID(ctx, req.OrgID)
	if err != nil || mspOrg == nil {
		Fail(c, errs.NewBadRequest("org_id is invalid", nil), http.StatusBadRequest)
		return
	}
	if mspOrg.OrgTag != string(entity.OrgTagMsp) {
		Fail(c, errs.NewBadRequest("org id is invalid", nil), http.StatusBadRequest)
		return
	}

	userSvc, _ := user.GetUserSvc()
	registerToken, err := userSvc.CreateInviteToken(ctx, mspOrg.ID.Uint64(), mspOrg.Email, config.MspCustomerRegister)
	if err != nil {
		tilog.Error(ctx, "get registerToken fail:", zap.Any("req", req), zap.Error(err))
		Fail(c, err, http.StatusInternalServerError)
		return
	}
	signupUrl := fmt.Sprintf("https://%s/signup?msp=%s&third_party_account_provider=%s&third_party_account_token=%s", config.Global().ServerConfig.FrontendDNS, mspOrg.Name, entity.MspThirdPartyAccountProvider, registerToken.TokenStr)
	//signupUrl = html.UnescapeString(signupUrl)
	tilog.Info(ctx, "GetSignupUrl success", zap.Any("signup_url", signupUrl))
	//obj := forms.MspOrg{RegistrationLink: signupUrl}
	SuccessPureJSON(c, signupUrl, http.StatusOK)
}

// @Summary CreateMspApiKey
// @tags msp
// @Accept  json
// @Produce json
// @Param org_id path string true "org_id"
// @Success 200 {object} forms.EmptyResponse
// @Router /partner/msp/{org_id}/create-apikey [post]
func CreateMspApiKey(c *gin.Context) {
	ctx := c.Request.Context()

	req := forms.GetOrgIDReq{}
	if err := c.ShouldBindUri(&req); err != nil {
		tilog.Error(ctx, "CreateMspApiKey ShouldBindUri err", zap.Any("req", req), zap.Error(err))
		Fail(c, err, http.StatusBadRequest)
		return
	}
	tilog.Info(ctx, "CreateMspApiKey", zap.Any("req", req))
	//email, _ := GetUserEmail(c)
	orgSvc, _ := orgsvc.GetOrgSvc()
	mspOrg, err := orgSvc.GetOrgByID(ctx, req.OrgID)
	if err != nil || mspOrg == nil {
		Fail(c, errs.NewBadRequest("param is invalid", nil), http.StatusBadRequest)
		return
	}
	if mspOrg.OrgTag != string(entity.OrgTagMsp) {
		Fail(c, errs.NewBadRequest("org id is invalid", nil), http.StatusBadRequest)
		return
	}
	//mspOrg := forms.MspOrg{OrgId: req.OrgID, Email: email}
	if mspOrg.Email == "" {
		Fail(c, errs.NewBadRequest("the msp org email is nil", nil), http.StatusBadRequest)
		return
	}
	userSvc, _ := user.GetUserSvc()
	createKeyToken, err := userSvc.CreateInviteToken(ctx, mspOrg.ID.Uint64(), mspOrg.Email, config.MspCreateKey)
	if err != nil {
		tilog.Error(ctx, "createKeyToken err", zap.Any("req", req), zap.Error(err))
		Fail(c, err, http.StatusInternalServerError)
		return
	}
	//createKeyToken, err := getInviteToken(mspOrg.OrgId, mspOrg.Email)
	//action := "msp_first_apikey"
	if err := sendEmailForRefreshKey(ctx, *mspOrg, createKeyToken); err != nil {
		tilog.Error(ctx, "sendEmail err", zap.Any("TenantID", req.OrgID), zap.Error(err))
		Fail(c, err, http.StatusInternalServerError)
		return
	}
	tilog.Info(ctx, "CreateMspApiKey  success", zap.Any("createKeyToken", createKeyToken))
	Success(c, nil, http.StatusOK)
}

//
//func createOpenAPIKey(ctx context.Context, mspOrg forms.MspOrg, description string) (*accountpb.ApiKey, error) {
//
//	operator := accountpb.OperatorType_OPERATOR_TYPE_USER
//	createApiKeyReq := &accountpb.CreateApiKeyReq{
//
//		Source:       "account_ops_msp",
//		Description:  description,
//		ScopeType:    string(entity.RoleBindingScopeOrg),
//		ResourceIds:  []uint64{mspOrg.OrgId},
//		Operator:     mspOrg.CreatedBy,
//		Role:         apikey.ApiKeyRoleBindingOrgOwner,
//		OperatorType: &operator,
//	}
//
//	apiKey, err := account.GetHandler().CreateApiKey(ctx, createApiKeyReq)
//	if err != nil {
//		logger.Error("CreateOpenAPIKey  for msp fail:" + err.Error())
//		return nil, err
//	}
//	if err != nil {
//		return nil, err
//	}
//
//	tilog.Info(ctx, " CreateOpenAPIKey success", zap.Any("apiKey", apiKey.ApiKey.AccessKey), zap.Any("createApiKeyReq", createApiKeyReq))
//	return apiKey.ApiKey, nil
//}

/*func getInviteToken(ctx context.Context, orgId uint64, email string, method string) (*userDao.CreateInviteTokenResp, error) {
	var inviterToken entity.UserInviteToken
	var period time.Duration
	userSvc, _ := deps.GetUserSvc()
	if method == config.MspCreateKey {
		inviterToken = entity.UserInviteToken{
			Method:    method,
			Email:     email,
			TenantID:  entity.ID(orgId),
			BeginAt:   time.Now(),
			IsOneTime: true,
		}
		// expire 7 day
		period = 7 * 24 * time.Hour
	} else if method == config.MspCustomerRegister {
		inviterToken = entity.UserInviteToken{
			Method:    method,
			Email:     email,
			TenantID:  entity.ID(orgId),
			BeginAt:   time.Now(),
			IsOneTime: true,
		}
		// expire 1 day
		period = 1 * 24 * time.Hour
	}
	tokenResp, err := userSvc.NewUserInviteToken(ctx, inviterToken, period)
	if err != nil {
		tilog.Error(ctx, "GenUserInviteToken err", zap.Any("inviterToken", inviterToken), zap.Error(err))
		return nil, err
	}
	return tokenResp, nil
}*/

func sendEmailForFirstKey(ctx context.Context, mspOrg forms.MspOrg, createKeyToken *userDao.CreateInviteTokenResp, registerToken *userDao.CreateInviteTokenResp, inviteToken string) error {
	email := mspOrg.Email

	name := utils.EscapeStr(ctx, mspOrg.Name)

	url := getCreateApiKeyUrl(ctx, createKeyToken.TokenStr)

	inviteUrl := fmt.Sprintf("https://%s/invitation-verification?token=%s", utils.GetCentralBackendDns(), inviteToken)
	tilog.Info(ctx, "generate inviteUrl", zap.Any("inviteUrl", inviteUrl))

	registrationLink := fmt.Sprintf("https://%s/signup?msp=%s&third_party_account_provider=%s&third_party_account_token=%s", config.Global().ServerConfig.FrontendDNS, mspOrg.Name, entity.MspThirdPartyAccountProvider, registerToken.TokenStr)
	tilog.Info(ctx, "registrationLink", zap.Any("register url", registrationLink))
	tilog.Info(ctx, "getCreateApiKeyUrl", zap.Any("create apikey url", url))

	emailVars := map[string]string{
		"mspName": name,
		//"registrationLink": registrationLink,
		"url":        url,
		"consoleURL": inviteUrl,
	}

	// this is Unique Value    demo: msp_fist_key_keyId:3333
	identifier := fmt.Sprintf("emailTN:%s_InviteToken:%d", config.TNMspFirstApiKey, createKeyToken.InviteToken.ID)
	// f63eb7baaa84422ba2d85e730b0cf8e1
	sendEmailReq := &accountpb.SendEmailReq{
		OrgId:        mspOrg.OrgId,
		Scene:        config.SendEmailScene,
		Identifier:   identifier,
		Emails:       []string{email},
		CcEmails:     nil,
		TemplateId:   config.SendgridTemplateName2id[config.TNMspFirstApiKey],
		TemplateVars: emailVars,
	}
	tilog.Info(ctx, "send  email req", zap.Any("sendEmailReq", sendEmailReq))
	accountHandler := account.GetHandler()
	resp, err := accountHandler.SendEmail(ctx, sendEmailReq)
	if err != nil && !errs.IsError(err, errs.ErrConflict) {
		tilog.Error(ctx, "failed to send msp first key  email", zap.String("email", email), zap.Error(err))
		return err
	}
	tilog.Info(ctx, "sendEmailForFirstKey resp", zap.Any("resp", resp))

	return nil
}

func sendEmailForRefreshKey(ctx context.Context, mspOrg entity.Tenant, inviteToken *userDao.CreateInviteTokenResp) error {
	email := mspOrg.Email
	name := utils.EscapeStr(ctx, mspOrg.Name)
	url := getCreateApiKeyUrl(ctx, inviteToken.TokenStr)

	emailVars := map[string]string{
		"mspName": name,
		"url":     url,
	}

	// this is Unique Value    demo: msp_fist_key_keyId:3333
	identifier := fmt.Sprintf("emailTN:%s_InviteToken:%d", config.TNMspRefreshApiKey, inviteToken.InviteToken.ID)

	sendEmailReq := &accountpb.SendEmailReq{
		OrgId:        mspOrg.ID.Uint64(),
		Scene:        config.SendEmailScene,
		Identifier:   identifier,
		Emails:       []string{email},
		CcEmails:     nil,
		TemplateId:   config.SendgridTemplateName2id[config.TNMspRefreshApiKey],
		TemplateVars: emailVars,
	}
	tilog.Info(ctx, "sendEmailForRefreshKey req", zap.Any("sendEmailReq", sendEmailReq))
	accountHandler := account.GetHandler()
	resp, err := accountHandler.SendEmail(ctx, sendEmailReq)
	if err != nil && !errs.IsError(err, errs.ErrConflict) {
		tilog.Error(ctx, "failed to send sendEmailForRefreshKey  email", zap.String("email", email), zap.Error(err))
		return err
	}
	tilog.Info(ctx, "sendEmailForRefreshKey resp", zap.Any("resp", resp))

	return nil
}

func getCreateApiKeyUrl(ctx context.Context, tokenStr string) string {
	//url := fmt.Sprintf("https://%s/api/v1/api-keys/msp?token=%s", config.Global().ServerConfig.BackendDNS, tokenStr)
	url := fmt.Sprintf("https://%s/msp/api-keys?token=%s", config.Global().ServerConfig.FrontendDNS, tokenStr)
	tilog.Info(ctx, "getCreateApiKeyUrl", zap.Any("url", url))
	return url
}

// @Summary UploadMspLogo
// @tags msp
// @Accept  json
// @Produce json
// @Param msp body forms.UploadMspLogo true "UploadMspLogo"
// @Success 200 {object} forms.UploadMspLogoResp
// @Router /partner/msp/upload-logo [post]
func UploadMspLogo(c *gin.Context) {
	ctx := c.Request.Context()
	req := &forms.UploadMspLogo{}
	err := c.ShouldBind(req)
	if err != nil {
		Fail(c, err, http.StatusBadRequest)
		return
	}

	filename := req.File.Filename

	extName := filepath.Ext(filename)
	newFileName := fmt.Sprintf("%s%s", uuid.NewString(), extName)

	body, err := req.File.Open()
	if err != nil {
		Fail(c, err, http.StatusBadRequest)
		return
	}
	//bucket := "dbaas-ui-cloudfront-dev"
	bucket := config.Global().MspLogoConfig.MspCloudfrontS3bucket

	path := fmt.Sprintf("%s/%s", "msp", newFileName)
	//contentType := getFileMIME(body)
	contentType := "image/svg+xml"

	err = cdn.UploadLogoImag(ctx, contentType, path, req.File.Size, body, bucket)
	if err != nil {
		tilog.Warn(ctx, "UploadLogoImag fail", zap.Any("path", path), zap.Any("contentType", contentType))
		Fail(c, err, http.StatusInternalServerError)
		return
	}

	obj := &forms.UploadMspLogoResp{
		LogoName: newFileName,
		LogoUrl:  fmt.Sprintf("%s/%s", config.Global().MspLogoConfig.MspCloudfrontDomain, path),
	}
	tilog.Info(ctx, "UploadMspLogo", zap.Any("UploadFileResp", obj))
	Success(c, obj, http.StatusOK)

}

func getMspLogonUrl(logoName string) string {
	if logoName == "" {
		return ""
	}
	LogoUrl := fmt.Sprintf("%s/msp/%s", config.Global().MspLogoConfig.MspCloudfrontDomain, logoName)
	return LogoUrl
}

/*
	func getFileMIME(file multipart.File) string {
		buffer := make([]byte, 512)
		_, err := file.Read(buffer)
		if err != nil {
			return ""
		}
		contentType := http.DetectContentType(buffer)
		return contentType
	}
*/
