// Package cmd contains CLI helpers. This file implements importing a Vertex AI
// service account JSON into the auth store as a dedicated "vertex" credential.
package cmd

import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"strings"

	"github.com/router-for-me/CLIProxyAPI/v7/internal/auth/vertex"
	"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
	"github.com/router-for-me/CLIProxyAPI/v7/internal/util"
	sdkAuth "github.com/router-for-me/CLIProxyAPI/v7/sdk/auth"
	coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
	log "github.com/sirupsen/logrus"
)

// DoVertexImport imports a Google Cloud service account key JSON and persists
// it as a "vertex" provider credential. The file content is embedded in the auth
// file to allow portable deployment across stores.
func DoVertexImport(cfg *config.Config, keyPath string, prefix string) {
	if cfg == nil {
		cfg = &config.Config{}
	}
	if resolved, errResolve := util.ResolveAuthDir(cfg.AuthDir); errResolve == nil {
		cfg.AuthDir = resolved
	}
	rawPath := strings.TrimSpace(keyPath)
	if rawPath == "" {
		log.Errorf("vertex-import: missing service account key path")
		return
	}
	data, errRead := os.ReadFile(rawPath)
	if errRead != nil {
		log.Errorf("vertex-import: read file failed: %v", errRead)
		return
	}
	var sa map[string]any
	if errUnmarshal := json.Unmarshal(data, &sa); errUnmarshal != nil {
		log.Errorf("vertex-import: invalid service account json: %v", errUnmarshal)
		return
	}
	// Validate and normalize private_key before saving
	normalizedSA, errFix := vertex.NormalizeServiceAccountMap(sa)
	if errFix != nil {
		log.Errorf("vertex-import: %v", errFix)
		return
	}
	sa = normalizedSA
	email, _ := sa["client_email"].(string)
	projectID, _ := sa["project_id"].(string)
	if strings.TrimSpace(projectID) == "" {
		log.Errorf("vertex-import: project_id missing in service account json")
		return
	}
	if strings.TrimSpace(email) == "" {
		// Keep empty email but warn
		log.Warn("vertex-import: client_email missing in service account json")
	}
	// Default location if not provided by user. Can be edited in the saved file later.
	location := "us-central1"

	// Normalize and validate prefix: must be a single segment (no "/" allowed).
	prefix = strings.TrimSpace(prefix)
	prefix = strings.Trim(prefix, "/")
	if prefix != "" && strings.Contains(prefix, "/") {
		log.Errorf("vertex-import: prefix must be a single segment (no '/' allowed): %q", prefix)
		return
	}

	// Include prefix in filename so importing the same project with different
	// prefixes creates separate credential files instead of overwriting.
	baseName := sanitizeFilePart(projectID)
	if prefix != "" {
		baseName = sanitizeFilePart(prefix) + "-" + baseName
	}
	fileName := fmt.Sprintf("vertex-%s.json", baseName)
	// Build auth record
	storage := &vertex.VertexCredentialStorage{
		ServiceAccount: sa,
		ProjectID:      projectID,
		Email:          email,
		Location:       location,
		Prefix:         prefix,
	}
	metadata := map[string]any{
		"service_account": sa,
		"project_id":      projectID,
		"email":           email,
		"location":        location,
		"type":            "vertex",
		"prefix":          prefix,
		"label":           labelForVertex(projectID, email),
	}
	record := &coreauth.Auth{
		ID:       fileName,
		Provider: "vertex",
		FileName: fileName,
		Storage:  storage,
		Metadata: metadata,
	}

	store := sdkAuth.GetTokenStore()
	if setter, ok := store.(interface{ SetBaseDir(string) }); ok {
		setter.SetBaseDir(cfg.AuthDir)
	}
	path, errSave := store.Save(context.Background(), record)
	if errSave != nil {
		log.Errorf("vertex-import: save credential failed: %v", errSave)
		return
	}
	fmt.Printf("Vertex credentials imported: %s\n", path)
}

func sanitizeFilePart(s string) string {
	out := strings.TrimSpace(s)
	replacers := []string{"/", "_", "\\", "_", ":", "_", " ", "-"}
	for i := 0; i < len(replacers); i += 2 {
		out = strings.ReplaceAll(out, replacers[i], replacers[i+1])
	}
	return out
}

func labelForVertex(projectID, email string) string {
	p := strings.TrimSpace(projectID)
	e := strings.TrimSpace(email)
	if p != "" && e != "" {
		return fmt.Sprintf("%s (%s)", p, e)
	}
	if p != "" {
		return p
	}
	if e != "" {
		return e
	}
	return "vertex"
}
