package adk

import (
	"fmt"
)

// AgentConfig represents configuration for an agent.
//
// This is a generic configuration structure that can be adapted
// to any ADK implementation.
type AgentConfig struct {
	// Agent name
	Name string

	// Agent description
	Description string

	// System instruction
	Instruction string

	// Available tools
	Tools []Tool

	// Before tool callback
	BeforeToolCallback BeforeToolCallback

	// After tool callback
	AfterToolCallback AfterToolCallback
}

// ConfigForImplementationAgent creates configuration for an Implementation Agent.
//
// Implementation Agent writes code against approved patterns only.
// It MUST check constraints before generating code.
//
// Example usage:
//
//	client := steme.NewClient("http://localhost:18180", signer)
//	config := adk.ConfigForImplementationAgent(client, logFunc)
func ConfigForImplementationAgent(client EpistemeClient, logFunc func(string, ...any)) AgentConfig {
	tools := []Tool{
		NewQueryTool(client),
		NewConstraintCheckTool(client),
		// Add your code generation tools here
	}

	return AgentConfig{
		Name:        "implementation_agent",
		Description: "Writes code against current approved patterns",
		Instruction: `You write code. Always use approved patterns only.

CRITICAL RULES:
1. Query Episteme with lifecycle=approved for patterns
2. Check constraints BEFORE writing code
3. Never use proposed or deprecated patterns
4. If no approved pattern exists, escalate to human

Example workflow:
1. Query for approved pattern: episteme_query(subject="auth/jwt", predicate="signing_algorithm", lifecycle="approved")
2. Check constraints: episteme_constraint_check(context="auth_jwt")
3. Write code using approved pattern and respecting constraints`,

		Tools: tools,

		BeforeToolCallback: ConstraintEnforcementCallback(client, []string{
			"write_code",
			"generate_config",
			"create_file",
		}),

		AfterToolCallback: AuditLoggingCallback(logFunc),
	}
}

// ConfigForLeadOrchestrator creates configuration for a Lead Orchestrator.
//
// Lead Orchestrator queries Episteme for current state and routes work
// based on confidence thresholds.
//
// Example usage:
//
//	config := adk.ConfigForLeadOrchestrator(client, 0.8, setState, logFunc)
func ConfigForLeadOrchestrator(
	client EpistemeClient,
	confidenceThreshold float32,
	setState func(string, any),
	logFunc func(string, ...any),
) AgentConfig {
	tools := []Tool{
		NewQueryTool(client),
		// Add delegation tools here
	}

	return AgentConfig{
		Name:        "lead_orchestrator",
		Description: "Coordinates agent team based on knowledge state",
		Instruction: fmt.Sprintf(`You coordinate the agent team. Query Episteme for current state.

CRITICAL RULES:
1. Query with appropriate lens (authority, consensus, recency)
2. If confidence < %.2f, escalate to human supervisor
3. Only route to implementation if confidence is high
4. Always include lifecycle filter in queries

Example workflow:
1. Query current state: episteme_query(subject="task/xyz", predicate="status", lens="authority")
2. Check confidence score
3. If confidence >= %.2f: route to implementation agent
4. If confidence < %.2f: escalate to human supervisor`, confidenceThreshold, confidenceThreshold, confidenceThreshold),

		Tools: tools,

		AfterToolCallback: ChainAfterCallbacks(
			ConfidenceEscalationCallback(confidenceThreshold, setState),
			AuditLoggingCallback(logFunc),
		),
	}
}

// ConfigForResearchAgent creates configuration for a Research Agent.
//
// Research Agent discovers and stores knowledge with source attribution.
// It stores conflicting information without resolving it.
//
// Example usage:
//
//	config := adk.ConfigForResearchAgent(client, logFunc)
func ConfigForResearchAgent(client EpistemeClient, logFunc func(string, ...any)) AgentConfig {
	tools := []Tool{
		NewAssertTool(client),
		// Add search/research tools here
	}

	return AgentConfig{
		Name:        "research_agent",
		Description: "Researches and stores knowledge with source attribution",
		Instruction: `You research topics and store findings with source attribution.

CRITICAL RULES:
1. Always include source_hash for provenance
2. Use confidence to express uncertainty (0.0-1.0)
3. Mark conflicting sources - don't resolve them
4. Default to lifecycle=proposed (not approved)
5. Include context in meta.reason

Example workflow:
1. Research topic from multiple sources
2. For each source, create assertion:
   episteme_assert(
       subject="topic",
       predicate="property",
       object="value",
       source_hash="<hash of source>",
       confidence=0.8,
       lifecycle="proposed",
   )
3. Store ALL sources, even if they conflict
4. Let Lead Orchestrator resolve conflicts via lens`,

		Tools: tools,

		AfterToolCallback: AuditLoggingCallback(logFunc),
	}
}

