package contract

import (
	"context"

	"github.com/nexuscrm/shared/pkg/models"
)

// ApplicationNavigation is the neutral application/navigation catalog surface
// used by API dialects. L0 owns app metadata persistence and effective
// app/tab visibility; dialects own vendor URL shapes, envelopes, and tab string
// grammars.
type ApplicationNavigation interface {
	ListApplications(ctx context.Context) ([]*models.AppConfig, error)
	ListVisibleApplications(ctx context.Context, user *models.UserSession) ([]*models.AppConfig, error)
	GetApplication(ctx context.Context, id string) (*models.AppConfig, error)
	CreateApplication(ctx context.Context, app *models.AppConfig) error
	UpdateApplication(ctx context.Context, id string, updates *models.AppConfig, presence ApplicationPatchPresence) error
	DeleteApplication(ctx context.Context, id string) error
}

type ApplicationPatchPresence struct {
	IsDefaultProvided bool
	// NavigationItemIdentities identifies requested navigation items for sparse
	// PATCH merges. Dialects map wire grammar into these neutral identities; the
	// owner of app metadata performs the merge atomically with the update.
	NavigationItemIdentities []ApplicationNavigationItemIdentity
}

type ApplicationNavigationItemIdentityKind string

const (
	ApplicationNavigationItemIdentityObject ApplicationNavigationItemIdentityKind = "object"
	ApplicationNavigationItemIdentityPage   ApplicationNavigationItemIdentityKind = "page"
	ApplicationNavigationItemIdentityID     ApplicationNavigationItemIdentityKind = "id"
)

type ApplicationNavigationItemIdentity struct {
	Kind ApplicationNavigationItemIdentityKind
	Key  string
}

type ApplicationNavigationErrorKind string

const (
	ApplicationNavigationErrorValidation ApplicationNavigationErrorKind = "validation"
	ApplicationNavigationErrorNotFound   ApplicationNavigationErrorKind = "not_found"
	ApplicationNavigationErrorConflict   ApplicationNavigationErrorKind = "conflict"
	ApplicationNavigationErrorForbidden  ApplicationNavigationErrorKind = "forbidden"
	ApplicationNavigationErrorInternal   ApplicationNavigationErrorKind = "internal"
	ApplicationNavigationErrorServer     ApplicationNavigationErrorKind = "server"
)

type ApplicationNavigationError struct {
	Kind    ApplicationNavigationErrorKind
	Field   string
	Message string
	Cause   error
}

func (e *ApplicationNavigationError) Error() string {
	if e == nil {
		return ""
	}
	return e.Message
}

func (e *ApplicationNavigationError) Unwrap() error {
	if e == nil {
		return nil
	}
	return e.Cause
}
