package config

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"time"
)

type Config struct {
	AppName                   string
	Environment               string
	APIPort                   string
	DatabaseURL               string
	StorefrontURL             string
	AllowedOrigins            []string
	ResendAPIKey              string
	ResendOrderFrom           string
	ResendForward             string
	ClientDashboardUser       string
	ClientDashboardPass       string
	ClientDashboardSecret     string
	ClientDashboardSessionTTL time.Duration
	StripeSecretKey           string
	StripeWebhookSecret       string
	StripePriceID             string
	StripeCurrency            string
	RoyalPopUnitAmount        int64
	RoyalPopRetailAmount      int64
	ShutdownTimeout           time.Duration
}

func Load() *Config {
	environment := getEnv("GO_ENV", "development")
	storefrontURL := getEnv("API_ALLOWED_ORIGIN", getEnv("STOREFRONT_URL", "http://localhost:4321"))
	clientDashboardUser := getEnv("CLIENT_DASHBOARD_USERNAME", "")
	clientDashboardPass := getEnv("CLIENT_DASHBOARD_PASSWORD", "")

	if strings.EqualFold(environment, "development") {
		if strings.TrimSpace(clientDashboardUser) == "" {
			clientDashboardUser = "client"
		}
		if strings.TrimSpace(clientDashboardPass) == "" {
			clientDashboardPass = "royalpop-dev"
		}
	}

	return &Config{
		AppName:                   getEnv("APP_NAME", "royal-pop"),
		Environment:               environment,
		APIPort:                   getEnv("BACKEND_API_PORT", "8081"),
		DatabaseURL:               getEnv("DATABASE_URL", "postgres://royalpop:royalpop_dev_password@localhost:5432/royalpop?sslmode=disable"),
		StorefrontURL:             storefrontURL,
		AllowedOrigins:            splitCSV(getEnv("API_ALLOWED_ORIGINS", storefrontURL)),
		ResendAPIKey:              getEnv("RESEND_API_KEY", ""),
		ResendOrderFrom:           getEnv("RESEND_ORDER_FROM", "orders@royal-pop-accessory.com"),
		ResendForward:             getEnv("RESEND_FORWARD", ""),
		ClientDashboardUser:       clientDashboardUser,
		ClientDashboardPass:       clientDashboardPass,
		ClientDashboardSecret:     getEnv("CLIENT_DASHBOARD_SESSION_SECRET", ""),
		ClientDashboardSessionTTL: getDurationEnv("CLIENT_DASHBOARD_SESSION_TTL", 12*time.Hour),
		StripeSecretKey:           getEnv("STRIPE_SECRET_KEY", ""),
		StripeWebhookSecret:       getEnv("STRIPE_WEBHOOK_SECRET", ""),
		StripePriceID:             getEnv("STRIPE_PRICE_ID", "price_1TkPnvCpoCwKMSycHiQBPVms"),
		StripeCurrency:            strings.ToLower(getEnv("STRIPE_CURRENCY", "gbp")),
		RoyalPopUnitAmount:        getInt64Env("ROYAL_POP_UNIT_AMOUNT", 4999),
		RoyalPopRetailAmount:      getInt64Env("ROYAL_POP_RETAIL_AMOUNT", 8999),
		ShutdownTimeout:           getDurationEnv("BACKEND_SHUTDOWN_TIMEOUT", 10*time.Second),
	}
}

func (c *Config) Address() string {
	return fmt.Sprintf(":%s", c.APIPort)
}

func (c *Config) IsDevelopment() bool {
	return strings.EqualFold(c.Environment, "development")
}

func (c *Config) ClientDashboardEnabled() bool {
	if c == nil {
		return false
	}

	return strings.TrimSpace(c.ClientDashboardUser) != "" && strings.TrimSpace(c.ClientDashboardPass) != ""
}

func (c *Config) ClientDashboardSigningSecret() string {
	if c == nil || !c.ClientDashboardEnabled() {
		return ""
	}

	if secret := strings.TrimSpace(c.ClientDashboardSecret); secret != "" {
		return secret
	}

	return strings.Join([]string{c.AppName, c.ClientDashboardUser, c.ClientDashboardPass}, "|")
}

func getEnv(key, fallback string) string {
	if value, exists := os.LookupEnv(key); exists && strings.TrimSpace(value) != "" {
		return value
	}

	return fallback
}

func getDurationEnv(key string, fallback time.Duration) time.Duration {
	value, exists := os.LookupEnv(key)
	if !exists {
		return fallback
	}

	parsed, err := time.ParseDuration(value)
	if err != nil {
		return fallback
	}

	return parsed
}

func getInt64Env(key string, fallback int64) int64 {
	value, exists := os.LookupEnv(key)
	if !exists || strings.TrimSpace(value) == "" {
		return fallback
	}

	parsed, err := strconv.ParseInt(strings.TrimSpace(value), 10, 64)
	if err != nil {
		return fallback
	}

	return parsed
}

func splitCSV(raw string) []string {
	parts := strings.Split(raw, ",")
	values := make([]string, 0, len(parts))

	for _, part := range parts {
		trimmed := strings.TrimSpace(part)
		if trimmed == "" {
			continue
		}
		values = append(values, trimmed)
	}

	if len(values) == 0 {
		return []string{"*"}
	}

	return values
}
