package skills

import "time"

// Skill is the persisted resource-runtime Skill collection metadata. Its
// repository binding is owned separately by the resource repository lifecycle;
// this row is neither a repo-native Skill definition nor an API DTO.
type Skill struct {
	ID                        string     `gorm:"primaryKey;size:64;index:idx_skills_exact_content,priority:2"`
	WorkspaceID               string     `gorm:"size:64;not null;index:idx_skills_workspace_updated;index:idx_skills_workspace_creator_deleted;uniqueIndex:uk_skill_workspace_visibility_slug,priority:1;index:idx_skills_exact_content,priority:1"`
	Slug                      string     `gorm:"size:255;not null;default:'';index;uniqueIndex:uk_skill_workspace_visibility_slug,priority:4"`
	Name                      string     `gorm:"size:255;not null"`
	Description               string     `gorm:"type:text;not null"`
	StorageScope              string     `gorm:"size:32;not null;default:'personal'"`
	StorageOwnerLogin         string     `gorm:"size:128;not null;default:''"`
	VisibilityScope           string     `gorm:"size:32;not null;default:'private';index:idx_skills_visibility;uniqueIndex:uk_skill_workspace_visibility_slug,priority:2"`
	VisibilityOwnerID         string     `gorm:"size:64;not null;default:'';index:idx_skills_visibility;uniqueIndex:uk_skill_workspace_visibility_slug,priority:3"`
	SkillCount                int        `gorm:"not null;default:0"`
	OfficialSourceFingerprint string     `gorm:"size:128;not null;default:''"`
	ContentID                 string     `gorm:"size:64;not null;default:'';index:idx_skills_content;index:idx_skills_exact_content,priority:3"`
	ActiveContentVersionID    string     `gorm:"size:64;not null;default:'';index:idx_skills_active_content_version;index:idx_skills_exact_content,priority:4"`
	IsActive                  bool       `gorm:"not null;index"`
	CreatedBy                 string     `gorm:"size:64;not null;index:idx_skills_workspace_creator_deleted"`
	UpdatedBy                 string     `gorm:"size:64;not null"`
	CreatedAt                 time.Time  `gorm:"not null"`
	UpdatedAt                 time.Time  `gorm:"not null;index:idx_skills_workspace_updated"`
	DeletedAt                 *time.Time `gorm:"index;index:idx_skills_workspace_creator_deleted"`

	Role      string `gorm:"-"`
	CanManage bool   `gorm:"-"`
}

// TableName returns the stable resource Skill collection table name.
func (Skill) TableName() string { return "skills" }

// SkillVersion is the immutable Skill-domain projection of one exact Content
// Store version. Payload metadata and bytes remain owned by Content Store; the
// Skill domain stores only the exact reference and the bounded scan summary it
// needs for history and rollback UI.
type SkillVersion struct {
	ID               string    `gorm:"primaryKey;size:64;index:idx_skill_versions_history,priority:4"`
	WorkspaceID      string    `gorm:"size:64;not null;index:idx_skill_versions_history,priority:1;uniqueIndex:uk_skill_content_version,priority:1;index:idx_skill_versions_content,priority:1"`
	SkillID          string    `gorm:"size:64;not null;index:idx_skill_versions_history,priority:2;uniqueIndex:uk_skill_content_version,priority:2"`
	ContentID        string    `gorm:"size:64;not null;uniqueIndex:uk_skill_content_version,priority:3;index:idx_skill_versions_content,priority:2"`
	ContentVersionID string    `gorm:"size:64;not null;uniqueIndex:uk_skill_content_version,priority:4;index:idx_skill_versions_content,priority:3"`
	RootDigest       string    `gorm:"size:64;not null"`
	FileCount        int       `gorm:"not null"`
	SizeBytes        int64     `gorm:"not null"`
	SkillCount       int       `gorm:"not null"`
	CreatedBy        string    `gorm:"size:64;not null"`
	CreatedAt        time.Time `gorm:"not null;index:idx_skill_versions_history,priority:3"`
}

// TableName returns the stable immutable Skill version projection table.
func (SkillVersion) TableName() string { return "skill_versions" }

