package config

import (
	"fmt"
	"net/url"
	"os"
	"strings"
	"time"
)

type Config struct {
	Server      ServerConfig      `envconfig:"server"`
	Database    DatabaseConfig    `envconfig:"database"`
	GITEA       GITEAConfig       `envconfig:"gitea"`
	Auth        AuthConfig        `envconfig:"auth"`
	Logging     LoggingConfig     `envconfig:"logging"`
	BACKBEAT    BackbeatConfig    `envconfig:"backbeat"`
	Docker      DockerConfig      `envconfig:"docker"`
	N8N         N8NConfig         `envconfig:"n8n"`
	OpenTelemetry OpenTelemetryConfig `envconfig:"opentelemetry"`
	Composer    ComposerConfig    `envconfig:"composer"`
}

type ServerConfig struct {
	ListenAddr         string        `envconfig:"LISTEN_ADDR" default:":8080"`
	ReadTimeout        time.Duration `envconfig:"READ_TIMEOUT" default:"30s"`
	WriteTimeout       time.Duration `envconfig:"WRITE_TIMEOUT" default:"30s"`
	ShutdownTimeout    time.Duration `envconfig:"SHUTDOWN_TIMEOUT" default:"30s"`
	AllowedOrigins     []string      `envconfig:"ALLOWED_ORIGINS" default:"http://localhost:3000,http://localhost:8080"`
	AllowedOriginsFile string        `envconfig:"ALLOWED_ORIGINS_FILE"`
}

type DatabaseConfig struct {
	Host         string `envconfig:"DB_HOST" default:"localhost"`
	Port         int    `envconfig:"DB_PORT" default:"5432"`
	Database     string `envconfig:"DB_NAME" default:"whoosh"`
	Username     string `envconfig:"DB_USER" default:"whoosh"`
	Password     string `envconfig:"DB_PASSWORD"`
	PasswordFile string `envconfig:"DB_PASSWORD_FILE"`
	SSLMode      string `envconfig:"DB_SSL_MODE" default:"disable"`
	URL          string `envconfig:"DB_URL"`
	AutoMigrate  bool   `envconfig:"DB_AUTO_MIGRATE" default:"false"`
	MaxOpenConns int    `envconfig:"DB_MAX_OPEN_CONNS" default:"25"`
	MaxIdleConns int    `envconfig:"DB_MAX_IDLE_CONNS" default:"5"`
}


type GITEAConfig struct {
	BaseURL          string `envconfig:"BASE_URL" required:"true"`
	Token            string `envconfig:"TOKEN"`
	TokenFile        string `envconfig:"TOKEN_FILE"`
	WebhookPath      string `envconfig:"WEBHOOK_PATH" default:"/webhooks/gitea"`
	WebhookToken     string `envconfig:"WEBHOOK_TOKEN"`
	WebhookTokenFile string `envconfig:"WEBHOOK_TOKEN_FILE"`
	
	// Fetch hardening options
	EagerFilter      bool `envconfig:"EAGER_FILTER" default:"true"`      // Pre-filter by labels at API level
	FullRescan       bool `envconfig:"FULL_RESCAN" default:"false"`     // Ignore since parameter for full rescan
	DebugURLs        bool `envconfig:"DEBUG_URLS" default:"false"`      // Log exact URLs being used
	MaxRetries       int  `envconfig:"MAX_RETRIES" default:"3"`         // Maximum retry attempts
	RetryDelay       time.Duration `envconfig:"RETRY_DELAY" default:"2s"` // Delay between retries
}

type AuthConfig struct {
	JWTSecret         string        `envconfig:"JWT_SECRET"`
	JWTSecretFile     string        `envconfig:"JWT_SECRET_FILE"`
	JWTExpiry         time.Duration `envconfig:"JWT_EXPIRY" default:"24h"`
	ServiceTokens     []string      `envconfig:"SERVICE_TOKENS"`
	ServiceTokensFile string        `envconfig:"SERVICE_TOKENS_FILE"`
}

type LoggingConfig struct {
	Level       string `envconfig:"LEVEL" default:"info"`
	Environment string `envconfig:"ENVIRONMENT" default:"production"`
}

type BackbeatConfig struct {
	Enabled     bool   `envconfig:"ENABLED" default:"true"`
	ClusterID   string `envconfig:"CLUSTER_ID" default:"chorus-production"`
	AgentID     string `envconfig:"AGENT_ID" default:"whoosh"`
	NATSUrl     string `envconfig:"NATS_URL" default:"nats://backbeat-nats:4222"`
}

type DockerConfig struct {
	Enabled bool   `envconfig:"ENABLED" default:"true"`
	Host    string `envconfig:"HOST" default:"unix:///var/run/docker.sock"`
}

type N8NConfig struct {
	BaseURL string `envconfig:"BASE_URL" default:"https://n8n.home.deepblack.cloud"`
}

type OpenTelemetryConfig struct {
	Enabled         bool   `envconfig:"ENABLED" default:"true"`
	ServiceName     string `envconfig:"SERVICE_NAME" default:"whoosh"`
	ServiceVersion  string `envconfig:"SERVICE_VERSION" default:"0.1.7"`
	Environment     string `envconfig:"ENVIRONMENT" default:"production"`
	JaegerEndpoint  string `envconfig:"JAEGER_ENDPOINT" default:"http://localhost:14268/api/traces"`
	SampleRate      float64 `envconfig:"SAMPLE_RATE" default:"1.0"`
}

