package models

// PusherConfig holds Pusher configuration for direct streaming.
// Supports both Pusher cloud (Cluster) and self-hosted servers like Reverb (Host + Scheme).
type PusherConfig struct {
	AppID   string `json:"app_id"`
	Key     string `json:"key"`
	Secret  string `json:"secret"`
	Cluster string `json:"cluster,omitempty"`
	Host    string `json:"host,omitempty"`   // Custom host:port for Reverb
	Scheme  string `json:"scheme,omitempty"` // "http" or "https"
}

// FeatureFlags controls optional features per-request
type FeatureFlags struct {
	ParallelTools  bool `json:"parallel_tools"`  // Enable parallel tool execution (default: true)
	RetryLLM       bool `json:"retry_llm"`       // Enable LLM retry with backoff (default: true)
	AutoCompaction bool `json:"auto_compaction"` // Enable auto context compaction (default: true)
	GranularEvents bool `json:"granular_events"` // Enable granular progress events (default: true)
}

// DefaultFeatureFlags returns the default feature flags
func DefaultFeatureFlags() FeatureFlags {
	return FeatureFlags{
		ParallelTools:  true,
		RetryLLM:       true,
		AutoCompaction: true,
		GranularEvents: true, // Enabled by default for better progress visibility
	}
}

// ProjectCapabilities holds project feature availability passed from Laravel.
// This tells the agent what dynamic features are available for code generation.
type ProjectCapabilities struct {
	Supabase *SupabaseCapability `json:"supabase,omitempty"`
	Storage  *StorageCapability  `json:"storage,omitempty"`
	WebAgent *WebAgentCapability `json:"web_agent,omitempty"`
	Github   *GithubCapability   `json:"github,omitempty"`
}

// SupabaseCapability indicates Supabase backend availability for the project.
// SECURITY: SecretKey and DBConnection are server-side only. formatProjectCapabilities()
// intentionally omits them from agent context — do NOT add them there.
type SupabaseCapability struct {
	Enabled        bool   `json:"enabled"`
	URL            string `json:"url"`
	PublishableKey string `json:"publishable_key"`
	SecretKey      string `json:"secret_key"` // server-side only — never forward to agent
	Schema         string `json:"schema"`
	DBConnection   string `json:"db_connection"` // server-side only — never forward to agent
}

// StorageCapability indicates file storage availability for the project
type StorageCapability struct {
	Enabled          bool     `json:"enabled"`
	MaxFileSizeMB    int      `json:"max_file_size_mb"`
	AllowedFileTypes []string `json:"allowed_file_types"`
}

// WebAgentCapability indicates whether the agent can fetch/navigate external
// websites (provided by the webby-plugin-webagent plugin).
type WebAgentCapability struct {
	Enabled                     bool   `json:"enabled"`
	FetchMode                   string `json:"fetch_mode"`
	MaxActionsPerSession        int    `json:"max_actions_per_session"`
	HTTPTimeoutSeconds          int    `json:"http_timeout_seconds"`
	BrowserActionTimeoutSeconds int    `json:"browser_action_timeout_seconds"`
	MaxResponseSizeMB           int    `json:"max_response_size_mb"`

	// FirecrawlEnabled gates the webFetchFirecrawl tool registration.
	// True only when the plan has firecrawl quota AND the mode is firecrawl/smart.
	FirecrawlEnabled bool `json:"firecrawl_enabled"`

	// FirecrawlAPIKey is the operator's Firecrawl API key. Pre-stripped on
	// the Laravel side when the mode doesn't need it, so we trust whatever we
	// receive — empty string means do not call Firecrawl.
	FirecrawlAPIKey string `json:"firecrawl_api_key"`

	// FirecrawlRemainingPages is the user's monthly Firecrawl page balance.
	// nil = unlimited; 0 = exhausted; N > 0 = N pages left this month.
	FirecrawlRemainingPages *int `json:"firecrawl_remaining_pages"`

	// FirecrawlMaxCallsPerSession is the hard per-build-session ceiling on
	// webFetchFirecrawl invocations. Defaults to 20.
	FirecrawlMaxCallsPerSession int `json:"firecrawl_max_calls_per_session"`
}

