package region_sync

import (
	"fmt"
	"time"

	"github.com/QuantumNous/new-api/common"
	"github.com/QuantumNous/new-api/logger"
	"github.com/QuantumNous/new-api/model"
	"github.com/QuantumNous/new-api/setting/system_setting"
	"github.com/bytedance/gopkg/util/gopool"
)

// PushUserCreateToSlave 在 master 节点创建用户后，异步推送到 slave 节点
func PushUserCreateToSlave(user *model.User) {
	settings := system_setting.GetRegionSyncSettings()

	if !settings.Enabled || !settings.IsMaster {
		return
	}
	if len(settings.SlaveEndpoints) == 0 || settings.SyncApiKey == "" {
		return
	}

	gopool.Go(func() {
		req := &SyncUserRequest{
			Username:     user.Username,
			Email:        user.Email,
			PasswordHash: user.Password, // 传输的是哈希值，非明文密码
			DisplayName:  user.DisplayName,
			Quota:        user.Quota,
			RemoteUserId: user.Id,
			Group:        user.Group,
			AffCode:      user.AffCode,
		}

		for _, endpoint := range settings.SlaveEndpoints {
			client := NewSyncClient(endpoint, settings.SyncApiKey)
			resp, err := client.SyncUserCreate(req)
			if err != nil {
				logSyncError("user", user.Username, endpoint, "", err)
				continue
			}
			if !resp.Success {
				logSyncError("user", user.Username, endpoint, resp.Error, nil)
				continue
			}
			logSyncSuccess("user", user.Username, user.Id, endpoint)
		}

		recordSyncLog(user.Id, 0, model.SyncTypeUserCreate, "")
	})
}

// PushQuotaUpdateToSlave 在 master 节点更新用户余额后，推送到 slave 节点
func PushQuotaUpdateToSlave(userId int, quota int) {
	settings := system_setting.GetRegionSyncSettings()
	if !settings.Enabled || !settings.IsMaster {
		return
	}
	if len(settings.SlaveEndpoints) == 0 || settings.SyncApiKey == "" {
		return
	}

	logger.LogDebug(nil, "[RegionSync] PushQuotaUpdateToSlave: userId=%d, quota=%d, endpoints=%v", userId, quota, settings.SlaveEndpoints)

	gopool.Go(func() {
		for _, endpoint := range settings.SlaveEndpoints {
			client := NewSyncClient(endpoint, settings.SyncApiKey)
			resp, err := client.UpdateQuota(userId, quota)
			if err != nil {
				logSyncError("quota update", fmt.Sprintf("user %d", userId), endpoint, "", err)
				continue
			}
			if !resp.Success {
				logSyncError("quota update", fmt.Sprintf("user %d", userId), endpoint, resp.Error, nil)
				continue
			}
			logSyncSuccess("quota update", fmt.Sprintf("user %d", userId), 0, endpoint)
		}
	})
}

// logSyncError 记录同步错误日志
func logSyncError(operation, target, endpoint string, errMsg string, err error) {
	if err != nil {
		common.SysError(fmt.Sprintf("[RegionSync] Failed to push %s %s to slave %s: %v", operation, target, endpoint, err))
	} else {
		common.SysError(fmt.Sprintf("[RegionSync] Slave %s rejected %s %s: %s", endpoint, operation, target, errMsg))
	}
}

// logSyncSuccess 记录同步成功日志
func logSyncSuccess(operation, target string, id int, endpoint string) {
	if id > 0 {
		common.SysLog(fmt.Sprintf("[RegionSync] Successfully pushed %s %s (id=%d) to slave %s", operation, target, id, endpoint))
	} else {
		common.SysLog(fmt.Sprintf("[RegionSync] Successfully pushed %s %s to slave %s", operation, target, endpoint))
	}
}

// recordSyncLog 创建同步日志记录
func recordSyncLog(userId, remoteUserId int, syncType string, requestId string) {
	syncLog := &model.QuotaSyncLog{
		UserId:       userId,
		RemoteUserId: remoteUserId,
		SyncType:     syncType,
		Direction:    model.SyncDirectionCnToOv,
		Status:       model.SyncStatusSuccess,
		RequestId:    requestId,
		CreatedAt:    time.Now().Unix(),
	}
	if err := model.CreateSyncLog(syncLog); err != nil {
		common.SysError(fmt.Sprintf("[RegionSync] Failed to create sync log: %v", err))
	}
}
