package sync

import "time"

// ChangeType represents the type of file change in a delta.
type ChangeType string

const (
	ChangeCreate ChangeType = "create"
	ChangeUpdate ChangeType = "update"
	ChangeDelete ChangeType = "delete"
	ChangeRename ChangeType = "rename"
)

// ResolutionStrategy defines how to resolve a sync conflict.
type ResolutionStrategy string

const (
	ResolutionLastWriteWins ResolutionStrategy = "last-write-wins"
	ResolutionRenameBoth    ResolutionStrategy = "rename-both"
	ResolutionManualMerge   ResolutionStrategy = "manual-merge"
	ResolutionServerWins    ResolutionStrategy = "server-wins"
	ResolutionClientWins    ResolutionStrategy = "client-wins"
)

// FileEntry represents a single file in a snapshot.
type FileEntry struct {
	Path     string    `json:"path"`
	Hash     string    `json:"hash"`
	Size     int64     `json:"size"`
	Modified time.Time `json:"modified"`
}

// Snapshot represents a point-in-time view of the filesystem.
type Snapshot struct {
	ID        string      `json:"id"`
	DeviceID  string      `json:"deviceId"`
	UserID    string      `json:"userId,omitempty"`
	CreatedAt time.Time   `json:"createdAt"`
	Files     []FileEntry `json:"files"`
}

// Change represents a single file change.
type Change struct {
	Type     ChangeType `json:"type"`
	Path     string     `json:"path"`
	OldPath  string     `json:"oldPath,omitempty"`
	Hash     string     `json:"hash,omitempty"`
	Content  string     `json:"content,omitempty"`
	Size     int64      `json:"size,omitempty"`
	Modified time.Time  `json:"modified,omitempty"`
}

// Delta is a list of changes since a snapshot.
type Delta struct {
	Changes []Change `json:"changes"`
}

// Conflict represents a file changed on both client and server.
type Conflict struct {
	Path           string             `json:"path"`
	ServerHash     string             `json:"serverHash"`
	ClientHash     string             `json:"clientHash"`
	ServerModified time.Time          `json:"serverModified"`
	ClientModified time.Time          `json:"clientModified"`
	Strategy       ResolutionStrategy `json:"strategy,omitempty"`
}

// DeltaResult is the server's response to a delta upload.
type DeltaResult struct {
	ServerDelta   []Change   `json:"serverDelta"`
	Conflicts     []Conflict `json:"conflicts"`
	NewSnapshotID string     `json:"newSnapshotId,omitempty"`
}

// Resolution is a user's choice for resolving a conflict.
type Resolution struct {
	Path     string             `json:"path"`
	Strategy ResolutionStrategy `json:"strategy"`
	NewPath  string             `json:"newPath,omitempty"` // for rename-both
	Hash     string             `json:"hash,omitempty"`
	Content  string             `json:"content,omitempty"`
}

// InitRequest starts a new sync session.
type InitRequest struct {
	DeviceID string `json:"deviceId"`
	RootPath string `json:"rootPath"`
}

// InitResponse returns the server's current snapshot.
type InitResponse struct {
	SnapshotID     string      `json:"snapshotId"`
	ServerSnapshot []FileEntry `json:"serverSnapshot"`
}

// DeltaRequest uploads client changes.
type DeltaRequest struct {
	SnapshotID  string   `json:"snapshotId"`
	ClientDelta []Change `json:"clientDelta"`
}

// DeltaResponse returns server changes and conflicts.
type DeltaResponse struct {
	ServerDelta   []Change   `json:"serverDelta"`
	Conflicts     []Conflict `json:"conflicts"`
	NewSnapshotID string     `json:"newSnapshotId,omitempty"`
}

// ResolveRequest uploads conflict resolutions.
type ResolveRequest struct {
	SnapshotID  string       `json:"snapshotId"`
	Resolutions []Resolution `json:"resolutions"`
}

// ResolveResponse confirms the new snapshot.
type ResolveResponse struct {
	NewSnapshotID string `json:"newSnapshotId"`
}
