package agent

import (
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/store/storeerr"
)

// ValidateCreateProjectParams normalizes and validates a Project create.
//
// WorkspaceID, MachineID, and RootPath are required and surface as typed
// storeerr.BadRequest when missing. RootPath MUST be an absolute path —
// reuses the review-target predicate because the field has the same
// filesystem semantics.
//
// Visibility defaults to ProjectVisibilityPrivate when empty; an invalid
// non-empty value is rejected. Name and Description are trimmed of leading/
// trailing whitespace; both may be empty after trim (the UI shows a fallback).
//
// OwnerUserID is intentionally NOT a parameter — the store resolves it
// from the authenticating user, so callers cannot forge ownership.
func ValidateCreateProjectParams(params CreateProjectParams) (CreateProjectParams, error) {
	normalized := CreateProjectParams{
		WorkspaceID: strings.TrimSpace(params.WorkspaceID),
		MachineID:   strings.TrimSpace(params.MachineID),
		RootPath:    params.RootPath,
		Name:        strings.TrimSpace(params.Name),
		Description: strings.TrimSpace(params.Description),
		Visibility:  strings.TrimSpace(params.Visibility),
	}
	if normalized.WorkspaceID == "" {
		return CreateProjectParams{}, storeerr.BadRequest("workspaceId is required")
	}
	if normalized.MachineID == "" {
		return CreateProjectParams{}, storeerr.BadRequest("machineId is required")
	}
	if !isAbsoluteTargetPath(normalized.RootPath) {
		return CreateProjectParams{}, storeerr.BadRequest("rootPath must be an absolute path")
	}
	if normalized.Visibility == "" {
		normalized.Visibility = ProjectVisibilityPrivate
	}
	if !isValidProjectVisibility(normalized.Visibility) {
		return CreateProjectParams{}, storeerr.BadRequest("visibility must be 'private' or 'workspace'")
	}
	return normalized, nil
}

// ValidateUpdateProjectParams normalizes a partial update. Each non-nil
// pointer is normalized in place; nil pointers are left untouched so the
// store can apply "preserve existing" semantics. An invalid Visibility
// value is rejected with storeerr.BadRequest.
func ValidateUpdateProjectParams(params UpdateProjectParams) (UpdateProjectParams, error) {
	normalized := params
	if normalized.Name != nil {
		trimmed := strings.TrimSpace(*normalized.Name)
		normalized.Name = &trimmed
	}
	if normalized.Description != nil {
		trimmed := strings.TrimSpace(*normalized.Description)
		normalized.Description = &trimmed
	}
	if normalized.Visibility != nil {
		v := strings.TrimSpace(*normalized.Visibility)
		if !isValidProjectVisibility(v) {
			return UpdateProjectParams{}, storeerr.BadRequest("visibility must be 'private' or 'workspace'")
		}
		normalized.Visibility = &v
	}
	return normalized, nil
}

// ValidateProjectGrantRole rejects any role value that is not manage/view.
// ProjectRoleOwner is intentionally excluded — owner is derived from
// projects.owner_user_id, never persisted as a grant.
func ValidateProjectGrantRole(role string) error {
	switch role {
	case ProjectRoleManage, ProjectRoleView:
		return nil
	default:
		return storeerr.BadRequest("project grant role must be 'manage' or 'view'")
	}
}

func isValidProjectVisibility(v string) bool {
	return v == ProjectVisibilityPrivate || v == ProjectVisibilityWorkspace
}
