package auth

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"log/slog"
	"strings"

	"hyapp/pkg/appcode"
	"hyapp/pkg/idgen"
	"hyapp/pkg/logx"
	authdomain "hyapp/services/user-service/internal/domain/auth"
)

const (
	riskBlockReasonIPAsync = "ip_async"
)

func (s *Service) enqueueLoginIPRiskJob(ctx context.Context, meta Meta, token authdomain.Token, channel string, platform string, language string, timezone string) {
	if s.authRepository == nil || strings.TrimSpace(meta.ClientIP) == "" || token.SessionID == "" || token.UserID <= 0 {
		// 没有可复核 IP 或 session 时不创建任务；登录主链路不因此失败。
		return
	}
	nowMs := s.now().UnixMilli()
	clientIP := strings.TrimSpace(meta.ClientIP)
	job := authdomain.LoginIPRiskJob{
		AppCode:         appcode.Normalize(token.AppCode),
		JobID:           idgen.New("iprisk"),
		SessionID:       token.SessionID,
		UserID:          token.UserID,
		ClientIP:        clientIP,
		ClientIPHash:    HashLoginRiskIP(clientIP),
		Channel:         normalizeChannel(channel),
		Platform:        normalizePlatform(firstNonEmpty(platform, meta.Platform)),
		Language:        strings.TrimSpace(firstNonEmpty(language, meta.Language)),
		Timezone:        strings.TrimSpace(firstNonEmpty(timezone, meta.Timezone)),
		RequestID:       meta.RequestID,
		EdgeCountryCode: normalizeCountryCode(meta.CountryByIP),
		Status:          authdomain.LoginIPRiskStatusPending,
		CreatedAtMs:     nowMs,
		UpdatedAtMs:     nowMs,
	}
	if job.Channel == "" {
		job.Channel = "account"
	}
	if err := s.authRepository.CreateLoginIPRiskJob(ctx, job); err != nil {
		// 风控任务失败按文档 fail-open；日志只输出 IP hash，明文 IP 已在业务表审计。
		logx.Error(logx.With(ctx, slog.String("request_id", meta.RequestID), slog.String("app_code", job.AppCode)), "login_ip_risk_job_create_failed", err, slog.String("component", "user_auth"), slog.String("client_ip_hash", job.ClientIPHash), slog.String("session_id", job.SessionID))
		return
	}
	logx.Info(logx.With(ctx, slog.String("request_id", meta.RequestID), slog.String("app_code", job.AppCode)), "login_ip_risk_job_created", slog.String("component", "user_auth"), slog.String("job_id", job.JobID), slog.String("session_id", job.SessionID), slog.Int64("user_id", job.UserID), slog.String("client_ip_hash", job.ClientIPHash), slog.String("channel", job.Channel), slog.String("platform", job.Platform))
}

// HashLoginRiskIP 生成登录风险 Redis key 和 DB 索引用的稳定 IP 摘要。
func HashLoginRiskIP(ip string) string {
	sum := sha256.Sum256([]byte(strings.TrimSpace(ip)))
	return hex.EncodeToString(sum[:])
}
