// Package types defines the shared domain model for Poimen workflows.
// Both workflow/ (orchestration) and activity/ (execution) import from here.
package types

import (
	"time"

	"github.com/rockliang/poimen/workflows/pkg/db"
)

// ===== LLM Configuration =====

type ModelSpec struct {
	ModelID  string
	Thinking string // "adaptive" or ""
	Effort   string // "low", "medium", "high", "xhigh", "max"
}

type PromptSpec struct {
	TemplateRef string
	RawTemplate string
	Variables   map[string]any
	Model       ModelSpec
	LessonsRef  string
}

type SkillRef struct {
	Name string
	URL  string
}

// ===== Retry & Tuning =====

type PiRetryPolicy struct {
	ScheduleToCloseTimeout time.Duration
	InitialInterval        time.Duration
	MaximumInterval        time.Duration
	BackoffCoefficient     float64
	StreamTimeout          time.Duration
	StreamTimeoutMax       time.Duration
}

type ActivityTuning struct {
	ImplementerBaseTimeout  time.Duration
	ImplementerMaxRetries   int
	JudgeTimeout            time.Duration
	PiRetry                 PiRetryPolicy
	InitialRetryInterval    time.Duration
	MaxRetryInterval        time.Duration
	RetryBackoffCoefficient float64
}

// ===== Orchestrator =====

type OrchestratorConfig struct {
	SystemPrompt string
	Skills       []SkillRef
	RolePrompts  map[string]PromptSpec
	Tuning       ActivityTuning
}

type OrchestratorInput struct {
	TargetRepoPath     string
	RemoteURL          string
	Milestone          string
	Config             OrchestratorConfig
	DryRun             bool
	CycleCount         int
	MaxCyclesBeforeCAN int
	PiProvider         string
}

type OrchestratorOutput struct {
	MilestoneComplete bool
	Done              bool
	LastError         string
}

// ===== TaskUnit =====

type TaskUnitInput struct {
	TaskID         string
	RemoteURL      string
	TargetRepoPath string
	Milestone      string
	Config         OrchestratorConfig
	DryRun         bool
}

type TaskUnitOutput struct {
	TaskID   string
	Status   string
	Verdict  string
	Critique string
	Branch   string
	Reason   string
	Changes  string
}

// ===== Canvas & Relations =====

type RelationWording struct {
	Verb              string  `json:"verb"`
	SourceOutput      string  `json:"source_output"`
	TargetInput       string  `json:"target_input"`
	ConnectionType    string  `json:"connection_type"`
	Confidence        float64 `json:"confidence"`
	SemanticMatch     string  `json:"semantic_match"`
	TransformerNeeded string  `json:"transformer_needed,omitempty"`
}

type EdgeWithWording struct {
	ID              string          `json:"id,omitempty"`
	Source          string          `json:"source"`
	Target          string          `json:"target"`
	RelationType    string          `json:"relation_type"`
	RelationLabel   string          `json:"relation_label"`
	RelationWording RelationWording `json:"relation_wording"`
	CreatedAt       string          `json:"created_at,omitempty"`
}

type CanvasWithRelationsData struct {
	WorkflowID string            `json:"workflow_id"`
	Version    int               `json:"version"`
	Nodes      []db.WorkflowNode `json:"nodes"`
	Edges      []db.WorkflowEdge `json:"edges"`
	Relations  []EdgeWithWording `json:"relations"`
	UpdatedAt  string            `json:"updated_at"`
}

// ===== Activity I/O =====

type FetchCanvasRelationsInput struct {
	WorkflowID string `json:"workflow_id"`
	Version    int    `json:"version"`
}

type CanvasReasonerInput struct {
	Nodes            []db.WorkflowNode `json:"nodes"`
	Edges            []db.WorkflowEdge `json:"edges"`
	PreserveExisting bool              `json:"preserve_existing,omitempty"`
	AuthToken        string            `json:"auth_token,omitempty"`
}

type QueryPathData struct {
	SourceID   string   `json:"source_id"`
	TargetID   string   `json:"target_id"`
	Distance   int      `json:"distance"`
	PathCount  int      `json:"path_count"`
	NodeIDs    []string `json:"node_ids"`
	Confidence float64  `json:"total_confidence"`
}

type GraphRAGQueryInput struct {
	WorkflowID      string                 `json:"workflow_id"`
	Query           string                 `json:"query"`
	SearchType      string                 `json:"search_type"`
	RelationType    string                 `json:"relation_type"`
	ConfidenceFloor float64                `json:"confidence_floor"`
	TopK            int                    `json:"top_k"`
	RankingProfile  string                 `json:"ranking_profile"`
	Canvas          CanvasWithRelationsData `json:"canvas"`
}

type GraphRAGQueryOutput struct {
	WorkflowID  string            `json:"workflow_id"`
	Query       string            `json:"query"`
	Edges       []EdgeWithWording `json:"edges"`
	Paths       []QueryPathData   `json:"paths"`
	TotalCount  int               `json:"total_count"`
	HasMore     bool              `json:"has_more"`
	ExecutionMs int64             `json:"execution_time_ms"`
}

type CanvasCompatibilityInput struct {
	Nodes []db.WorkflowNode `json:"nodes"`
	Edges []db.WorkflowEdge `json:"edges"`
	Query string            `json:"query,omitempty"`
}

type IndexGraphRAGInput struct {
	WorkflowID string            `json:"workflow_id"`
	Version    int               `json:"version"`
	Nodes      []db.WorkflowNode `json:"nodes"`
	Relations  []EdgeWithWording `json:"relations"`
}

type IndexGraphRAGOutput struct {
	WorkflowID       string `json:"workflow_id"`
	Version          int    `json:"version"`
	IndexedEntities  int    `json:"indexed_entities"`
	IndexedEdges     int    `json:"indexed_edges"`
	Status           string `json:"status"`
	GraphRAGChecksum string `json:"graph_rag_checksum"`
	IndexedAt        string `json:"indexed_at"`
}

type PromptUpdate struct {
	Role string
	Spec PromptSpec
}

// ===== Defaults =====

func NewPiRetryPolicy() PiRetryPolicy {
	return PiRetryPolicy{
		ScheduleToCloseTimeout: 5 * time.Minute,
		InitialInterval:        2 * time.Second,
		MaximumInterval:        30 * time.Second,
		BackoffCoefficient:     2.0,
		StreamTimeout:          30 * time.Second,
		StreamTimeoutMax:       2 * time.Minute,
	}
}

func NewActivityTuning() ActivityTuning {
	return ActivityTuning{
		ImplementerBaseTimeout: 10 * time.Minute,
		ImplementerMaxRetries:  3,
		JudgeTimeout:           5 * time.Minute,
		PiRetry:                NewPiRetryPolicy(),
	}
}
