// Package config provides the configuration schema and loader for agents.
package config

import "time"

// AgentConfig is the root configuration for a single agent.
type AgentConfig struct {
	Agent       AgentMeta      `yaml:"agent"`
	Personality PersonalityCfg `yaml:"personality"`
	LLM         LLMCfg         `yaml:"llm"`
	Tools       ToolsCfg       `yaml:"tools"`
	Matrix      MatrixCfg      `yaml:"matrix"`
	SSH         SSHCfg         `yaml:"ssh"`
	Security    SecurityCfg    `yaml:"security"`
	Schedules   []ScheduleCfg  `yaml:"schedules"`
	Storage     StorageCfg     `yaml:"storage"`
	Memory      MemoryCfg      `yaml:"memory"`
	Skills      SkillsCfg      `yaml:"skills"`
}

// ── Identity ──────────────────────────────────────────────────────────────

type AgentMeta struct {
	ID          string   `yaml:"id"`
	Name        string   `yaml:"name"`
	Version     string   `yaml:"version"`
	Type        string   `yaml:"type"`        // "agent" (default) or "robot" (command-only, no LLM)
	Enabled     bool     `yaml:"enabled"`
	Template    bool     `yaml:"template"`    // if true, launcher will skip this agent
	Description string   `yaml:"description"`
	Tags        []string `yaml:"tags"`
}

// ── Personality ───────────────────────────────────────────────────────────

type PersonalityCfg struct {
	// --- campos existentes (sin cambios) ---
	Tone               string            `yaml:"tone"`
	Verbosity          string            `yaml:"verbosity"`
	Language           string            `yaml:"language"`
	LanguagesSupported []string          `yaml:"languages_supported"`
	EmojiStyle         string            `yaml:"emoji_style"`
	Prefix             string            `yaml:"prefix"`
	ErrorStyle         string            `yaml:"error_style"`
	Templates          TemplatesCfg      `yaml:"templates"`
	Behavior           BehaviorCfg       `yaml:"behavior"`

	// --- NUEVOS campos ---
	// Identidad narrativa
	Role          string   `yaml:"role"`           // rol principal: "asistente general", "devops engineer", "analista de datos"
	Backstory     string   `yaml:"backstory"`      // breve historia/contexto del personaje (1-3 frases)
	Expertise     []string `yaml:"expertise"`      // areas de experiencia: ["linux", "docker", "monitoring"]
	Limitations   []string `yaml:"limitations"`    // que NO sabe o no debe intentar

	// Estilo de comunicacion
	Communication CommunicationCfg `yaml:"communication"`

	// Directivas de comportamiento en texto libre
	CustomDirectives []string `yaml:"custom_directives"` // instrucciones adicionales para el system prompt
}

type TemplatesCfg struct {
	Greeting         string `yaml:"greeting"`
	UnknownCommand   string `yaml:"unknown_command"`
	PermissionDenied string `yaml:"permission_denied"`
	Error            string `yaml:"error"`
	Success          string `yaml:"success"`
	Busy             string `yaml:"busy"`
}

type BehaviorCfg struct {
	Proactive          bool `yaml:"proactive"`
	AskConfirmation    bool `yaml:"ask_confirmation"`
	ShowReasoning      bool `yaml:"show_reasoning"`
	ThreadReplies      bool `yaml:"thread_replies"`
	TypingIndicator    bool `yaml:"typing_indicator"`
	AcknowledgeReceipt bool `yaml:"acknowledge_receipt"`
}

// CommunicationCfg define como se expresa el agente mas alla del tone basico.
type CommunicationCfg struct {
	Formality     string   `yaml:"formality"`      // formal | semiformal | casual | coloquial
	Humor         string   `yaml:"humor"`          // none | subtle | moderate | frequent
	Personality   string   `yaml:"personality"`    // analytical | creative | pragmatic | empathetic | assertive
	ResponseStyle string   `yaml:"response_style"` // structured | conversational | bullet_points | narrative
	Quirks        []string `yaml:"quirks"`         // rasgos unicos: ["usa analogias de cocina", "cita a Linus Torvalds"]
	AvoidTopics   []string `yaml:"avoid_topics"`   // temas que evita o redirige
	Catchphrases  []string `yaml:"catchphrases"`   // frases tipicas que usa ocasionalmente
}

