// Command import-im-accounts performs an explicit, bounded Tencent IM account
// repair before replaying private notices that failed with invalid identifier.
package main

import (
	"context"
	"crypto/sha256"
	"flag"
	"fmt"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"

	"hyapp/pkg/tencentim"
	"hyapp/services/notice-service/internal/config"
)

const executeConfirmation = "IMPORT_EXACT_TENCENT_IM_ACCOUNTS"

type userIDFlags []int64

func (values *userIDFlags) String() string {
	parts := make([]string, 0, len(*values))
	for _, value := range *values {
		parts = append(parts, strconv.FormatInt(value, 10))
	}
	return strings.Join(parts, ",")
}

func (values *userIDFlags) Set(raw string) error {
	value, err := strconv.ParseInt(strings.TrimSpace(raw), 10, 64)
	if err != nil || value <= 0 {
		return fmt.Errorf("user-id must be a positive int64")
	}
	*values = append(*values, value)
	return nil
}

func main() {
	configPath := flag.String("config", "services/notice-service/configs/config.yaml", "notice-service config containing Tencent IM credentials")
	execute := flag.Bool("execute", false, "perform the exact account imports; default is dry-run")
	confirmation := flag.String("confirm", "", "required execution confirmation")
	timeout := flag.Duration("timeout", 30*time.Second, "total import timeout")
	var requested userIDFlags
	flag.Var(&requested, "user-id", "exact internal user_id to import; repeat for multiple users")
	flag.Parse()

	userIDs, err := normalizeUserIDs(requested)
	if err != nil {
		fatal(err)
	}
	if *timeout <= 0 || *timeout > 5*time.Minute {
		fatal(fmt.Errorf("timeout must be within (0,5m]"))
	}
	if *execute && strings.TrimSpace(*confirmation) != executeConfirmation {
		fatal(fmt.Errorf("--execute requires --confirm=%s", executeConfirmation))
	}
	fingerprint := userIDsSHA256(userIDs)
	if !*execute {
		fmt.Printf("mode=dry-run users=%d user_ids_sha256=%s\n", len(userIDs), fingerprint)
		return
	}

	cfg, err := config.Load(strings.TrimSpace(*configPath))
	if err != nil {
		fatal(err)
	}
	if !cfg.TencentIM.Enabled {
		fatal(fmt.Errorf("tencent_im.enabled is required"))
	}
	client, err := tencentim.NewRESTClient(cfg.TencentIM.RESTConfig())
	if err != nil {
		fatal(err)
	}
	ctx, cancel := context.WithTimeout(context.Background(), *timeout)
	defer cancel()
	for _, userID := range userIDs {
		// Account import is idempotent in the shared REST client: Tencent's
		// already-exists response is success, while transport and other API errors
		// stop the bounded batch before the notice replay is attempted.
		if err := client.ImportAccount(ctx, tencentim.AccountProfile{UserID: userID}); err != nil {
			fatal(fmt.Errorf("import user index %d: %w", sort.Search(len(userIDs), func(index int) bool { return userIDs[index] >= userID })+1, err))
		}
	}
	fmt.Printf("mode=execute imported=%d user_ids_sha256=%s\n", len(userIDs), fingerprint)
}

func normalizeUserIDs(values []int64) ([]int64, error) {
	if len(values) == 0 || len(values) > 100 {
		return nil, fmt.Errorf("user-id count must be between 1 and 100")
	}
	normalized := append([]int64(nil), values...)
	sort.Slice(normalized, func(i, j int) bool { return normalized[i] < normalized[j] })
	result := normalized[:0]
	for _, value := range normalized {
		if value <= 0 {
			return nil, fmt.Errorf("user-id must be a positive int64")
		}
		if len(result) == 0 || result[len(result)-1] != value {
			result = append(result, value)
		}
	}
	return result, nil
}

func userIDsSHA256(values []int64) string {
	parts := make([]string, 0, len(values))
	for _, value := range values {
		parts = append(parts, strconv.FormatInt(value, 10))
	}
	return fmt.Sprintf("%x", sha256.Sum256([]byte(strings.Join(parts, "\n"))))
}

func fatal(err error) {
	fmt.Fprintln(os.Stderr, err)
	os.Exit(1)
}
