package repository

import (
	"baron-sso-backend/internal/domain"
	"context"
	"testing"
	"time"

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

func TestWorksmobileOutboxRepositoryDeletePendingByTenantRoot(t *testing.T) {
	repo := NewWorksmobileOutboxRepository(testDB)
	ctx := context.Background()

	require.NoError(t, testDB.Exec("DELETE FROM worksmobile_outboxes").Error)

	rows := []domain.WorksmobileOutbox{
		{
			ID:           "00000000-0000-0000-0000-000000000101",
			ResourceType: domain.WorksmobileResourceUser,
			ResourceID:   "user-pending",
			Action:       domain.WorksmobileActionUpsert,
			Status:       domain.WorksmobileOutboxStatusPending,
			DedupeKey:    "pending-root",
			Payload:      domain.JSONMap{"tenantRootId": "root-1"},
		},
		{
			ID:           "00000000-0000-0000-0000-000000000102",
			ResourceType: domain.WorksmobileResourceUser,
			ResourceID:   "user-other-root",
			Action:       domain.WorksmobileActionUpsert,
			Status:       domain.WorksmobileOutboxStatusPending,
			DedupeKey:    "pending-other-root",
			Payload:      domain.JSONMap{"tenantRootId": "root-2"},
		},
		{
			ID:           "00000000-0000-0000-0000-000000000103",
			ResourceType: domain.WorksmobileResourceUser,
			ResourceID:   "user-failed",
			Action:       domain.WorksmobileActionUpsert,
			Status:       domain.WorksmobileOutboxStatusFailed,
			DedupeKey:    "failed-root",
			Payload:      domain.JSONMap{"tenantRootId": "root-1"},
		},
		{
			ID:           "00000000-0000-0000-0000-000000000104",
			ResourceType: domain.WorksmobileResourceOrgUnit,
			ResourceID:   "org-processed",
			Action:       domain.WorksmobileActionUpsert,
			Status:       domain.WorksmobileOutboxStatusProcessed,
			DedupeKey:    "processed-root",
			Payload:      domain.JSONMap{"tenantRootId": "root-1"},
		},
	}
	for i := range rows {
		require.NoError(t, repo.Create(ctx, &rows[i]))
	}

	deleted, err := repo.DeletePendingByTenantRoot(ctx, "root-1")

	require.NoError(t, err)
	require.Equal(t, int64(1), deleted)
	var remaining []domain.WorksmobileOutbox
	require.NoError(t, testDB.Order("id asc").Find(&remaining).Error)
	require.Len(t, remaining, 3)
	require.Equal(t, "00000000-0000-0000-0000-000000000102", remaining[0].ID)
	require.Equal(t, "00000000-0000-0000-0000-000000000103", remaining[1].ID)
	require.Equal(t, "00000000-0000-0000-0000-000000000104", remaining[2].ID)
}

func TestWorksmobileOutboxRepositoryListReadyWaitsForPendingOrgUnitParent(t *testing.T) {
	repo := NewWorksmobileOutboxRepository(testDB)
	ctx := context.Background()

	require.NoError(t, testDB.Exec("DELETE FROM worksmobile_outboxes").Error)

	baseTime := time.Date(2026, 6, 2, 15, 21, 0, 0, time.UTC)
	child := domain.WorksmobileOutbox{
		ID:           "00000000-0000-0000-0000-000000000201",
		ResourceType: domain.WorksmobileResourceOrgUnit,
		ResourceID:   "child-tenant",
		Action:       domain.WorksmobileActionUpsert,
		Status:       domain.WorksmobileOutboxStatusPending,
		DedupeKey:    "orgunit:upsert:child-tenant",
		Payload: domain.JSONMap{
			"request": map[string]any{
				"orgUnitExternalKey": "child-tenant",
				"parentOrgUnitId":    "externalKey:parent-tenant",
			},
		},
		CreatedAt: baseTime,
		UpdatedAt: baseTime,
	}
	parent := domain.WorksmobileOutbox{
		ID:           "00000000-0000-0000-0000-000000000202",
		ResourceType: domain.WorksmobileResourceOrgUnit,
		ResourceID:   "parent-tenant",
		Action:       domain.WorksmobileActionUpsert,
		Status:       domain.WorksmobileOutboxStatusPending,
		DedupeKey:    "orgunit:upsert:parent-tenant",
		Payload: domain.JSONMap{
			"request": map[string]any{
				"orgUnitExternalKey": "parent-tenant",
			},
		},
		CreatedAt: baseTime.Add(time.Second),
		UpdatedAt: baseTime.Add(time.Second),
	}
	require.NoError(t, testDB.Create(&child).Error)
	require.NoError(t, testDB.Create(&parent).Error)

	rows, err := repo.ListReady(ctx, 10)

	require.NoError(t, err)
	require.Len(t, rows, 1)
	require.Equal(t, "parent-tenant", rows[0].ResourceID)

	require.NoError(t, repo.MarkProcessed(ctx, parent.ID))
	rows, err = repo.ListReady(ctx, 10)

	require.NoError(t, err)
	require.Len(t, rows, 1)
	require.Equal(t, "child-tenant", rows[0].ResourceID)
}