// ── LLM ───────────────────────────────────────────────────────────────────

type LLMCfg struct {
	Primary   LLMProviderCfg `yaml:"primary"`
	Fallback  LLMProviderCfg `yaml:"fallback"`
	Reasoning LLMReasoningCfg `yaml:"reasoning"`
	ToolUse   LLMToolUseCfg   `yaml:"tool_use"`
	RateLimit LLMRateLimitCfg `yaml:"rate_limit"`
}

type LLMProviderCfg struct {
	Provider    string  `yaml:"provider"`
	Model       string  `yaml:"model"`
	APIKeyEnv   string  `yaml:"api_key_env"`
	BaseURL     string  `yaml:"base_url"`
	MaxTokens   int     `yaml:"max_tokens"`
	Temperature float64 `yaml:"temperature"`

	// ClaudeCode holds configuration for the claude-code provider (claude -p).
	ClaudeCode ClaudeCodeCfg `yaml:"claude_code"`
}

// ClaudeCodeCfg configures the claude -p subprocess provider.
type ClaudeCodeCfg struct {
	Binary          string        `yaml:"binary"`           // path to claude binary (default: "claude")
	Timeout         time.Duration `yaml:"timeout"`          // subprocess timeout (default: 5m)
	DisableTools    bool          `yaml:"disable_tools"`    // pass --tools "" to disable all internal tools
	AllowedTools    []string      `yaml:"allowed_tools"`    // tools claude -p can use internally (e.g. Bash, Read, Edit)
	DisallowedTools []string      `yaml:"disallowed_tools"` // tools to block
	WorkingDir      string        `yaml:"working_dir"`      // working directory for claude -p
	PermissionMode  string        `yaml:"permission_mode"`  // default, acceptEdits, bypassPermissions, plan
	Model           string        `yaml:"model"`            // inner model: sonnet, opus, haiku, or full name
	FallbackModel   string        `yaml:"fallback_model"`   // fallback model if primary is overloaded
	SessionID       string        `yaml:"session_id"`       // fixed session ID for continuity
	AddDirs         []string      `yaml:"add_dirs"`         // additional directories accessible
}

type LLMReasoningCfg struct {
	SystemPromptFile string `yaml:"system_prompt_file"`
	ContextWindow    int    `yaml:"context_window"`
	MemoryMessages   int    `yaml:"memory_messages"`
}

type LLMToolUseCfg struct {
	Enabled       bool `yaml:"enabled"`
	MaxIterations int  `yaml:"max_iterations"`
	ParallelCalls bool `yaml:"parallel_calls"`
}

type LLMRateLimitCfg struct {
	RequestsPerMinute  int `yaml:"requests_per_minute"`
	TokensPerMinute    int `yaml:"tokens_per_minute"`
	ConcurrentRequests int `yaml:"concurrent_requests"`
}

// ── Tools ─────────────────────────────────────────────────────────────────

type ToolsCfg struct {
	SSH             SSHToolCfg             `yaml:"ssh"`
	HTTP            HTTPToolCfg            `yaml:"http"`
	Scripts         ScriptsCfg             `yaml:"scripts"`
	FileOps         FileOpsCfg             `yaml:"file_ops"`
	Matrix          MatrixToolCfg          `yaml:"matrix_send"`
	MCP             MCPToolCfg             `yaml:"mcp"`
	Memory          MemoryToolCfg          `yaml:"memory"`
	Knowledge       KnowledgeToolCfg       `yaml:"knowledge"`
	SharedKnowledge SharedKnowledgeToolCfg `yaml:"shared_knowledge"`
	Skills          SkillsToolCfg          `yaml:"skills"`
	IMDb            IMDbToolCfg            `yaml:"imdb"`
}

type MatrixToolCfg struct {
	AllowedRooms []string `yaml:"allowed_rooms"` // if non-empty, only these room IDs can be targeted
}

type KnowledgeToolCfg struct {
	Enabled bool   `yaml:"enabled"`
	Dir     string `yaml:"dir"` // default: "./knowledge" (relative to agent dir)
}

type SharedKnowledgeToolCfg struct {
	Enabled bool   `yaml:"enabled"` // default false
	Dir     string `yaml:"dir"`     // default "knowledges" (relative to project root)
	DBPath  string `yaml:"db_path"` // default "knowledges/data/knowledge.db"
}

