package org

import (
	"context"
	"errors"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/apr/agentteambridge"
	"github.com/tidbcloud/AgentTeam/internal/knowledgeqa/protocol"
	"github.com/tidbcloud/AgentTeam/internal/maas/availability"
	"github.com/tidbcloud/AgentTeam/internal/store/identity"
	"github.com/tidbcloud/AgentTeam/internal/store/organization"
	"github.com/tidbcloud/AgentTeam/internal/store/plan"
)

// Store is the authentication port used by organization routes.
type Store interface {
	AuthenticateSession(ctx context.Context, token string) (identity.AuthenticatedUser, error)
}

type Runtime interface {
	SyncMachineCatalog(ctx context.Context, machineID string) error
}

type LLMRegistryRefresher interface {
	Refresh(ctx context.Context) error
}

type HostedAvailabilityClient interface {
	LoadHostedAvailability(ctx context.Context, organizationID string) (availability.Availability, error)
}

type KnowledgeQAPolicyStore interface {
	LoadPolicyMetrics(context.Context, string) (protocol.PolicyMetrics, error)
	LoadOrganizationPolicy(context.Context, string) (protocol.OrganizationPolicy, error)
	UpdateOrganizationPolicy(context.Context, string, string, protocol.OrganizationPolicyUpdate, time.Time) (protocol.OrganizationPolicy, error)
}

type CodexProviderRuntime interface {
	CodexAuthSnapshots(organizationID string, providerID string) ([]agentteambridge.CodexAuthSnapshot, bool)
	ForceRefreshCodexAuth(ctx context.Context, organizationID string, providerID string, source string) ([]agentteambridge.CodexAuthRefreshResult, bool)
}

// PlanStore is the organization plan read surface used by org routes.
type PlanStore interface {
	LoadOrganizationPlanView(ctx context.Context, organizationID string) (plan.OrganizationPlanView, error)
}

