package channel

import (
	"context"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestResolveChannelAccessForUserReturnsJoinedChannelVisibility(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	pool := startChannelDiscoveryTestDB(t, ctx)
	now := time.Date(2026, 7, 9, 12, 5, 0, 0, time.UTC)

	const (
		workspaceID    = "wsp_channel_access_visibility"
		ownerUserID    = "usr_channel_access_visibility_owner"
		ownerMemberID  = "mem_channel_access_visibility_owner"
		viewerUserID   = "usr_channel_access_visibility_viewer"
		viewerMemberID = "mem_channel_access_visibility_viewer"
		channelID      = "chn_channel_access_visibility_public"
	)

	seedChannelDiscoveryWorkspace(t, ctx, pool, workspaceID, ownerUserID, ownerMemberID, now)
	seedChannelDiscoveryUserMember(t, ctx, pool, workspaceID, viewerUserID, viewerMemberID, now)
	seedChannelDiscoveryChannelScope(t, ctx, pool, workspaceID, channelID, "public-access-room", ownerMemberID, now)
	mustExecChannelDiscovery(t, ctx, pool, `
INSERT INTO scope_memberships (
    scope_id, member_id, visibility, owner_member_id, last_read_seq,
    last_read_global_seq, last_activity_global_seq, owner_context_dismissed_through_global_seq,
    effective_from_seq, effective_to_seq, created_at, updated_at, removed_at, archived_at
) VALUES ($1, $2, 'public', NULL, 0, 0, 0, 0, 0, NULL, $3, $3, NULL, NULL)
`, channelID, viewerMemberID, now)

	store := New(pool, Options{RequireWorkspaceAccess: func(ctx context.Context, userID string, workspaceID string) (string, error) {
		return channelDiscoveryRequireWorkspaceAccess(ctx, pool, userID, workspaceID)
	}})
	resolution, err := store.ResolveChannelAccessForUser(ctx, viewerUserID, workspaceID, channelID)
	require.NoError(t, err)
	require.Equal(t, ChannelAccessStatusJoined, resolution.Status)
	require.Equal(t, "public", resolution.Channel.Visibility)
}

func TestResolveChannelAccessProjectsCompletedTutorialAsOrdinaryChannel(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	pool := startChannelDiscoveryTestDB(t, ctx)
	now := time.Date(2026, 7, 29, 12, 5, 0, 0, time.UTC)

	const (
		workspaceID   = "wsp_channel_access_tutorial"
		ownerUserID   = "usr_channel_access_tutorial_owner"
		ownerMemberID = "mem_channel_access_tutorial_owner"
		channelID     = "chn_channel_access_tutorial"
	)

	seedChannelDiscoveryWorkspace(t, ctx, pool, workspaceID, ownerUserID, ownerMemberID, now)
	seedChannelDiscoveryChannelScope(t, ctx, pool, workspaceID, channelID, "quick-start-owner", ownerMemberID, now)
	mustExecChannelDiscovery(t, ctx, pool, `
UPDATE scope_channel_profiles
SET subsystem = 'tutorial', visibility = 'private'
WHERE scope_id = $1
`, channelID)
	mustExecChannelDiscovery(t, ctx, pool, `
INSERT INTO desktop_onboarding_states (
    user_id, workspace_id, organization_id, owner_member_id,
    tutorial_channel_id, flow_version, status, current_step, progress_json,
    created_at, updated_at
) VALUES ($1, $2, $3, $4, $5, 'v1', 'active', 'create_agent', JSON_OBJECT(), $6, $6)
`, ownerUserID, workspaceID, workspaceID+"_org", ownerMemberID, channelID, now)

	store := New(pool, Options{RequireWorkspaceAccess: func(ctx context.Context, userID string, workspaceID string) (string, error) {
		return channelDiscoveryRequireWorkspaceAccess(ctx, pool, userID, workspaceID)
	}})
	resolution, err := store.ResolveChannelAccessForUser(ctx, ownerUserID, workspaceID, channelID)
	require.NoError(t, err)
	require.Equal(t, ChannelAccessStatusJoined, resolution.Status)
	require.Equal(t, "tutorial", resolution.Channel.Subsystem)
	require.True(t, resolution.Channel.Tutorial)

	mustExecChannelDiscovery(t, ctx, pool, `
UPDATE desktop_onboarding_states
SET status = 'completed', current_step = 'done', completed_at = $3, updated_at = $3
WHERE user_id = $1 AND workspace_id = $2
`, ownerUserID, workspaceID, now.Add(time.Minute))
	resolution, err = store.ResolveChannelAccessForUser(ctx, ownerUserID, workspaceID, channelID)
	require.NoError(t, err)
	require.Equal(t, ChannelAccessStatusJoined, resolution.Status)
	require.Equal(t, "im", resolution.Channel.Subsystem)
	require.True(t, resolution.Channel.Tutorial)
}