// ConfigForHumanSupervisor creates configuration for a Human Supervisor.
//
// Human Supervisor has access to time-travel queries, trace, and supersede.
// This is for incident investigation and knowledge correction.
//
// Example usage:
//
//	config := adk.ConfigForHumanSupervisor(client, logFunc)
func ConfigForHumanSupervisor(client EpistemeClient, logFunc func(string, ...any)) AgentConfig {
	tools := []Tool{
		NewQueryTool(client),
		NewAssertTool(client),
		NewTraceTool(client),
		NewSupersedeTool(client),
	}

	return AgentConfig{
		Name:        "human_supervisor",
		Description: "Investigates incidents and corrects knowledge",
		Instruction: `You investigate incidents and correct bad knowledge.

CRITICAL CAPABILITIES:
1. Time-travel queries: as_of parameter shows knowledge at specific time
2. Trace queries: see what an agent queried and when
3. Supersede: correct bad assertions with cascade tracking
4. Approve: promote proposed assertions to approved

Example incident investigation:
1. Time-travel to incident: episteme_query(subject="auth/jwt", predicate="signing_algorithm", as_of="2024-01-15T21:00:00Z")
2. Trace agent queries: episteme_trace(agent_id="deployment-agent", from="-6h", subject="auth/*")
3. Identify bad assertion from trace
4. Supersede: episteme_supersede(hash="<bad_hash>", reason="Proposal treated as approved", type="Invalidate")
5. Verify fix: episteme_query(subject="auth/jwt", predicate="signing_algorithm", lifecycle="approved")`,

		Tools: tools,

		AfterToolCallback: AuditLoggingCallback(logFunc),
	}
}

// ConfigForOnCallSRE creates configuration for an On-Call SRE.
//
// On-Call SRE focuses on fast trace queries for incident response.
// Sub-second queries are critical.
//
// Example usage:
//
//	config := adk.ConfigForOnCallSRE(client, logFunc)
func ConfigForOnCallSRE(client EpistemeClient, logFunc func(string, ...any)) AgentConfig {
	tools := []Tool{
		NewQueryTool(client),
		NewTraceTool(client),
	}

	return AgentConfig{
		Name:        "oncall_sre",
		Description: "Investigates production incidents via trace queries",
		Instruction: `You investigate production incidents. Speed is critical.

CRITICAL WORKFLOW (under 10 minutes):
1. Trace: What did the agent query?
2. Diff: What changed recently?
3. Identify: Which assertion is bad?
4. Escalate: Flag for human supervisor to correct

Example 3am workflow:
1. Trace deployment agent: episteme_trace(agent_id="deployment-agent", from="-6h", subject="auth/*")
2. Find suspicious query in trace
3. Query current value: episteme_query(subject="auth/jwt", predicate="signing_algorithm", lifecycle="approved")
4. If value is wrong, escalate to human supervisor with trace evidence

DO NOT:
- Correct assertions yourself (escalate to supervisor)
- Make changes to production knowledge
- Skip the trace step`,

		Tools: tools,

		AfterToolCallback: AuditLoggingCallback(logFunc),
	}
}

// AllConfigs returns configurations for all standard agent types.
//
// This is a convenience function for setting up a complete agent team.
func AllConfigs(
	client EpistemeClient,
	confidenceThreshold float32,
	setState func(string, any),
	logFunc func(string, ...any),
) map[string]AgentConfig {
	return map[string]AgentConfig{
		"implementation": ConfigForImplementationAgent(client, logFunc),
		"lead":           ConfigForLeadOrchestrator(client, confidenceThreshold, setState, logFunc),
		"research":       ConfigForResearchAgent(client, logFunc),
		"supervisor":     ConfigForHumanSupervisor(client, logFunc),
		"oncall":         ConfigForOnCallSRE(client, logFunc),
	}
}
