// Package mailstore adapts the generic Installation and Connection stores for the
// stateless Email extension.
package mailstore

import (
	"context"
	"fmt"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
	"github.com/tidbcloud/AgentTeam/internal/store/app"
	"github.com/tidbcloud/AgentTeam/internal/store/app/runtime"
)

// Store is the Email adapter over generic App and Service Actor persistence.
// It does not own any Email-specific runtime tables.
type Store struct {
	db   coredb.DB
	apps NamedAppPersistence
}

// NamedAppPersistence is the reusable App substrate used by Email setup.
type NamedAppPersistence interface {
	RequireWorkspaceAppManagementForUser(
		context.Context,
		string,
		string,
	) error
	FinalizeNamedAppInstallationForWorkspaceAdmin(
		context.Context,
		string,
		string,
		app.NamedAppInstallationParams,
		app.NamedAppMutationHooks,
	) (app.NamedAppInstallationView, error)
	FinalizeNamedAppReconnectForWorkspaceAdmin(
		context.Context,
		string,
		string,
		app.NamedAppReconnectParams,
		app.NamedAppMutationHooks,
	) (runtime.ConnectionView, error)
	DisconnectNamedAppConnectionForWorkspaceAdmin(
		context.Context,
		string,
		string,
		string,
		string,
		string,
		func(context.Context, coredb.Tx, time.Time) error,
	) error
}

// New constructs a Mail store.
func New(db coredb.DB) *Store {
	return &Store{db: db}
}

// NewWithNamedApps constructs the Email persistence adapter used by Human
// installation, reconnect, and disconnect management.
func NewWithNamedApps(
	db coredb.DB,
	apps NamedAppPersistence,
) *Store {
	store := New(db)
	store.apps = apps
	return store
}

// Validate checks the collaborators required by every Email operation.
func (store *Store) Validate() error {
	if store == nil || store.db == nil {
		return fmt.Errorf("mail store is not configured")
	}
	return nil
}

// RequireWorkspaceAppManagementForUser performs a fresh canonical authority
// check before the Email setup service does any external provider I/O.
func (store *Store) RequireWorkspaceAppManagementForUser(
	ctx context.Context,
	userID string,
	workspaceID string,
) error {
	if err := store.validateMailboxMaterializer(); err != nil {
		return err
	}
	return store.apps.RequireWorkspaceAppManagementForUser(
		ctx,
		userID,
		workspaceID,
	)
}

func (store *Store) validateMailboxMaterializer() error {
	if err := store.Validate(); err != nil {
		return err
	}
	if store.apps == nil {
		return fmt.Errorf("Mail named App persistence is not configured")
	}
	return nil
}