// OrganizationProvider is the organization service surface consumed by org routes.
type OrganizationProvider interface {
	ListOrganizationsForUser(ctx context.Context, userID string) ([]organization.OrganizationSummary, error)
	RequireOrganizationAdmin(ctx context.Context, userID string, organizationID string) error
	PatchOrganizationForUser(ctx context.Context, userID string, organizationID string, params organization.UpdateOrganizationParams) (organization.OrganizationSummary, error)
	GetOrganizationSettingsForUser(ctx context.Context, userID string, organizationID string) (organization.OrganizationSettingsView, error)
	GetOrganizationHostedModelSettingsForUser(ctx context.Context, userID string, organizationID string) (organization.OrganizationHostedModelSettingsView, error)
	GetOrganizationDirectorySyncRunForUser(ctx context.Context, userID string, organizationID string, syncRunID string) (organization.OrganizationDirectorySyncRunDetailView, error)
	GetOrganizationEnterpriseFeishuForUser(ctx context.Context, userID string, organizationID string) (organization.OrganizationEnterpriseFeishuView, error)
	UpdateOrganizationEnterpriseFeishuCredentialsForUser(ctx context.Context, userID string, organizationID string, appID string, appSecret string) (organization.OrganizationEnterpriseFeishuView, error)
	DeleteOrganizationEnterpriseFeishuCredentialsForUser(ctx context.Context, userID string, organizationID string) (organization.OrganizationEnterpriseFeishuView, error)
	PatchOrganizationSettingsForUser(ctx context.Context, userID string, organizationID string, params organization.UpdateOrganizationSettingsParams) (organization.OrganizationSettingsView, error)
	PatchOrganizationHostedModelSettingsForUser(ctx context.Context, userID string, organizationID string, params organization.UpdateOrganizationHostedModelSettingsParams) (organization.OrganizationHostedModelSettingsView, error)
	StartOrganizationFeishuDirectorySyncForUser(ctx context.Context, userID string, organizationID string) (organization.OrganizationDirectorySyncRunSummaryView, bool, error)
	RunOrganizationFeishuDirectorySyncForUser(ctx context.Context, userID string, organizationID string, syncRunID string) (organization.OrganizationFeishuDirectoryImportResult, error)
	SyncOrganizationFeishuDirectoryForUser(ctx context.Context, userID string, organizationID string) (organization.OrganizationFeishuDirectoryImportResult, error)
	ListOrganizationInvitesForUser(ctx context.Context, userID string, organizationID string) ([]organization.OrganizationInviteView, error)
	CreateOrganizationInviteForUser(ctx context.Context, userID string, organizationID string, params organization.CreateOrganizationInviteParams, tokenHash string, expiresAt time.Time) (organization.OrganizationInviteView, error)
	RevokeOrganizationInviteForUser(ctx context.Context, userID string, organizationID string, inviteID string) error
	ListOrganizationUnitsForUser(ctx context.Context, userID string, organizationID string) ([]organization.OrganizationUnitView, error)
	CreateOrganizationUnitForUser(ctx context.Context, userID string, organizationID string, params organization.CreateOrganizationUnitParams) (organization.OrganizationUnitView, error)
	ListOrganizationUnitMembersForUser(ctx context.Context, userID string, organizationID string, unitID string) ([]organization.OrganizationUnitMemberView, error)
	AddOrganizationUnitMemberForUser(ctx context.Context, userID string, organizationID string, unitID string, params organization.AddOrganizationUnitMemberParams) (organization.OrganizationUnitMemberView, error)
	RemoveOrganizationUnitMemberForUser(ctx context.Context, userID string, organizationID string, unitID string, memberID string) error
	ListOrganizationMemberUnitsForUser(ctx context.Context, userID string, organizationID string, memberID string) ([]organization.OrganizationMemberUnitView, error)
	ListOrganizationTeamsForUser(ctx context.Context, userID string, organizationID string) ([]organization.OrganizationTeamView, error)
	CreateOrganizationTeamForUser(ctx context.Context, userID string, organizationID string, name string, slug string, description string) (organization.OrganizationTeamView, error)
	ListOrganizationTeamMembersForUser(ctx context.Context, userID string, organizationID string, teamID string) ([]organization.OrganizationTeamMemberView, error)
	AddOrganizationTeamMemberForUser(ctx context.Context, userID string, organizationID string, teamID string, params organization.AddOrganizationTeamMemberParams) (organization.OrganizationTeamMemberView, error)
	RemoveOrganizationTeamMemberForUser(ctx context.Context, userID string, organizationID string, teamID string, memberID string) error
	SwitchOrganizationMemberPrimaryTeamForUser(ctx context.Context, userID string, organizationID string, memberID string, teamID string) (organization.OrganizationMemberView, error)
	ListOrganizationMembersForUser(ctx context.Context, userID string, organizationID string) ([]organization.OrganizationMemberView, error)
	ListOrganizationMembersForUserPage(ctx context.Context, userID string, organizationID string, options organization.OrganizationMemberListOptions) (organization.OrganizationMemberPage, error)
	CreateOrganizationMemberForUser(ctx context.Context, userID string, organizationID string, teamID string, email string, defaultWorkspaceRole string) (organization.OrganizationMemberView, error)
	UpdateOrganizationMemberRoleForUser(ctx context.Context, userID string, organizationID string, memberID string, role string) (organization.OrganizationMemberView, error)
	PreviewOrganizationMemberRemovalImpactForUser(ctx context.Context, userID string, organizationID string, memberID string) (organization.OrganizationMemberRemovalImpact, error)
	RemoveOrganizationMemberForUser(ctx context.Context, userID string, organizationID string, memberID string) (organization.OrganizationMemberRemovalResult, error)
	ListOrganizationWorkspacesForUser(ctx context.Context, userID string, organizationID string) ([]organization.OrganizationWorkspaceView, error)
	CreateOrganizationWorkspaceForUser(ctx context.Context, userID string, organizationID string, name string, slug string) (organization.OrganizationWorkspaceView, error)
	ListOrganizationProvidersForUser(ctx context.Context, userID string, organizationID string) ([]organization.OrganizationProviderView, error)
	ListOrganizationProviderRoutesForUser(ctx context.Context, userID string, organizationID string) ([]organization.OrganizationProviderRouteView, error)
	CreateOrganizationProviderRouteForUser(ctx context.Context, userID string, organizationID string, params organization.CreateOrganizationProviderRouteParams) (organization.OrganizationProviderRouteView, error)
	UpdateOrganizationProviderRouteForUser(ctx context.Context, userID string, organizationID string, routeID string, params organization.UpdateOrganizationProviderRouteParams) (organization.OrganizationProviderRouteView, error)
	DeleteOrganizationProviderRouteForUser(ctx context.Context, userID string, organizationID string, routeID string) error
	ListOrganizationProviderRouteGroupsForUser(ctx context.Context, userID string, organizationID string, routeID string) ([]organization.OrganizationProviderRouteGroupView, error)
	CreateOrganizationProviderRouteGroupForUser(ctx context.Context, userID string, organizationID string, routeID string, params organization.CreateOrganizationProviderRouteGroupParams) (organization.OrganizationProviderRouteGroupView, error)
	UpdateOrganizationProviderRouteGroupForUser(ctx context.Context, userID string, organizationID string, routeID string, groupID string, params organization.UpdateOrganizationProviderRouteGroupParams) (organization.OrganizationProviderRouteGroupView, error)
	DeleteOrganizationProviderRouteGroupForUser(ctx context.Context, userID string, organizationID string, routeID string, groupID string) error
	GetOrganizationProviderForUser(ctx context.Context, userID string, organizationID string, providerID string) (organization.OrganizationProviderView, error)
	CreateOrganizationProviderForUser(ctx context.Context, userID string, organizationID string, params organization.CreateOrganizationProviderParams) (organization.OrganizationProviderView, error)
	UpdateOrganizationProviderForUser(ctx context.Context, userID string, organizationID string, providerID string, params organization.UpdateOrganizationProviderParams) (organization.OrganizationProviderView, error)
	DeleteOrganizationProviderForUser(ctx context.Context, userID string, organizationID string, providerID string) error
	ListOrganizationProviderTokensForUser(ctx context.Context, userID string, organizationID string, providerID string) ([]organization.OrganizationProviderTokenView, error)
	CreateOrganizationProviderTokenForUser(ctx context.Context, userID string, organizationID string, providerID string, params organization.CreateOrganizationProviderTokenParams) (organization.OrganizationProviderTokenView, error)
	DeleteOrganizationProviderTokenForUser(ctx context.Context, userID string, organizationID string, providerID string, tokenID string) error
	ListOrganizationLLMProxyKeysForUser(ctx context.Context, userID string, organizationID string) ([]organization.OrganizationLLMProxyKeyView, error)
	CreateOrganizationLLMProxyKeyForUser(ctx context.Context, userID string, organizationID string, params organization.CreateOrganizationLLMProxyKeyParams) (organization.OrganizationLLMProxyKeyCreateResult, error)
	DeleteOrganizationLLMProxyKeyForUser(ctx context.Context, userID string, organizationID string, keyID string) error
	ListOrganizationLLMStatsSummaryForUser(ctx context.Context, userID string, organizationID string) ([]organization.OrganizationLLMStatsSummaryView, error)
	ListOrganizationLLMStatsDetailForUser(ctx context.Context, userID string, organizationID string, query organization.OrganizationLLMStatsQuery) ([]organization.OrganizationLLMStatsDetailView, error)
	GetOrganizationLLMStatsTimeSeriesForUser(ctx context.Context, userID string, organizationID string, query organization.OrganizationLLMStatsQuery) (organization.OrganizationLLMTimeSeriesView, error)
	GetOrganizationLLMErrorSummaryForUser(ctx context.Context, userID string, organizationID string, query organization.OrganizationLLMStatsQuery) (organization.OrganizationLLMErrorSummaryView, error)
	GetOrganizationLLMErrorTimeSeriesForUser(ctx context.Context, userID string, organizationID string, query organization.OrganizationLLMStatsQuery) (organization.OrganizationLLMErrorTimeSeriesView, error)
	ListOrganizationLLMQuotaPoliciesForUser(ctx context.Context, userID string, organizationID string) ([]organization.OrganizationLLMQuotaPolicyView, error)
	UpsertOrganizationLLMQuotaPolicyForUser(ctx context.Context, userID string, organizationID string, params organization.UpsertOrganizationLLMQuotaPolicyParams) (organization.OrganizationLLMQuotaPolicyView, error)
	DeleteOrganizationLLMQuotaPolicyForUser(ctx context.Context, userID string, organizationID string, subjectType string, subjectID string) error
	CreateInternalWorkspaceProxyKey(ctx context.Context, workspaceID string, expiresAt time.Time) (string, error)
	ListOrganizationWorkspaceProviderGrantsForUser(ctx context.Context, userID string, organizationID string, workspaceID string) ([]organization.OrganizationWorkspaceProviderGrantView, error)
	ListOrganizationWorkspaceRouteGrantsForUser(ctx context.Context, userID string, organizationID string, workspaceID string) ([]organization.OrganizationWorkspaceRouteGrantView, error)
	GrantOrganizationWorkspaceProviderForUser(ctx context.Context, userID string, organizationID string, workspaceID string, providerID string) (organization.OrganizationWorkspaceProviderGrantView, error)
	GrantOrganizationWorkspaceRouteForUser(ctx context.Context, userID string, organizationID string, workspaceID string, routeID string) (organization.OrganizationWorkspaceRouteGrantView, error)
	RevokeOrganizationWorkspaceProviderForUser(ctx context.Context, userID string, organizationID string, workspaceID string, providerID string) error
	RevokeOrganizationWorkspaceRouteForUser(ctx context.Context, userID string, organizationID string, workspaceID string, routeID string) error
	GetOrganizationWorkspaceHostedModelAuthorizationForUser(ctx context.Context, userID string, organizationID string, workspaceID string) (organization.OrganizationWorkspaceHostedModelAuthorizationView, error)
	PreviewOrganizationWorkspaceHostedModelAuthorizationForUser(ctx context.Context, userID string, organizationID string, workspaceID string, params organization.UpsertOrganizationWorkspaceHostedModelAuthorizationParams) (organization.OrganizationWorkspaceHostedModelAuthorizationView, error)
	UpsertOrganizationWorkspaceHostedModelAuthorizationForUser(ctx context.Context, userID string, organizationID string, workspaceID string, params organization.UpsertOrganizationWorkspaceHostedModelAuthorizationParams) (organization.OrganizationWorkspaceHostedModelAuthorizationView, error)
	ListVisibleOrganizationProvidersForWorkspace(ctx context.Context, workspaceID string) ([]organization.OrganizationProviderView, error)
	ListOrganizationWorkspaceGrantsForUser(ctx context.Context, userID string, organizationID string, workspaceID string) ([]organization.OrganizationWorkspaceGrantView, error)
	GrantOrganizationMemberWorkspaceAccessForUser(ctx context.Context, userID string, organizationID string, workspaceID string, memberID string, role string) (organization.OrganizationWorkspaceGrantView, error)
	RevokeOrganizationMemberWorkspaceAccessForUser(ctx context.Context, userID string, organizationID string, workspaceID string, memberID string) error
	ListOrganizationWorkspaceTeamGrantsForUser(ctx context.Context, userID string, organizationID string, workspaceID string) ([]organization.OrganizationWorkspaceTeamGrantView, error)
	GrantOrganizationTeamWorkspaceAccessForUser(ctx context.Context, userID string, organizationID string, workspaceID string, teamID string, role string) (organization.OrganizationWorkspaceTeamGrantView, error)
	RevokeOrganizationTeamWorkspaceAccessForUser(ctx context.Context, userID string, organizationID string, workspaceID string, teamID string) error
}

func isOrganizationProviderForbidden(err error) bool {
	return errors.Is(err, organization.ErrForbidden)
}
