package registry

import "time"

// Kind classifies a registry entry.
type Kind string

const (
	KindFunction  Kind = "function"
	KindPipeline  Kind = "pipeline"
	KindComponent Kind = "component"
)

// Purity indicates whether a function has side effects.
type Purity string

const (
	PurityPure   Purity = "pure"
	PurityImpure Purity = "impure"
)

// Algebraic classifies a type.
type Algebraic string

const (
	AlgebraicProduct Algebraic = "product"
	AlgebraicSum     Algebraic = "sum"
)

// Function represents an entry in the functions table.
// Covers kind: function, pipeline, and component.
type Function struct {
	ID              string   `json:"id"`
	Name            string   `json:"name"`
	Kind            Kind     `json:"kind"`
	Lang            string   `json:"lang"`
	Domain          string   `json:"domain"`
	Version         string   `json:"version"`
	Purity          Purity   `json:"purity"`
	Signature       string   `json:"signature"`
	Description     string   `json:"description"`
	Tags            []string `json:"tags"`
	UsesFunctions   []string `json:"uses_functions"`
	UsesTypes       []string `json:"uses_types"`
	Returns         []string `json:"returns"`
	ReturnsOptional bool     `json:"returns_optional"`
	ErrorType       string   `json:"error_type"`
	Imports         []string `json:"imports"`
	Example         string   `json:"example"`
	Notes           string   `json:"notes"`
	Documentation   string   `json:"documentation"`
	Code            string   `json:"code"`
	ParamsSchema    string   `json:"params_schema"`
	Tested          bool     `json:"tested"`
	Tests           []string `json:"tests"`
	TestFilePath    string   `json:"test_file_path"`
	FilePath        string   `json:"file_path"`
	ContentHash     string   `json:"content_hash"`
	SourceRepo      string   `json:"source_repo"`
	SourceLicense   string   `json:"source_license"`
	SourceFile      string   `json:"source_file"`
	CreatedAt       time.Time `json:"created_at"`
	UpdatedAt       time.Time `json:"updated_at"`

	// Component-only fields (kind: component)
	Props    []PropDef `json:"props,omitempty"`
	Emits    []string  `json:"emits,omitempty"`
	HasState *bool     `json:"has_state,omitempty"`
	Framework string   `json:"framework,omitempty"`
	Variant  []string  `json:"variant,omitempty"`
}

// PropDef describes a component prop.
type PropDef struct {
	Name        string `json:"name"`
	Type        string `json:"type"`
	Required    bool   `json:"required"`
	Description string `json:"description"`
}

// Type represents an entry in the types table.
type Type struct {
	ID         string    `json:"id"`
	Name       string    `json:"name"`
	Lang       string    `json:"lang"`
	Domain     string    `json:"domain"`
	Version    string    `json:"version"`
	Algebraic  Algebraic `json:"algebraic"`
	Definition string    `json:"definition"`
	Description string   `json:"description"`
	Tags       []string  `json:"tags"`
	UsesTypes  []string  `json:"uses_types"`
	Examples      string    `json:"examples"`
	Notes         string    `json:"notes"`
	Documentation string    `json:"documentation"`
	Code          string    `json:"code"`
	FilePath      string    `json:"file_path"`
	ContentHash   string    `json:"content_hash"`
	SourceRepo    string    `json:"source_repo"`
	SourceLicense string    `json:"source_license"`
	SourceFile    string    `json:"source_file"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
}

// App represents an entry in the apps table.
type App struct {
	ID            string       `json:"id"`
	Name          string       `json:"name"`
	Lang          string       `json:"lang"`
	Domain        string       `json:"domain"`
	Version       string       `json:"version"`
	Description   string       `json:"description"`
	Tags          []string     `json:"tags"`
	UsesFunctions []string     `json:"uses_functions"`
	UsesTypes     []string     `json:"uses_types"`
	UsesModules   []string     `json:"uses_modules"`
	Framework     string       `json:"framework"`
	EntryPoint    string       `json:"entry_point"`
	Documentation string       `json:"documentation"`
	Notes         string       `json:"notes"`
	DirPath       string       `json:"dir_path"`
	ContentHash   string       `json:"content_hash"`
	RepoURL       string       `json:"repo_url"`
	ProjectID     string       `json:"project_id"`
	Service       *ServiceSpec `json:"service,omitempty"`
	CreatedAt     time.Time    `json:"created_at"`
	UpdatedAt     time.Time    `json:"updated_at"`
}

// ServiceSpec describes how an app runs as a long-lived service.
// Populated from the `service:` block of app.md frontmatter (issue 0105).
type ServiceSpec struct {
	Port           int      `json:"port,omitempty"`
	HealthEndpoint string   `json:"health_endpoint,omitempty"`
	HealthTimeoutS int      `json:"health_timeout_s,omitempty"`
	SystemdUnit    string   `json:"systemd_unit,omitempty"`
	SystemdScope   string   `json:"systemd_scope,omitempty"`
	RestartPolicy  string   `json:"restart_policy,omitempty"`
	Runtime        string   `json:"runtime,omitempty"`
	IsLocalOnly    bool     `json:"is_local_only,omitempty"`
	PCTargets      []string `json:"pc_targets,omitempty"`
}

// Analysis represents an entry in the analysis table.
type Analysis struct {
	ID            string    `json:"id"`
	Name          string    `json:"name"`
	Lang          string    `json:"lang"`
	Domain        string    `json:"domain"`
	Description   string    `json:"description"`
	Tags          []string  `json:"tags"`
	UsesFunctions []string  `json:"uses_functions"`
	UsesTypes     []string  `json:"uses_types"`
	UsesModules   []string  `json:"uses_modules"`
	Framework     string    `json:"framework"`
	EntryPoint    string    `json:"entry_point"`
	Documentation string    `json:"documentation"`
	Notes         string    `json:"notes"`
	RepoURL       string    `json:"repo_url"`
	DirPath       string    `json:"dir_path"`
	ContentHash   string    `json:"content_hash"`
	ProjectID     string    `json:"project_id"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
}