type SSHToolCfg struct {
	Enabled             bool          `yaml:"enabled"`
	AllowedTargets      []string      `yaml:"allowed_targets"`
	AllowedCommands     []string      `yaml:"allowed_commands"`     // allowlist: if non-empty, only these command prefixes are permitted
	ForbiddenCommands   []string      `yaml:"forbidden_commands"`
	Timeout             time.Duration `yaml:"timeout"`
	MaxConcurrent       int           `yaml:"max_concurrent"`
	RequireConfirmation []string      `yaml:"require_confirmation"`
}

type HTTPToolCfg struct {
	Enabled        bool          `yaml:"enabled"`
	AllowedDomains []string      `yaml:"allowed_domains"`
	Timeout        time.Duration `yaml:"timeout"`
	MaxRetries     int           `yaml:"max_retries"`
}

type ScriptsCfg struct {
	Enabled    bool          `yaml:"enabled"`
	ScriptsDir string        `yaml:"scripts_dir"`
	Allowed    []string      `yaml:"allowed"`
	Timeout    time.Duration `yaml:"timeout"`
	Sandbox    bool          `yaml:"sandbox"`
}

type FileOpsCfg struct {
	Enabled      bool     `yaml:"enabled"`
	AllowedPaths []string `yaml:"allowed_paths"`
	ReadOnly     bool     `yaml:"read_only"`
}

type MCPToolCfg struct {
	Enabled bool            `yaml:"enabled"`
	Servers []MCPServerCfg  `yaml:"servers"`
	Expose  MCPExposeCfg    `yaml:"expose"`
}

type MCPServerCfg struct {
	Name      string            `yaml:"name"`       // nombre logico del servidor
	Transport string            `yaml:"transport"`  // "stdio" | "sse" (default: auto-detect)
	Command   string            `yaml:"command"`    // stdio: comando a ejecutar
	Args      []string          `yaml:"args"`       // stdio: argumentos del comando
	Env       map[string]string `yaml:"env"`        // stdio: variables de entorno extra
	URL       string            `yaml:"url"`        // sse: URL del servidor
	Headers   map[string]string `yaml:"headers"`    // sse: headers HTTP extra (auth, etc.)
	Tools     []string          `yaml:"tools"`      // filtro: solo exponer estas tools (vacio = todas)
	Prefix    string            `yaml:"prefix"`     // prefijo para nombres de tools (evitar colisiones)
	Timeout   time.Duration     `yaml:"timeout"`    // timeout por llamada (default: 30s)
}

type MCPExposeCfg struct {
	Port  int      `yaml:"port"`
	Tools []string `yaml:"tools"`
}

// ── Matrix ────────────────────────────────────────────────────────────────

type MatrixCfg struct {
	Homeserver      string         `yaml:"homeserver"`
	UserID          string         `yaml:"user_id"`
	AccessTokenEnv  string         `yaml:"access_token_env"`
	DeviceID        string         `yaml:"device_id"`
	Encryption      EncryptionCfg  `yaml:"encryption"`
	Rooms           RoomsCfg       `yaml:"rooms"`
	Filters         FiltersCfg     `yaml:"filters"`
	Threads         ThreadsCfg     `yaml:"threads"`
}

// ThreadsCfg controls Matrix thread support (m.thread).
type ThreadsCfg struct {
	Enabled    bool `yaml:"enabled"`     // respond in threads when message is in a thread (default true)
	AutoThread bool `yaml:"auto_thread"` // auto-create a thread for each new conversation (default false)
}

type EncryptionCfg struct {
	Enabled        bool   `yaml:"enabled"`
	StorePath      string `yaml:"store_path"`
	PickleKeyEnv   string `yaml:"pickle_key_env"`   // env var with hex-encoded 32-byte key
	TrustMode      string `yaml:"trust_mode"`       // tofu | cross-signing | manual
	RecoveryKeyEnv string `yaml:"recovery_key_env"` // env var with base58 SSSS recovery key for cross-signing
}

type RoomsCfg struct {
	Listen  []string `yaml:"listen"`
	Respond []string `yaml:"respond"`
	Admin   []string `yaml:"admin"`
}

