package serviceaccount

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

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

type audienceScopeBaseline struct {
	ScopeID         string
	LatestSeq       int64
	LatestGlobalSeq int64
	Open            bool
}

// EnsureHumanAudienceMembershipsInTx attaches one active Human to every
// active service-account scope in the workspace. The scope tail is the unread
// baseline, while the service-account read contract continues to expose
// retained history to current audience members.
func (store *Store) EnsureHumanAudienceMembershipsInTx(
	ctx context.Context,
	tx coredb.Tx,
	workspaceID string,
	memberID string,
	now time.Time,
) error {
	if store == nil {
		return fmt.Errorf("service account audience store is not configured")
	}
	workspaceID = strings.TrimSpace(workspaceID)
	memberID = strings.TrimSpace(memberID)
	if workspaceID == "" || memberID == "" {
		return storeerr.BadRequest("workspaceId and memberId are required")
	}
	if tx == nil {
		return fmt.Errorf("service account audience transaction is not configured")
	}
	now = now.UTC()
	if now.IsZero() {
		now = time.Now().UTC()
	}

	var activeHuman bool
	if err := tx.QueryRow(ctx, `
SELECT EXISTS (
  SELECT 1
  FROM members
  WHERE id = $1
    AND workspace_id = $2
    AND type = 'human'
    AND status = 'active'
)
`, memberID, workspaceID).Scan(&activeHuman); err != nil {
		return fmt.Errorf("validate service account audience member: %w", err)
	}
	if !activeHuman {
		return storeerr.Conflict("service account audience member must be an active workspace Human")
	}

	rows, err := tx.Query(ctx, `
SELECT message_scope.id,
       message_scope.latest_seq,
       message_scope.latest_global_seq,
       EXISTS (
         SELECT 1
         FROM scope_memberships membership
         WHERE membership.scope_id = message_scope.id
           AND membership.member_id = $2
           AND membership.visibility = 'public'
           AND membership.effective_to_seq IS NULL
           AND membership.removed_at IS NULL
           AND membership.archived_at IS NULL
       ) AS has_open_membership
FROM service_accounts account
JOIN scopes message_scope
  ON message_scope.id = account.message_scope_id
 AND message_scope.workspace_id = account.workspace_id
 AND message_scope.type = 'service_account'
 AND message_scope.status = 'active'
WHERE account.workspace_id = $1
ORDER BY account.id ASC
FOR UPDATE
`, workspaceID, memberID)
	if err != nil {
		return fmt.Errorf("list service account audience scopes: %w", err)
	}
	baselines := make([]audienceScopeBaseline, 0)
	for rows.Next() {
		var baseline audienceScopeBaseline
		if err := rows.Scan(&baseline.ScopeID, &baseline.LatestSeq, &baseline.LatestGlobalSeq, &baseline.Open); err != nil {
			rows.Close()
			return fmt.Errorf("scan service account audience scope: %w", err)
		}
		baselines = append(baselines, baseline)
	}
	iterateErr := rows.Err()
	rows.Close()
	if iterateErr != nil {
		return fmt.Errorf("iterate service account audience scopes: %w", iterateErr)
	}

	repositories := message.NewScopeRepositories(tx)
	for _, baseline := range baselines {
		if !baseline.Open {
			if err := repositories.Memberships.Upsert(ctx, message.ScopeMembershipRecord{
				ScopeID:               baseline.ScopeID,
				MemberID:              memberID,
				Visibility:            "public",
				LastReadSeq:           baseline.LatestSeq,
				LastReadGlobalSeq:     baseline.LatestGlobalSeq,
				LastActivityGlobalSeq: baseline.LatestGlobalSeq,
				EffectiveFromSeq:      baseline.LatestSeq + 1,
				CreatedAt:             now,
				UpdatedAt:             now,
			}); err != nil {
				return err
			}
		}
		if err := repositories.Notifications.Upsert(ctx, message.ScopeNotificationSettingRecord{
			ScopeID:   baseline.ScopeID,
			MemberID:  memberID,
			State:     "active",
			CreatedAt: now,
			UpdatedAt: now,
		}); err != nil {
			return err
		}
	}
	return nil
}
