// Package admin gère la configuration et les permissions de l'interface d'administration.
package admin

import (
	"fmt"
	"os"
	"strings"

	"gopkg.in/yaml.v3"
)

// AdminConfig représente la configuration complète de l'admin.
type AdminConfig struct {
	Session   SessionConfig   `yaml:"session"`
	RateLimit RateLimitConfig `yaml:"rate_limit"`
	Users     []AdminUser     `yaml:"users"`
}

// SessionConfig configure les sessions.
type SessionConfig struct {
	SecretFile string `yaml:"secret_file"`
	MaxAge     int    `yaml:"max_age"`      // secondes
	CookieName string `yaml:"cookie_name"`
	Secret     string `yaml:"-"` // chargé depuis fichier
}

// RateLimitConfig configure le rate limiting.
type RateLimitConfig struct {
	LoginMax    int `yaml:"login_max"`
	LoginWindow int `yaml:"login_window"` // secondes
}

// AdminUser représente un utilisateur admin.
type AdminUser struct {
	Username     string   `yaml:"username"`
	PasswordHash string   `yaml:"password_hash"`
	Role         string   `yaml:"role"`
	Email        string   `yaml:"email"`
	Apps         []string `yaml:"apps,omitempty"`        // pour app_admin
	Permissions  []string `yaml:"permissions,omitempty"` // pour app_admin
}

// IsSuperAdmin retourne true si l'utilisateur est super_admin.
func (u *AdminUser) IsSuperAdmin() bool {
	return u.Role == "super_admin"
}

// LoadAdminConfig charge la configuration admin depuis un fichier YAML.
func LoadAdminConfig(path string) (*AdminConfig, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("read admin config: %w", err)
	}

	var cfg AdminConfig
	if err := yaml.Unmarshal(data, &cfg); err != nil {
		return nil, fmt.Errorf("parse admin config: %w", err)
	}

	// Valeurs par défaut
	if cfg.Session.MaxAge == 0 {
		cfg.Session.MaxAge = 3600 // 1 heure
	}
	if cfg.Session.CookieName == "" {
		cfg.Session.CookieName = "sogoms_admin_sid"
	}
	if cfg.RateLimit.LoginMax == 0 {
		cfg.RateLimit.LoginMax = 5
	}
	if cfg.RateLimit.LoginWindow == 0 {
		cfg.RateLimit.LoginWindow = 60
	}

	// Charger le secret de session depuis le fichier
	if cfg.Session.SecretFile != "" {
		secretData, err := os.ReadFile(cfg.Session.SecretFile)
		if err != nil {
			return nil, fmt.Errorf("read session secret: %w", err)
		}
		cfg.Session.Secret = strings.TrimSpace(string(secretData))
	}

	// Valider
	if len(cfg.Users) == 0 {
		return nil, fmt.Errorf("no users defined")
	}
	if cfg.Session.Secret == "" {
		return nil, fmt.Errorf("session secret is required")
	}

	return &cfg, nil
}

// GetUser retourne un utilisateur par son username.
func (cfg *AdminConfig) GetUser(username string) *AdminUser {
	for i := range cfg.Users {
		if cfg.Users[i].Username == username {
			return &cfg.Users[i]
		}
	}
	return nil
}

// GetUserByEmail retourne un utilisateur par son email.
func (cfg *AdminConfig) GetUserByEmail(email string) *AdminUser {
	for i := range cfg.Users {
		if cfg.Users[i].Email == email {
			return &cfg.Users[i]
		}
	}
	return nil
}
