package config

import (
	"encoding/json"
	"os"
)

// Config represents the application configuration
type Config struct {
	Server       ServerConfig       `json:"server"`
	WhatsApp     []WhatsAppConfig   `json:"whatsapp"`
	Hooks        []Hook             `json:"hooks"`
	Database     DatabaseConfig     `json:"database,omitempty"`
	Media        MediaConfig        `json:"media"`
	EventLogger  EventLoggerConfig  `json:"event_logger,omitempty"`
	MessageCache MessageCacheConfig `json:"message_cache,omitempty"`
	LogLevel     string             `json:"log_level"`
}

// ServerConfig holds server-specific configuration
type ServerConfig struct {
	Host               string    `json:"host"`
	Port               int       `json:"port"`
	DefaultCountryCode string    `json:"default_country_code,omitempty"`
	Username           string    `json:"username,omitempty"`
	Password           string    `json:"password,omitempty"`
	AuthKey            string    `json:"auth_key,omitempty"`
	JWTSecret          string    `json:"jwt_secret,omitempty"` // Secret for JWT signing
	UIPath             string    `json:"ui_path,omitempty"`    // Filesystem path to built frontend files (default: web/dist)
	TLS                TLSConfig `json:"tls,omitempty"`
}

// TLSConfig holds TLS/HTTPS configuration
type TLSConfig struct {
	Enabled  bool   `json:"enabled"`             // Enable HTTPS
	Mode     string `json:"mode"`                // "self-signed", "custom", or "autocert"
	CertFile string `json:"cert_file,omitempty"` // Path to certificate file (for custom mode)
	KeyFile  string `json:"key_file,omitempty"`  // Path to key file (for custom mode)

	// Self-signed certificate options
	CertDir string `json:"cert_dir,omitempty"` // Directory to store generated certificates

	// Let's Encrypt / autocert options
	Domain     string `json:"domain,omitempty"`     // Domain name for Let's Encrypt
	Email      string `json:"email,omitempty"`      // Email for Let's Encrypt notifications
	CacheDir   string `json:"cache_dir,omitempty"`  // Cache directory for autocert
	Production bool   `json:"production,omitempty"` // Use Let's Encrypt production (default: staging)
}

// WhatsAppConfig holds configuration for a WhatsApp account
type WhatsAppConfig struct {
	ID          string             `json:"id"`
	Type        string             `json:"type"` // "whatsmeow" or "business-api"
	PhoneNumber string             `json:"phone_number"`
	SessionPath string             `json:"session_path,omitempty"`
	ShowQR      bool               `json:"show_qr,omitempty"`
	Disabled    bool               `json:"disabled,omitempty"` // If true, account won't be connected
	BusinessAPI *BusinessAPIConfig `json:"business_api,omitempty"`
}

// BusinessAPIConfig holds configuration for WhatsApp Business API
type BusinessAPIConfig struct {
	PhoneNumberID     string `json:"phone_number_id"`
	AccessToken       string `json:"access_token"`
	WABAId            string `json:"waba_id,omitempty"`             // WhatsApp Business Account ID (resolved at connect time)
	BusinessAccountID string `json:"business_account_id,omitempty"` // Facebook Business Manager ID (optional)
	APIVersion        string `json:"api_version,omitempty"`         // Default: v21.0
	WebhookPath       string `json:"webhook_path,omitempty"`
	VerifyToken       string `json:"verify_token,omitempty"`
}

// Hook represents a registered webhook
type Hook struct {
	ID            string            `json:"id"`
	Name          string            `json:"name"`
	URL           string            `json:"url"`
	Method        string            `json:"method"`
	Headers       map[string]string `json:"headers,omitempty"`
	Active        bool              `json:"active"`
	Events        []string          `json:"events,omitempty"`
	Description   string            `json:"description,omitempty"`
	AllowInsecure bool              `json:"allow_insecure,omitempty"` // Skip TLS certificate verification
}

// DatabaseConfig holds database connection information
type DatabaseConfig struct {
	Type       string `json:"type"`
	Host       string `json:"host"`
	Port       int    `json:"port"`
	Username   string `json:"username"`
	Password   string `json:"password"`
	Database   string `json:"database"`
	SQLitePath string `json:"sqlite_path,omitempty"` // Path to SQLite database file
}

// MediaConfig holds media storage and delivery configuration
type MediaConfig struct {
	DataPath string `json:"data_path"`
	Mode     string `json:"mode"`               // "base64", "link", or "both"
	BaseURL  string `json:"base_url,omitempty"` // Base URL for media links
}

// EventLoggerConfig holds event logging configuration
type EventLoggerConfig struct {
	Enabled bool     `json:"enabled"`
	Targets []string `json:"targets"` // "file", "sqlite", "postgres", "mqtt"

	// File-based logging
	FileDir string `json:"file_dir,omitempty"` // Base directory for event files

	// Database logging (uses main Database config for connection)
	TableName string `json:"table_name,omitempty"` // Table name for event logs (default: "event_logs")

	// MQTT logging
	MQTT MQTTConfig `json:"mqtt,omitempty"` // MQTT broker configuration
}

