package config

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"
)

// APIKeys holds external service credentials.
type APIKeys struct {
	TPDBAPIKey      string `json:"tpdb_api_key"`
	AEAPIKey        string `json:"ae_api_key"`
	StashDBAPIKey   string `json:"stashdb_api_key"`
	StashDBEndpoint string `json:"stashdb_endpoint"`
}

const apiKeysFile = "config/api_keys.json"

var (
	keysMu sync.RWMutex
	cached *APIKeys
)

// GetAPIKeys returns the configured API keys, preferring the persisted file, falling back to environment variables.
func GetAPIKeys() APIKeys {
	keysMu.RLock()
	if cached != nil {
		defer keysMu.RUnlock()
		return *cached
	}
	keysMu.RUnlock()

	keys := APIKeys{}

	// Try file first.
	if b, err := os.ReadFile(apiKeysFile); err == nil {
		_ = json.Unmarshal(b, &keys)
	}

	// Fallback to env if fields are empty.
	if keys.TPDBAPIKey == "" {
		keys.TPDBAPIKey = os.Getenv("TPDB_API_KEY")
	}
	if keys.AEAPIKey == "" {
		keys.AEAPIKey = os.Getenv("AE_API_KEY")
	}
	if keys.StashDBAPIKey == "" {
		keys.StashDBAPIKey = os.Getenv("STASHDB_API_KEY")
	}
	if keys.StashDBEndpoint == "" {
		keys.StashDBEndpoint = os.Getenv("STASHDB_ENDPOINT")
	}
	if keys.StashDBEndpoint == "" {
		keys.StashDBEndpoint = "https://stashdb.org/graphql"
	}

	keysMu.Lock()
	cached = &keys
	keysMu.Unlock()

	return keys
}

// SaveAPIKeys persists API keys to disk (config/api_keys.json) and updates cache.
func SaveAPIKeys(keys APIKeys) error {
	keysMu.Lock()
	defer keysMu.Unlock()

	// Normalize whitespace.
	keys.TPDBAPIKey = strings.TrimSpace(keys.TPDBAPIKey)
	keys.AEAPIKey = strings.TrimSpace(keys.AEAPIKey)
	keys.StashDBAPIKey = strings.TrimSpace(keys.StashDBAPIKey)
	keys.StashDBEndpoint = strings.TrimSpace(keys.StashDBEndpoint)
	if keys.StashDBEndpoint == "" {
		keys.StashDBEndpoint = "https://stashdb.org/graphql"
	}

	if err := os.MkdirAll(filepath.Dir(apiKeysFile), 0o755); err != nil {
		return fmt.Errorf("create config dir: %w", err)
	}

	data, err := json.MarshalIndent(keys, "", "  ")
	if err != nil {
		return fmt.Errorf("marshal keys: %w", err)
	}

	if err := os.WriteFile(apiKeysFile, data, 0o600); err != nil {
		return fmt.Errorf("write keys file: %w", err)
	}

	cached = &keys
	return nil
}
