package app

import (
	"context"
	"errors"

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

type ProviderWatchView = ServiceEventSubscriptionView

type ProviderWatchActionResult struct {
	Status        string
	AlreadyExists bool
	Watch         ProviderWatchView
	BindingID     string
	Message       string
}

func providerWatchEventsMap(events []string) map[string]any {
	return serviceEventSubscriptionEventsMap(events)
}

func providerWatchUserError(err error) error {
	if err != nil && errors.Is(err, storeerr.ErrNotFound) {
		return storeerr.NotFound("watch_not_found")
	}
	return err
}

func providerWatchActionResultFromServiceEventSubscription(result ServiceEventSubscriptionActionResult) ProviderWatchActionResult {
	return ProviderWatchActionResult{
		Status:        result.Status,
		AlreadyExists: result.AlreadyExists,
		Watch:         result.Subscription,
		BindingID:     result.BindingID,
		Message:       result.Message,
	}
}

func (store *Store) authorizeProviderWatchUser(ctx context.Context, userID string, workspaceID string) error {
	_, err := store.loadAuthorizedHumanWorkspaceMember(ctx, store.db, userID, workspaceID, workspaceAccessAction)
	return err
}

func (store *Store) ListProviderWatchesForUser(ctx context.Context, userID string, workspaceID string, installationID string, target string, resource string, status string, limit int) ([]ProviderWatchView, error) {
	if err := store.authorizeProviderWatchUser(ctx, userID, workspaceID); err != nil {
		return nil, err
	}
	return store.ListServiceEventSubscriptionsForUser(ctx, userID, workspaceID, installationID, target, resource, status, limit)
}

func (store *Store) GetProviderWatchForUser(ctx context.Context, userID string, workspaceID string, watchID string) (ProviderWatchView, error) {
	if err := store.authorizeProviderWatchUser(ctx, userID, workspaceID); err != nil {
		return ProviderWatchView{}, err
	}
	view, err := store.GetServiceEventSubscriptionForUser(ctx, userID, workspaceID, watchID)
	return view, providerWatchUserError(err)
}

func (store *Store) CreateProviderWatchForUser(ctx context.Context, userID string, workspaceID string, installationID string, target string, prRefOrURL string, events []string, notifyPrincipal *bool) (ProviderWatchActionResult, error) {
	if err := store.authorizeProviderWatchUser(ctx, userID, workspaceID); err != nil {
		return ProviderWatchActionResult{}, err
	}
	result, err := store.CreateServiceEventSubscriptionForUser(ctx, userID, workspaceID, installationID, target, prRefOrURL, events, notifyPrincipal)
	if err != nil {
		return ProviderWatchActionResult{}, providerWatchUserError(err)
	}
	return providerWatchActionResultFromServiceEventSubscription(result), nil
}

func (store *Store) PauseProviderWatchForUser(ctx context.Context, userID string, workspaceID string, watchID string) (ProviderWatchActionResult, error) {
	if err := store.authorizeProviderWatchUser(ctx, userID, workspaceID); err != nil {
		return ProviderWatchActionResult{}, err
	}
	result, err := store.PauseServiceEventSubscriptionForUser(ctx, userID, workspaceID, watchID)
	if err != nil {
		return ProviderWatchActionResult{}, providerWatchUserError(err)
	}
	return providerWatchActionResultFromServiceEventSubscription(result), nil
}

func (store *Store) ResumeProviderWatchForUser(ctx context.Context, userID string, workspaceID string, watchID string) (ProviderWatchActionResult, error) {
	if err := store.authorizeProviderWatchUser(ctx, userID, workspaceID); err != nil {
		return ProviderWatchActionResult{}, err
	}
	result, err := store.ResumeServiceEventSubscriptionForUser(ctx, userID, workspaceID, watchID)
	if err != nil {
		return ProviderWatchActionResult{}, providerWatchUserError(err)
	}
	return providerWatchActionResultFromServiceEventSubscription(result), nil
}

func (store *Store) RemoveProviderWatchForUser(ctx context.Context, userID string, workspaceID string, watchID string) (ProviderWatchActionResult, error) {
	if err := store.authorizeProviderWatchUser(ctx, userID, workspaceID); err != nil {
		return ProviderWatchActionResult{}, err
	}
	result, err := store.RemoveServiceEventSubscriptionForUser(ctx, userID, workspaceID, watchID)
	if err != nil {
		return ProviderWatchActionResult{}, providerWatchUserError(err)
	}
	return providerWatchActionResultFromServiceEventSubscription(result), nil
}