// SkillRepositoryBranch persists the branch pin for an actively assigned
// resource Skill repository. It does not replace the generic repository binding.
// It pins an actively assigned workspace repo identity to
// exactly one branch. It is intentionally repo-scoped, not agent-scoped, so the
// same skill repo cannot be active on two different branches for different
// agents.
type SkillRepositoryBranch struct {
	ID          string    `gorm:"primaryKey;size:64"`
	WorkspaceID string    `gorm:"size:64;not null;index:idx_skill_repo_branches_repo;uniqueIndex:uk_skill_repo_branch_repo"`
	RepoOwner   string    `gorm:"size:128;not null;index:idx_skill_repo_branches_repo;uniqueIndex:uk_skill_repo_branch_repo"`
	RepoName    string    `gorm:"size:128;not null;index:idx_skill_repo_branches_repo;uniqueIndex:uk_skill_repo_branch_repo"`
	Branch      string    `gorm:"size:255;not null"`
	CreatedBy   string    `gorm:"size:64;not null"`
	UpdatedBy   string    `gorm:"size:64;not null"`
	CreatedAt   time.Time `gorm:"not null"`
	UpdatedAt   time.Time `gorm:"not null;index"`
}

// TableName returns the stable Skill repository branch table name.
func (SkillRepositoryBranch) TableName() string { return "skill_repository_branches" }

// SkillAgentBinding persists one resource-runtime agent assignment to one Skill.
// Authorization policy remains owned by the Skill service. Multiple skills can
// be assigned to the same agent; same skill+agent upserts idempotently.
type SkillAgentBinding struct {
	ID          string    `gorm:"primaryKey;size:64"`
	WorkspaceID string    `gorm:"size:64;not null;index:idx_skill_agent_bindings_agent;uniqueIndex:uk_skill_agent_binding"`
	AgentID     string    `gorm:"size:64;not null;index:idx_skill_agent_bindings_agent;uniqueIndex:uk_skill_agent_binding"`
	SkillID     string    `gorm:"size:64;not null;index:idx_skill_agent_bindings_skill;uniqueIndex:uk_skill_agent_binding"`
	Branch      string    `gorm:"size:255;not null;default:'main'"`
	CreatedBy   string    `gorm:"size:64;not null"`
	UpdatedBy   string    `gorm:"size:64;not null"`
	CreatedAt   time.Time `gorm:"not null"`
	UpdatedAt   time.Time `gorm:"not null;index"`
}

// TableName returns the stable Skill agent-binding table name.
func (SkillAgentBinding) TableName() string { return "skill_agent_bindings" }

// SkillGrant records a user or workspace role on a skill (owner/manage/view).
// Legacy edit rows are treated as compatibility input by the service layer. The
// agent side of skill access continues to flow through SkillAgentBinding. The
// unique index enforces one grant per (workspace, skill, subject).
type SkillGrant struct {
	ID          string    `gorm:"primaryKey;size:64"`
	WorkspaceID string    `gorm:"size:64;not null;index:idx_skill_grants_subject;uniqueIndex:uk_skill_grants_subject"`
	SkillID     string    `gorm:"size:64;not null;index:idx_skill_grants_skill;uniqueIndex:uk_skill_grants_subject"`
	SubjectType string    `gorm:"size:32;not null;index:idx_skill_grants_subject;uniqueIndex:uk_skill_grants_subject"`
	SubjectID   string    `gorm:"size:64;not null;index:idx_skill_grants_subject;uniqueIndex:uk_skill_grants_subject"`
	Role        string    `gorm:"size:32;not null;default:'view'"`
	CreatedBy   string    `gorm:"size:64;not null"`
	UpdatedBy   string    `gorm:"size:64;not null"`
	CreatedAt   time.Time `gorm:"not null"`
	UpdatedAt   time.Time `gorm:"not null;index"`
}

// TableName returns the stable human/workspace Skill grant table name.
func (SkillGrant) TableName() string { return "skill_grants" }

// AgentAccessibleSkill pairs persisted Skill metadata with the agent binding
// that made it accessible; it is a store projection, not an API DTO.
type AgentAccessibleSkill struct {
	Skill
	Binding SkillAgentBinding
}
