package organization

import (
	"context"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/core/identifiers"
	"github.com/tidbcloud/AgentTeam/internal/coredb"
	"github.com/tidbcloud/AgentTeam/internal/store/model"
)

func (txs TxStore) ensureOrganizationDefaultTeamMembership(ctx context.Context, tx coredb.Tx, organizationID string, memberID string, userID string) error {
	defaultTeamID, _, err := txs.resolveOrganizationTeam(ctx, tx, organizationID, "")
	if err != nil {
		return err
	}
	if err := txs.upsertOrganizationTeamMembership(ctx, tx, organizationID, defaultTeamID, memberID, userID, false); err != nil {
		return err
	}
	return nil
}

func (txs TxStore) ensureOrganizationDefaultTeamMembershipForMember(ctx context.Context, tx coredb.Tx, organizationID string, memberID string) error {
	account, err := txs.loadActiveOrganizationMember(ctx, tx, organizationID, memberID)
	if err != nil {
		if errors.Is(err, ErrNotFound) {
			return nil
		}
		return err
	}
	if strings.TrimSpace(account.UserID) == "" {
		return nil
	}
	return txs.ensureOrganizationDefaultTeamMembership(ctx, tx, organizationID, memberID, account.UserID)
}

func (txs TxStore) createDefaultOrganizationWorkspaceInTx(ctx context.Context, tx coredb.Tx, organizationID string, owner model.User, workspaceName string, defaultTeamID string) (WorkspaceSummary, error) {
	summary, err := txs.core.CreateWorkspaceInTx(ctx, tx, organizationID, owner, workspaceName)
	if err != nil {
		return WorkspaceSummary{}, fmt.Errorf("create default organization workspace: %w", err)
	}

	now := time.Now().UTC()
	if _, err := tx.Exec(ctx, `
UPDATE organization_settings
SET default_workspace_id = $2,
    updated_at = $3
WHERE organization_id = $1
`, organizationID, summary.WorkspaceID, now); err != nil {
		return WorkspaceSummary{}, fmt.Errorf("update organization default workspace: %w", err)
	}

	if err := txs.grantOrganizationDefaultTeamWorkspace(ctx, tx, organizationID, summary.WorkspaceID, defaultTeamID, owner.ID, now); err != nil {
		return WorkspaceSummary{}, err
	}
	if err := txs.bootstrapInitialDefaultWorkspaceHostedAuthorizationInTx(ctx, tx, organizationID, summary.WorkspaceID, owner.ID); err != nil {
		return WorkspaceSummary{}, err
	}
	return summary, nil
}

func (txs TxStore) grantOrganizationDefaultTeamWorkspace(ctx context.Context, tx coredb.Tx, organizationID string, workspaceID string, defaultTeamID string, userID string, now time.Time) error {
	grantID, err := identifiers.NewEntityID("ogtg")
	if err != nil {
		return fmt.Errorf("generate default organization team grant id: %w", err)
	}
	if err := execPortableUpdateThenInsert(
		ctx,
		tx,
		`
SELECT 1
FROM organization_workspace_team_grants
WHERE workspace_id = $1
  AND organization_team_id = $2
`,
		[]any{workspaceID, defaultTeamID},
		`
UPDATE organization_workspace_team_grants
SET workspace_role = 'member',
    status = 'active',
    source = 'manual',
    granted_by_user_id = $3,
    updated_at = $4
WHERE workspace_id = $1
  AND organization_team_id = $2
`,
		[]any{workspaceID, defaultTeamID, userID, now},
		`
INSERT INTO organization_workspace_team_grants (
    id,
    organization_id,
    workspace_id,
    organization_team_id,
    workspace_role,
    status,
    source,
    granted_by_user_id,
    created_at,
    updated_at
) VALUES ($1, $2, $3, $4, 'member', 'active', 'manual', $5, $6, $6)
`,
		[]any{grantID, organizationID, workspaceID, defaultTeamID, userID, now},
	); err != nil {
		return fmt.Errorf("insert default organization workspace team grant: %w", err)
	}

	memberIDs, err := txs.listActiveOrganizationMemberIDsForTeam(ctx, tx, organizationID, defaultTeamID)
	if err != nil {
		return err
	}
	for _, memberID := range memberIDs {
		if _, _, _, err := txs.reconcileOrganizationMemberWorkspaceProjection(ctx, tx, organizationID, workspaceID, memberID); err != nil {
			return err
		}
	}
	return nil
}