// MQTTConfig holds MQTT broker configuration
type MQTTConfig struct {
	Broker      string   `json:"broker"`                 // MQTT broker URL (e.g., "tcp://localhost:1883")
	ClientID    string   `json:"client_id,omitempty"`    // Client ID (auto-generated if empty)
	Username    string   `json:"username,omitempty"`     // Username for authentication
	Password    string   `json:"password,omitempty"`     // Password for authentication
	TopicPrefix string   `json:"topic_prefix,omitempty"` // Topic prefix (default: "whatshooked")
	QoS         int      `json:"qos,omitempty"`          // Quality of Service (0, 1, or 2; default: 1)
	Retained    bool     `json:"retained,omitempty"`     // Retain messages on broker
	Events      []string `json:"events,omitempty"`       // Events to publish (empty = all events)
	Subscribe   bool     `json:"subscribe,omitempty"`    // Enable subscription for sending messages
}

// MessageCacheConfig holds message cache configuration
type MessageCacheConfig struct {
	Enabled    bool   `json:"enabled"`                // Enable message caching
	Storage    string `json:"storage,omitempty"`      // Storage backend: "database" (default) or "disk"
	DataPath   string `json:"data_path,omitempty"`    // Directory to store cached events
	MaxAgeDays int    `json:"max_age_days,omitempty"` // Maximum age in days before purging (default: 7)
	MaxEvents  int    `json:"max_events,omitempty"`   // Maximum number of events to cache (default: 10000)
}

// Load reads configuration from a file
func Load(path string) (*Config, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}

	var cfg Config
	if err := json.Unmarshal(data, &cfg); err != nil {
		return nil, err
	}

	// Set defaults
	if cfg.LogLevel == "" {
		cfg.LogLevel = "info"
	}
	if cfg.Server.Host == "" {
		cfg.Server.Host = "0.0.0.0"
	}
	if cfg.Server.Port == 0 {
		cfg.Server.Port = 8080
	}
	if cfg.Server.JWTSecret == "" {
		cfg.Server.JWTSecret = "change-me-in-production" // Default for development
	}
	if cfg.Server.UIPath == "" {
		cfg.Server.UIPath = "web/dist" // Default filesystem path to built frontend
	}
	if cfg.Media.DataPath == "" {
		cfg.Media.DataPath = "./data/media"
	}
	if cfg.Media.Mode == "" {
		cfg.Media.Mode = "link"
	}
	if cfg.EventLogger.FileDir == "" {
		cfg.EventLogger.FileDir = "./data/events"
	}
	if cfg.EventLogger.TableName == "" {
		cfg.EventLogger.TableName = "event_logs"
	}
	if cfg.Database.SQLitePath == "" {
		cfg.Database.SQLitePath = "./data/events.db"
	}

	// Default WhatsApp account type to whatsmeow for backwards compatibility
	for i := range cfg.WhatsApp {
		if cfg.WhatsApp[i].Type == "" {
			cfg.WhatsApp[i].Type = "whatsmeow"
		}
		// Set default API version for Business API
		if cfg.WhatsApp[i].Type == "business-api" && cfg.WhatsApp[i].BusinessAPI != nil {
			if cfg.WhatsApp[i].BusinessAPI.APIVersion == "" {
				cfg.WhatsApp[i].BusinessAPI.APIVersion = "v21.0"
			}
		}
	}

	// Set TLS defaults if enabled
	if cfg.Server.TLS.Enabled {
		if cfg.Server.TLS.Mode == "" {
			cfg.Server.TLS.Mode = "self-signed"
		}
		if cfg.Server.TLS.CertDir == "" {
			cfg.Server.TLS.CertDir = "./data/certs"
		}
		if cfg.Server.TLS.CacheDir == "" {
			cfg.Server.TLS.CacheDir = "./data/autocert"
		}
	}

	// Set message cache defaults
	if cfg.MessageCache.Storage == "" {
		cfg.MessageCache.Storage = "database"
	}
	if cfg.MessageCache.DataPath == "" {
		cfg.MessageCache.DataPath = "./data/message_cache"
	}
	if cfg.MessageCache.MaxAgeDays == 0 {
		cfg.MessageCache.MaxAgeDays = 7
	}
	if cfg.MessageCache.MaxEvents == 0 {
		cfg.MessageCache.MaxEvents = 10000
	}

	return &cfg, nil
}

// Save writes configuration to a file
func Save(path string, cfg *Config) error {
	data, err := json.MarshalIndent(cfg, "", "  ")
	if err != nil {
		return err
	}

	return os.WriteFile(path, data, 0644)
}