type FiltersCfg struct {
	// CommandPrefix is the prefix required for commands (e.g. "!" means "!help").
	// Set to "" (empty) to allow commands without prefix — useful for robots where
	// every message is a potential command. When empty, "!help" still works for
	// backward compatibility (the leading "!" is stripped automatically).
	CommandPrefix        string   `yaml:"command_prefix"`
	MentionRespond       bool     `yaml:"mention_respond"`
	DMRespond            bool     `yaml:"dm_respond"`
	IgnoreBots           bool     `yaml:"ignore_bots"`
	IgnoreUsers          []string `yaml:"ignore_users"`
	// Deprecated: use security/ centralized groups instead. Kept for backward compatibility.
	AllowedUsers         []string `yaml:"allowed_users"`
	UnauthorizedResponse string   `yaml:"unauthorized_response"`  // silent (default) | explicit
	MinPowerLevel        int      `yaml:"min_power_level"`
}

// ── SSH Inventory ─────────────────────────────────────────────────────────

type SSHCfg struct {
	Defaults SSHDefaultsCfg         `yaml:"defaults"`
	Targets  map[string]SSHTargetCfg `yaml:"targets"`
}

type SSHDefaultsCfg struct {
	User              string        `yaml:"user"`
	Port              int           `yaml:"port"`
	KeyFileEnv        string        `yaml:"key_file_env"`
	KnownHosts        string        `yaml:"known_hosts"`
	KeepaliveInterval time.Duration `yaml:"keepalive_interval"`
	Timeout           time.Duration `yaml:"timeout"`
}

type SSHTargetCfg struct {
	Hosts      []string `yaml:"hosts"`
	User       string   `yaml:"user"`
	Port       int      `yaml:"port"`
	JumpHost   string   `yaml:"jump_host"`
	KeyFileEnv string   `yaml:"key_file_env"`
}

// ── Security ──────────────────────────────────────────────────────────────

type SecurityCfg struct {
	// Deprecated: use security/ centralized groups instead (see security/user-groups.yaml, permissions.yaml).
	// Kept for backward compatibility; will be removed in a future issue.
	Roles         map[string]RoleCfg `yaml:"roles"`
	Audit         AuditCfg           `yaml:"audit"`
	Secrets       SecretsCfg         `yaml:"secrets"`
	Sanitize      SanitizeCfg        `yaml:"sanitize"`
	ToolRateLimit ToolRateLimitCfg   `yaml:"tool_rate_limit"`
}

// ToolRateLimitCfg controls per-room rate limiting of tool executions.
type ToolRateLimitCfg struct {
	Enabled          bool `yaml:"enabled"`            // enable tool rate limiting (default false)
	MaxCallsPerMin   int  `yaml:"max_calls_per_min"`  // max tool calls per room per minute (default 10)
	CleanupIntervalS int  `yaml:"cleanup_interval_s"` // seconds between stale entry cleanup (default 60)
}

// SanitizeCfg controls prompt injection detection on incoming messages.
type SanitizeCfg struct {
	Enabled          bool     `yaml:"enabled"`           // enable sanitization (default false)
	Mode             string   `yaml:"mode"`              // warn | strip | reject (default warn)
	MinSeverity      string   `yaml:"min_severity"`      // low | medium | high (default medium)
	DisabledPatterns []string `yaml:"disabled_patterns"` // pattern names to skip
}

type RoleCfg struct {
	Users   []string `yaml:"users"`
	Actions []string `yaml:"actions"`
}

type AuditCfg struct {
	Enabled   bool     `yaml:"enabled"`
	LogFile   string   `yaml:"log_file"`
	LogToRoom string   `yaml:"log_to_room"`
	Include   []string `yaml:"include"`
}

type SecretsCfg struct {
	Provider string `yaml:"provider"` // env | vault | sops
}

// ── Scheduling ────────────────────────────────────────────────────────────

type ScheduleCfg struct {
	Name      string        `yaml:"name"`
	Cron      string        `yaml:"cron"`
	Action    ScheduledAction `yaml:"action"`
	OnFailure FailureAction `yaml:"on_failure"`
	OutputRoom string       `yaml:"output_room"`
}

