package projectsync

// ProvisionPlan describes the complete workspace topology that must be prepared
// for a project before any slot checkout or sync operation can run. Building it
// never executes a git process; it only resolves paths from a normalized Config.
type ProvisionPlan struct {
	ProjectWorkspaceRoot string
	MainBranchPath       string
	DevelopBranchPath    string
	DefaultSlotPath      string
}

// BuildProvisionPlan derives the workspace topology plan from a project sync
// Config. It returns ErrInvalidConfig when the Config cannot be normalized.
func BuildProvisionPlan(config Config) (ProvisionPlan, error) {
	normalized, err := config.Normalize()
	if err != nil {
		return ProvisionPlan{}, err
	}
	root, err := ProjectWorkspaceRoot(normalized.WorkspaceBasePath, normalized.RepoDirName)
	if err != nil {
		return ProvisionPlan{}, err
	}
	mainPath, err := BranchWorkspacePath(normalized.WorkspaceBasePath, normalized.RepoDirName, BranchNameMain)
	if err != nil {
		return ProvisionPlan{}, err
	}
	developPath, err := BranchWorkspacePath(normalized.WorkspaceBasePath, normalized.RepoDirName, BranchNameDevelop)
	if err != nil {
		return ProvisionPlan{}, err
	}
	defaultSlot, err := SlotWorkspacePath(normalized.WorkspaceBasePath, normalized.RepoDirName, DefaultSlotIndex)
	if err != nil {
		return ProvisionPlan{}, err
	}
	return ProvisionPlan{
		ProjectWorkspaceRoot: root,
		MainBranchPath:       mainPath,
		DevelopBranchPath:    developPath,
		DefaultSlotPath:      defaultSlot,
	}, nil
}

// CheckoutPlan is the policy object describing where a single workspace slot
// should be checked out for a project sync target. It is derived purely from a
// normalized Config and a reserved WorkspaceSlot; building it never runs a git
// process. Actual clone/fetch/checkout execution is out of this package's scope.
type CheckoutPlan struct {
	// RemoteURL and SourceBranch always come from the project sync Config, never
	// from request input, so every slot of the same project checks out the same
	// remote and source-of-truth branch.
	RemoteURL    string
	SourceBranch string
	// ProjectWorkspaceRoot is the per-project workspace root and SlotPath is this
	// slot's independent checkout directory under that root.
	ProjectWorkspaceRoot string
	SlotPath             string
	SlotIndex            SlotIndex
}

// BuildCheckoutPlan derives a CheckoutPlan from a project sync Config and a
// reserved slot. The git remote and source branch are read from the Config so
// they can never be spoofed by request input, and each slot resolves to its own
// zero-padded checkout path (000 for the default single-operation slot, 001/002
// for parallel slots). It returns ErrInvalidConfig when the Config or slot index
// is invalid.
func BuildCheckoutPlan(config Config, slot WorkspaceSlot) (CheckoutPlan, error) {
	normalized, err := config.Normalize()
	if err != nil {
		return CheckoutPlan{}, err
	}
	if !slot.Index.Valid() {
		return CheckoutPlan{}, ErrInvalidConfig
	}
	root, err := ProjectWorkspaceRoot(normalized.WorkspaceBasePath, normalized.RepoDirName)
	if err != nil {
		return CheckoutPlan{}, err
	}
	slotPath, err := SlotWorkspacePath(normalized.WorkspaceBasePath, normalized.RepoDirName, slot.Index)
	if err != nil {
		return CheckoutPlan{}, err
	}
	return CheckoutPlan{
		RemoteURL:            normalized.GitRemoteURL,
		SourceBranch:         normalized.SourceBranch,
		ProjectWorkspaceRoot: root,
		SlotPath:             slotPath,
		SlotIndex:            slot.Index,
	}, nil
}