// Module represents an entry in the modules table.
// A module groups related registry functions/types under a single versioned
// artefact that apps opt into via uses_modules in app.md. Living data: kept
// in sync across PCs via fn sync.
type Module struct {
	ID            string    `json:"id"`
	Name          string    `json:"name"`
	Version       string    `json:"version"`
	Lang          string    `json:"lang"`
	Description   string    `json:"description"`
	Members       []string  `json:"members"`
	Tags          []string  `json:"tags"`
	DirPath       string    `json:"dir_path"`
	RepoURL       string    `json:"repo_url"`
	Documentation string    `json:"documentation"`
	Notes         string    `json:"notes"`
	ContentHash   string    `json:"content_hash"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
}

// ProposalKind classifies a proposal.
type ProposalKind string

const (
	ProposalNewFunction     ProposalKind = "new_function"
	ProposalNewType         ProposalKind = "new_type"
	ProposalImproveFunction ProposalKind = "improve_function"
	ProposalImproveType     ProposalKind = "improve_type"
	ProposalNewPipeline     ProposalKind = "new_pipeline"
)

// ProposalStatus represents the review state of a proposal.
type ProposalStatus string

const (
	ProposalPending     ProposalStatus = "pending"
	ProposalApproved    ProposalStatus = "approved"
	ProposalRejected    ProposalStatus = "rejected"
	ProposalImplemented ProposalStatus = "implemented"
)

// Proposal represents a suggested improvement to the registry.
type Proposal struct {
	ID          string         `json:"id"`
	Kind        ProposalKind   `json:"kind"`
	TargetID    string         `json:"target_id"`
	Title       string         `json:"title"`
	Description string         `json:"description"`
	Evidence    map[string]any `json:"evidence"`
	Status      ProposalStatus `json:"status"`
	CreatedBy   string         `json:"created_by"`
	ReviewedBy  string         `json:"reviewed_by"`
	CreatedAt   time.Time      `json:"created_at"`
	UpdatedAt   time.Time      `json:"updated_at"`
}

// UnitTest represents an individual test case extracted from a test file.
type UnitTest struct {
	ID         string    `json:"id"`
	FunctionID string    `json:"function_id"`
	Name       string    `json:"name"`
	Code       string    `json:"code"`
	FilePath   string    `json:"file_path"`
	Lang       string    `json:"lang"`
	CreatedAt  time.Time `json:"created_at"`
	UpdatedAt  time.Time `json:"updated_at"`
}

// Project groups apps, analysis and vaults under a common theme.
type Project struct {
	ID            string    `json:"id"`
	Name          string    `json:"name"`
	Description   string    `json:"description"`
	Tags          []string  `json:"tags"`
	RepoURL       string    `json:"repo_url"`
	DirPath       string    `json:"dir_path"`
	Documentation string    `json:"documentation"`
	Notes         string    `json:"notes"`
	ContentHash   string    `json:"content_hash"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
}

// Vault is a data store (symlink or directory) associated with a project or the registry.
type Vault struct {
	ID          string    `json:"id"`
	Name        string    `json:"name"`
	ProjectID   string    `json:"project_id"`
	Description string    `json:"description"`
	Path        string    `json:"path"`
	Symlink     bool      `json:"symlink"`
	Tags        []string  `json:"tags"`
	ContentHash string    `json:"content_hash"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
}

// PcLocation maps an entity to a directory path on a specific PC.
type PcLocation struct {
	ID         string    `json:"id"`
	EntityType string    `json:"entity_type"`
	EntityID   string    `json:"entity_id"`
	PcID       string    `json:"pc_id"`
	DirPath    string    `json:"dir_path"`
	Status     string    `json:"status"`
	Notes      string    `json:"notes"`
	CreatedAt  time.Time `json:"created_at"`
	UpdatedAt  time.Time `json:"updated_at"`
}

// GenerateID builds the canonical ID: {name}_{lang}_{domain}
func GenerateID(name, lang, domain string) string {
	return name + "_" + lang + "_" + domain
}

// GenerateModuleID builds the module canonical ID: {name}_{lang}.
// Modules are language-scoped but domain-agnostic; they live at modules/<name>/.
func GenerateModuleID(name, lang string) string {
	return name + "_" + lang
}