type ScheduledAction struct {
	Kind    string `yaml:"kind"`
	Target  string `yaml:"target"`
	Command string `yaml:"command"`
	Script  string `yaml:"script"`

	// Phase 1: send_message and llm_prompt fields
	Message  string `yaml:"message"`  // inline text for send_message
	Template string `yaml:"template"` // path to .md file for send_message
	Prompt   string `yaml:"prompt"`   // inline prompt text for llm_prompt
}

type FailureAction struct {
	NotifyRoom  string `yaml:"notify_room"`
	EscalateTo  string `yaml:"escalate_to"`
}

// ── Storage ───────────────────────────────────────────────────────────────

type StorageCfg struct {
	BasePath string            `yaml:"base_path"` // root for all data; default $AGENTS_DATA_DIR/<id> or agents/<id>/data
	State    StateStorageCfg   `yaml:"state"`
	Cache    CacheStorageCfg   `yaml:"cache"`
	History  HistoryStorageCfg `yaml:"history"`
}

type StateStorageCfg struct {
	Backend string `yaml:"backend"` // sqlite | redis | file
	Path    string `yaml:"path"`
}

type CacheStorageCfg struct {
	Enabled    bool          `yaml:"enabled"`
	Backend    string        `yaml:"backend"` // memory | redis
	TTL        time.Duration `yaml:"ttl"`
	MaxEntries int           `yaml:"max_entries"`
}

type HistoryStorageCfg struct {
	Backend   string        `yaml:"backend"`
	Path      string        `yaml:"path"`
	Retention time.Duration `yaml:"retention"`
}

// ── Memory ────────────────────────────────────────────────────────────────

type MemoryCfg struct {
	Enabled    bool   `yaml:"enabled"`
	WindowSize int    `yaml:"window_size"` // sliding window size per room (default 20)
	DBPath     string `yaml:"db_path"`     // SQLite path (default agents/<id>/data/memory.db)
}

type MemoryToolCfg struct {
	Enabled bool `yaml:"enabled"`
}

// ── Skills ────────────────────────────────────────────────────────────────

type SkillsCfg struct {
	Enabled    bool     `yaml:"enabled"`     // enable skills system (default false)
	SkillsPath string   `yaml:"path"`        // path to skills directory (default: "skills/")
	Categories []string `yaml:"categories"`  // filter: only load skills from these categories (empty = all)
	Timeout    time.Duration `yaml:"timeout"` // timeout for script execution (default: 60s)
}

type SkillsToolCfg struct {
	AllowedInterpreters []string `yaml:"allowed_interpreters"` // allowlist for skill script execution (default: ["bash", "sh"])
}

type IMDbToolCfg struct {
	Enabled   bool          `yaml:"enabled"`
	APIKey    string        `yaml:"api_key"`     // OMDb API key (get from http://www.omdbapi.com/)
	APIKeyEnv string        `yaml:"api_key_env"` // env var name for API key (e.g., "OMDB_API_KEY")
	Timeout   time.Duration `yaml:"timeout"`     // timeout for API requests (default: 10s)
}

// ── Special Agents ────────────────────────────────────────────────────────

// SpecialConfig is the root configuration for a special agent (no Matrix identity).
type SpecialConfig struct {
	Special       SpecialMeta      `yaml:"special"`
	LLM           LLMCfg           `yaml:"llm"`
	Orchestration OrchestrationCfg `yaml:"orchestration"`
}

// SpecialMeta identifies a special agent.
type SpecialMeta struct {
	ID          string `yaml:"id"`
	Type        string `yaml:"type"`        // "orchestrator", "scheduler", etc.
	Enabled     bool   `yaml:"enabled"`
	Description string `yaml:"description"`
}

// OrchestrationCfg configures the multi-bot orchestrator.
type OrchestrationCfg struct {
	MaxIterations        int                   `yaml:"max_iterations"`
	QualityThreshold     float64               `yaml:"quality_threshold"`
	DelegationTimeout    time.Duration         `yaml:"delegation_timeout"`
	RepetitionThreshold  float64               `yaml:"repetition_threshold"` // 0-1: similarity ratio to detect circular conversations
	Rooms                []OrchestratedRoomCfg `yaml:"rooms"`
}

// OrchestratedRoomCfg defines a room managed by the orchestrator.
type OrchestratedRoomCfg struct {
	RoomID       string   `yaml:"room_id"`
	Participants []string `yaml:"participants"` // bot IDs that participate in this room
}