// GithubCapability indicates the project is linked to a GitHub repo the agent
// may auto-commit/push to. Tokens are NEVER in this payload — the builder mints
// them per-op via the Laravel callback.
type GithubCapability struct {
	Enabled       bool   `json:"enabled"`
	Owner         string `json:"owner"`
	Name          string `json:"name"`
	DefaultBranch string `json:"default_branch"`
	AutoPush      bool   `json:"auto_push"`
}

// ThemePreset holds legacy theme-preset data (live re-theme path). Superseded
// by DesignSystem for build-time application; retained until the re-theme path
// is migrated.
type ThemePreset struct {
	ID          string            `json:"id"`
	Name        string            `json:"name"`
	Description string            `json:"description"`
	Light       map[string]string `json:"light"`
	Dark        map[string]string `json:"dark"`
}

// DesignSystem holds a resolved design system passed inline from Laravel:
// the accent-agnostic base tokens + the chosen accent's light/dark variable
// maps + font links + the agent playbook (+ optional component overrides for
// deep systems). The builder overlays this onto the template at build time.
type DesignSystem struct {
	Slug        string                `json:"slug"`
	Tokens      string                `json:"tokens"`            // tokens.css (accent-agnostic)
	Fonts       string                `json:"fonts"`             // fonts.html (<link>s)
	Playbook    string                `json:"playbook"`          // DESIGN.md (injected into the agent prompt)
	Accent      string                `json:"accent"`            // chosen accent name
	AccentLight map[string]string     `json:"accent_light"`      // accent vars for :root
	AccentDark  map[string]string     `json:"accent_dark"`       // accent vars for .dark
	Accents     map[string]AccentPair `json:"accents,omitempty"` // full accent catalog (WP style variations)
	Components  map[string]string     `json:"components"`        // optional: rel path -> file content
}

// AccentPair is one named accent's light/dark variable maps.
type AccentPair struct {
	Light map[string]string `json:"light"`
	Dark  map[string]string `json:"dark"`
}

// RunRequest is the request body for POST /api/run
type RunRequest struct {
	Goal                string               `json:"goal" binding:"required"`
	MaxIterations       int                  `json:"max_iterations"`
	History             []HistoryMessage     `json:"history"`
	IsCompacted         bool                 `json:"is_compacted"` // Skip summarization if history is already compacted
	Config              RequestConfig        `json:"config" binding:"required"`
	Template            *TemplateConfig      `json:"template,omitempty"`
	WorkspaceID         string               `json:"workspace_id" binding:"required"`
	WebhookURL          string               `json:"webhook_url" binding:"required"`
	Pusher              *PusherConfig        `json:"pusher,omitempty"`
	Features            *FeatureFlags        `json:"features,omitempty"`             // Optional feature flags
	LaravelURL          string               `json:"laravel_url,omitempty"`          // Laravel API URL for template fetching
	UserID              int                  `json:"user_id,omitempty"`              // Laravel user ID — used for Firecrawl reconciliation
	ProjectCapabilities *ProjectCapabilities `json:"project_capabilities,omitempty"` // Project feature availability
	ThemePreset         *ThemePreset         `json:"theme_preset,omitempty"`         // Legacy theme preset (live re-theme path)
	DesignSystem        *DesignSystem        `json:"design_system,omitempty"`        // Resolved design system (tokens+accent+playbook)
	OutputType          string               `json:"output_type,omitempty"`          // "website" (default) | "wordpress_theme"
	ProjectName         string               `json:"project_name,omitempty"`         // Project display name — titles the generated site (index.html <title>, WP Theme Name)
}