type ComposerConfig struct {
	// Feature flags for experimental features
	EnableLLMClassification   bool `envconfig:"ENABLE_LLM_CLASSIFICATION" default:"false"`
	EnableLLMSkillAnalysis    bool `envconfig:"ENABLE_LLM_SKILL_ANALYSIS" default:"false"`
	EnableLLMTeamMatching     bool `envconfig:"ENABLE_LLM_TEAM_MATCHING" default:"false"`
	
	// Analysis features
	EnableComplexityAnalysis  bool `envconfig:"ENABLE_COMPLEXITY_ANALYSIS" default:"true"`
	EnableRiskAssessment      bool `envconfig:"ENABLE_RISK_ASSESSMENT" default:"true"`
	EnableAlternativeOptions  bool `envconfig:"ENABLE_ALTERNATIVE_OPTIONS" default:"false"`
	
	// Debug and monitoring
	EnableAnalysisLogging     bool `envconfig:"ENABLE_ANALYSIS_LOGGING" default:"true"`
	EnablePerformanceMetrics  bool `envconfig:"ENABLE_PERFORMANCE_METRICS" default:"true"`
	EnableFailsafeFallback    bool `envconfig:"ENABLE_FAILSAFE_FALLBACK" default:"true"`
	
	// LLM model configuration
	ClassificationModel string `envconfig:"CLASSIFICATION_MODEL" default:"llama3.1:8b"`
	SkillAnalysisModel  string `envconfig:"SKILL_ANALYSIS_MODEL" default:"llama3.1:8b"`
	MatchingModel       string `envconfig:"MATCHING_MODEL" default:"llama3.1:8b"`
	
	// Performance settings
	AnalysisTimeoutSecs int `envconfig:"ANALYSIS_TIMEOUT_SECS" default:"60"`
	SkillMatchThreshold float64 `envconfig:"SKILL_MATCH_THRESHOLD" default:"0.6"`
}

func readSecretFile(filePath string) (string, error) {
	if filePath == "" {
		return "", nil
	}
	
	content, err := os.ReadFile(filePath)
	if err != nil {
		return "", fmt.Errorf("failed to read secret file %s: %w", filePath, err)
	}
	
	return strings.TrimSpace(string(content)), nil
}

func (c *Config) loadSecrets() error {
	// Load database password from file if specified
	if c.Database.PasswordFile != "" {
		password, err := readSecretFile(c.Database.PasswordFile)
		if err != nil {
			return err
		}
		c.Database.Password = password
	}


	// Load GITEA token from file if specified
	if c.GITEA.TokenFile != "" {
		token, err := readSecretFile(c.GITEA.TokenFile)
		if err != nil {
			return err
		}
		c.GITEA.Token = token
	}

	// Load GITEA webhook token from file if specified
	if c.GITEA.WebhookTokenFile != "" {
		token, err := readSecretFile(c.GITEA.WebhookTokenFile)
		if err != nil {
			return err
		}
		c.GITEA.WebhookToken = token
	}

	// Load JWT secret from file if specified
	if c.Auth.JWTSecretFile != "" {
		secret, err := readSecretFile(c.Auth.JWTSecretFile)
		if err != nil {
			return err
		}
		c.Auth.JWTSecret = secret
	}

	// Load service tokens from file if specified
	if c.Auth.ServiceTokensFile != "" {
		tokens, err := readSecretFile(c.Auth.ServiceTokensFile)
		if err != nil {
			return err
		}
		c.Auth.ServiceTokens = strings.Split(tokens, ",")
		// Trim whitespace from each token
		for i, token := range c.Auth.ServiceTokens {
			c.Auth.ServiceTokens[i] = strings.TrimSpace(token)
		}
	}

	// Load allowed origins from file if specified
	if c.Server.AllowedOriginsFile != "" {
		origins, err := readSecretFile(c.Server.AllowedOriginsFile)
		if err != nil {
			return err
		}
		c.Server.AllowedOrigins = strings.Split(origins, ",")
		// Trim whitespace from each origin
		for i, origin := range c.Server.AllowedOrigins {
			c.Server.AllowedOrigins[i] = strings.TrimSpace(origin)
		}
	}

	return nil
}

func (c *Config) Validate() error {
	// Load secrets from files first
	if err := c.loadSecrets(); err != nil {
		return err
	}

	// Validate required database password
	if c.Database.Password == "" {
		return fmt.Errorf("database password is required (set WHOOSH_DATABASE_DB_PASSWORD or WHOOSH_DATABASE_DB_PASSWORD_FILE)")
	}

	// Build database URL if not provided
	if c.Database.URL == "" {
		c.Database.URL = fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s",
			url.QueryEscape(c.Database.Username),
			url.QueryEscape(c.Database.Password),
			c.Database.Host,
			c.Database.Port,
			url.QueryEscape(c.Database.Database),
			c.Database.SSLMode,
		)
	}

	if c.GITEA.BaseURL == "" {
		return fmt.Errorf("GITEA base URL is required")
	}

	if c.GITEA.Token == "" {
		return fmt.Errorf("GITEA token is required (set WHOOSH_GITEA_TOKEN or WHOOSH_GITEA_TOKEN_FILE)")
	}

	if c.GITEA.WebhookToken == "" {
		return fmt.Errorf("GITEA webhook token is required (set WHOOSH_GITEA_WEBHOOK_TOKEN or WHOOSH_GITEA_WEBHOOK_TOKEN_FILE)")
	}

	if c.Auth.JWTSecret == "" {
		return fmt.Errorf("JWT secret is required (set WHOOSH_AUTH_JWT_SECRET or WHOOSH_AUTH_JWT_SECRET_FILE)")
	}

	if len(c.Auth.ServiceTokens) == 0 {
		return fmt.Errorf("at least one service token is required (set WHOOSH_AUTH_SERVICE_TOKENS or WHOOSH_AUTH_SERVICE_TOKENS_FILE)")
	}

	return nil
}