package acceptance

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"testing"
	"time"
)

type Config struct {
	StagingURL    string
	AdminEmail    string
	AdminPassword string
	UserEmail     string
	UserPassword  string
	NodeSecret    string
	NodeServerID  string
	NodeProtocol  string
	RunID         string
	ReportPath    string
	SeedSQLPath   string
	DB            DBConfig
	Redis         RedisConfig
	HTTPTimeout   time.Duration
}

type DBConfig struct {
	Host     string
	User     string
	Password string
	Name     string
}

type RedisConfig struct {
	Addr     string
	Password string
	DB       int
}

var testConfig = Config{
	HTTPTimeout:  15 * time.Second,
	NodeServerID: "31",
	NodeProtocol: "trojan",
	SeedSQLPath:  "fixtures/seed.sql",
}

func init() {
	flag.StringVar(&testConfig.StagingURL, "staging-url", getenv("STAGING_BASE_URL", "https://tapi.hifast.biz"), "staging base URL")
	flag.StringVar(&testConfig.AdminEmail, "admin-email", os.Getenv("ACCEPTANCE_ADMIN_EMAIL"), "admin login email")
	flag.StringVar(&testConfig.AdminPassword, "admin-password", os.Getenv("ACCEPTANCE_ADMIN_PASSWORD"), "admin login password")
	flag.StringVar(&testConfig.UserEmail, "user-email", os.Getenv("ACCEPTANCE_USER_EMAIL"), "user login email")
	flag.StringVar(&testConfig.UserPassword, "user-password", os.Getenv("ACCEPTANCE_USER_PASSWORD"), "user login password")
	flag.StringVar(&testConfig.NodeSecret, "node-secret", os.Getenv("ACCEPTANCE_NODE_SECRET"), "node secret; read from staging DB when omitted")
	flag.StringVar(&testConfig.NodeServerID, "node-server-id", getenv("ACCEPTANCE_NODE_SERVER_ID", testConfig.NodeServerID), "server id for node smoke tests")
	flag.StringVar(&testConfig.NodeProtocol, "node-protocol", getenv("ACCEPTANCE_NODE_PROTOCOL", testConfig.NodeProtocol), "server protocol for node smoke tests")
	flag.StringVar(&testConfig.RunID, "run-id", getenv("ACCEPTANCE_RUN_ID", defaultRunID()), "acceptance run id")
	flag.StringVar(&testConfig.ReportPath, "report-path", os.Getenv("ACCEPTANCE_REPORT_PATH"), "optional JSON report path")
	flag.StringVar(&testConfig.SeedSQLPath, "seed-sql", getenv("ACCEPTANCE_SEED_SQL", testConfig.SeedSQLPath), "seed SQL file path")
	flag.StringVar(&testConfig.DB.Host, "db-host", os.Getenv("STAGING_DB_HOST"), "staging DB host")
	flag.StringVar(&testConfig.DB.User, "db-user", os.Getenv("STAGING_DB_USER"), "staging DB user")
	flag.StringVar(&testConfig.DB.Password, "db-password", os.Getenv("STAGING_DB_PASSWORD"), "staging DB password")
	flag.StringVar(&testConfig.DB.Name, "db-name", os.Getenv("STAGING_DB_NAME"), "staging DB name")
	flag.StringVar(&testConfig.Redis.Addr, "redis-addr", os.Getenv("STAGING_REDIS_ADDR"), "staging Redis addr")
	flag.StringVar(&testConfig.Redis.Password, "redis-password", os.Getenv("STAGING_REDIS_PASSWORD"), "staging Redis password")
	flag.IntVar(&testConfig.Redis.DB, "redis-db", getenvInt("STAGING_REDIS_DB", 0), "staging Redis DB")
}

func cfg(t *testing.T) Config {
	t.Helper()
	if strings.TrimSpace(testConfig.StagingURL) == "" {
		t.Fatal("staging-url is required")
	}
	return testConfig
}

func requireSecret(t *testing.T, name string, value string) string {
	t.Helper()
	if strings.TrimSpace(value) == "" {
		t.Skipf("%s is required for this acceptance test", name)
	}
	return value
}

func getenv(key string, fallback string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return fallback
}

func getenvInt(key string, fallback int) int {
	value := os.Getenv(key)
	if value == "" {
		return fallback
	}
	var parsed int
	if _, err := fmt.Sscanf(value, "%d", &parsed); err != nil {
		return fallback
	}
	return parsed
}

func defaultRunID() string {
	runID := os.Getenv("GITHUB_RUN_ID")
	attempt := getenv("GITHUB_RUN_ATTEMPT", "1")
	if runID == "" {
		return "qa_local"
	}
	return "qa_" + runID + "_" + attempt
}