// HistoryMessage represents a message in conversation history
type HistoryMessage struct {
	Role    string `json:"role"` // "user" or "assistant"
	Content string `json:"content"`
}

// RunResponse is returned when a session is started
type RunResponse struct {
	SessionID string `json:"session_id"`
}

// StatusResponse is returned for session status queries
type StatusResponse struct {
	SessionID      string `json:"session_id"`
	Status         string `json:"status"`
	Iterations     int    `json:"iterations"`
	TokensUsed     int    `json:"tokens_used"`
	ActiveSessions int    `json:"active_sessions"`
	Error          string `json:"error,omitempty"`
}

// FileListResponse is returned for file listing
type FileListResponse struct {
	Files []FileInfo `json:"files"`
}

// FileInfo describes a file in the workspace
type FileInfo struct {
	Path    string `json:"path"`
	Name    string `json:"name"`
	Size    int64  `json:"size"`
	IsDir   bool   `json:"is_dir"`
	ModTime string `json:"mod_time"`
}

// FileResponse is returned when getting a file
type FileResponse struct {
	Path    string `json:"path"`
	Content string `json:"content"`
	Size    int64  `json:"size"`
}

// FileUpdateRequest is the request body for PUT /api/file/:session_id
type FileUpdateRequest struct {
	Path    string `json:"path" binding:"required"`
	Content string `json:"content" binding:"required"`
}

// ApplyThemeRequest is the request body for PUT /api/theme-workspace/:workspace_id
type ApplyThemeRequest struct {
	Light    map[string]string `json:"light" binding:"required"` // CSS variables for :root
	Dark     map[string]string `json:"dark" binding:"required"`  // CSS variables for .dark
	PresetID string            `json:"preset_id,omitempty"`      // Optional theme preset name (e.g. "mocha") recorded in design-intelligence.json
}

// BuildResponse is returned after a build
type BuildResponse struct {
	Success    bool     `json:"success"`
	Message    string   `json:"message"`
	Output     string   `json:"output,omitempty"`
	Errors     []string `json:"errors,omitempty"`
	FilesCount int      `json:"files_count,omitempty"`
	OutputSize int64    `json:"output_size,omitempty"`
}

// SuggestionsResponse is returned for suggestion queries
type SuggestionsResponse struct {
	Suggestions []string `json:"suggestions"`
}

// ChatRequest is the request body for POST /api/chat/:session_id
type ChatRequest struct {
	Message     string           `json:"message" binding:"required"`
	History     []HistoryMessage `json:"history"`
	IsCompacted bool             `json:"is_compacted"` // Skip summarization if history is already compacted
	Config      *RequestConfig   `json:"config,omitempty"`
}

// ErrorResponse is returned for errors
type ErrorResponse struct {
	Error string `json:"error"`
}

// ListWorkspacesResponse is returned for GET /api/workspaces
type ListWorkspacesResponse struct {
	WorkspaceIDs []string `json:"workspace_ids"`
	Count        int      `json:"count"`
}

// CleanupWorkspacesRequest is the request body for POST /api/cleanup-workspaces
type CleanupWorkspacesRequest struct {
	WorkspaceIDs []string `json:"workspace_ids" binding:"required"`
}

// CleanupWorkspaceResult represents the result for a single workspace cleanup
type CleanupWorkspaceResult struct {
	WorkspaceID string `json:"workspace_id"`
	Status      string `json:"status"` // "deleted", "not_found", "skipped", "failed"
	Reason      string `json:"reason,omitempty"`
}

// CleanupWorkspacesResponse is returned for POST /api/cleanup-workspaces
type CleanupWorkspacesResponse struct {
	Results  []CleanupWorkspaceResult `json:"results"`
	Deleted  int                      `json:"deleted"`
	NotFound int                      `json:"not_found"`
	Skipped  int                      `json:"skipped"`
	Failed   int                      `json:"failed"`
}
