package events

import (
	"bit.admedia.com/scm/ad/adpilot-indexing-repo-sync.com/internal/contracts/metadata"
)

// ChangeType describes how a file changed in a commit.
type ChangeType string

const (
	ChangeTypeAdded    ChangeType = "added"
	ChangeTypeModified ChangeType = "modified"
	ChangeTypeDeleted  ChangeType = "deleted"
	ChangeTypeRenamed  ChangeType = "renamed"
)

// FileKind describes how downstream services should route a changed file.
type FileKind string

const (
	FileKindCode    FileKind = "code"
	FileKindDocs    FileKind = "docs"
	FileKindConfig  FileKind = "config"
	FileKindTest    FileKind = "test"
	FileKindAsset   FileKind = "asset"
	FileKindUnknown FileKind = "unknown"
)

// ValidChangeTypes lists supported change_type values.
var ValidChangeTypes = []ChangeType{
	ChangeTypeAdded,
	ChangeTypeModified,
	ChangeTypeDeleted,
	ChangeTypeRenamed,
}

// ValidFileKinds lists supported file_kind values.
var ValidFileKinds = []FileKind{
	FileKindCode,
	FileKindDocs,
	FileKindConfig,
	FileKindTest,
	FileKindAsset,
	FileKindUnknown,
}

// IsValid reports whether the change type is supported.
func (c ChangeType) IsValid() bool {
	switch c {
	case ChangeTypeAdded, ChangeTypeModified, ChangeTypeDeleted, ChangeTypeRenamed:
		return true
	default:
		return false
	}
}

// IsValid reports whether the file kind is supported.
func (k FileKind) IsValid() bool {
	switch k {
	case FileKindCode, FileKindDocs, FileKindConfig, FileKindTest, FileKindAsset, FileKindUnknown:
		return true
	default:
		return false
	}
}

// FileChangedEvent is published when a repository file changes.
type FileChangedEvent struct {
	metadata.Envelope
	RepoID      string     `json:"repo_id"`
	SnapshotID  string     `json:"snapshot_id"`
	CommitSHA   string     `json:"commit_sha"`
	FilePath    string     `json:"file_path"`
	Language    string     `json:"language"`
	FileKind    FileKind   `json:"file_kind"`
	ChangeType  ChangeType `json:"change_type"`
	ArtifactURI string     `json:"artifact_uri,omitempty"`
	OldPath     string     `json:"old_path,omitempty"`
}

// NewFileChangedEvent creates a v1 file changed event with required metadata.
func NewFileChangedEvent(eventID, repoID, snapshotID, commitSHA, filePath, language string, fileKind FileKind, changeType ChangeType) FileChangedEvent {
	return FileChangedEvent{
		Envelope:   metadata.NewEnvelope(eventID),
		RepoID:     repoID,
		SnapshotID: snapshotID,
		CommitSHA:  commitSHA,
		FilePath:   filePath,
		Language:   language,
		FileKind:   fileKind,
		ChangeType: changeType,
	}
}
