import { describe, expect, it, vi } from 'vitest';
import { GraphQLError } from 'graphql';
import { AdminContextProvider } from '../providers/admin-context.provider.js';
function createProvider(options) {
    const query = vi.fn().mockImplementation((_statement, values) => {
        if (options.rowsByOwnerId) {
            const serializedValues = JSON.stringify(values ?? []);
            for (const [ownerId, row] of Object.entries(options.rowsByOwnerId)) {
                if (serializedValues.includes(ownerId)) {
                    return Promise.resolve({ rows: [row], rowCount: 1 });
                }
            }
            return Promise.resolve({ rows: [], rowCount: 0 });
        }
        return Promise.resolve({
            rows: options.row ? [options.row] : [],
            rowCount: options.row ? 1 : 0,
        });
    });
    const db = {
        query,
    };
    const auth = {
        getAuthContext: vi.fn().mockResolvedValue(options.businessId
            ? {
                authType: 'jwt',
                tenant: { businessId: options.businessId },
                ...(options.activeReadScopeBusinessIds
                    ? {
                        activeReadScope: {
                            businessIds: options.activeReadScopeBusinessIds,
                        },
                    }
                    : {}),
            }
            : null),
    };
    return {
        provider: new AdminContextProvider(auth, db),
        query,
        auth,
    };
}
describe('AdminContext DI Integration', () => {
    it('loads admin context through provider injection', async () => {
        const { provider, query, auth } = createProvider({
            businessId: 'owner-a',
            row: {
                owner_id: 'owner-a',
                default_local_currency: 'USD',
                default_fiat_currency_for_crypto_conversions: 'USD',
                date_established: null,
                initial_accounter_year: null,
            },
        });
        const context = await provider.getVerifiedAdminContext();
        expect(context.ownerId).toBe('owner-a');
        expect(context.defaultLocalCurrency).toBe('USD');
        expect(auth.getAuthContext).toHaveBeenCalledTimes(1);
        expect(query).toHaveBeenCalledTimes(1);
    });
    it('uses single-business active scope as owner selection', async () => {
        const primaryOwnerId = 'owner-primary';
        const scopedOwnerId = 'owner-scoped';
        const { provider } = createProvider({
            businessId: primaryOwnerId,
            activeReadScopeBusinessIds: [scopedOwnerId],
            rowsByOwnerId: {
                [scopedOwnerId]: {
                    owner_id: scopedOwnerId,
                    default_local_currency: 'USD',
                    default_fiat_currency_for_crypto_conversions: 'USD',
                    date_established: null,
                    initial_accounter_year: null,
                },
            },
        });
        const context = await provider.getVerifiedAdminContext();
        expect(context.ownerId).toBe(scopedOwnerId);
    });
    it('prefers primary tenant business when it is inside multi-business scope', async () => {
        const primaryOwnerId = 'owner-primary';
        const { provider } = createProvider({
            businessId: primaryOwnerId,
            activeReadScopeBusinessIds: ['owner-scoped-a', primaryOwnerId, 'owner-scoped-b'],
            rowsByOwnerId: {
                [primaryOwnerId]: {
                    owner_id: primaryOwnerId,
                    default_local_currency: 'USD',
                    default_fiat_currency_for_crypto_conversions: 'USD',
                    date_established: null,
                    initial_accounter_year: null,
                },
            },
        });
        const context = await provider.getVerifiedAdminContext();
        expect(context.ownerId).toBe(primaryOwnerId);
    });
    it('falls back to first scoped business when primary tenant business is outside scope', async () => {
        const primaryOwnerId = 'owner-primary';
        const firstScopedOwnerId = 'owner-scoped-a';
        const { provider } = createProvider({
            businessId: primaryOwnerId,
            activeReadScopeBusinessIds: [firstScopedOwnerId, 'owner-scoped-b'],
            rowsByOwnerId: {
                [firstScopedOwnerId]: {
                    owner_id: firstScopedOwnerId,
                    default_local_currency: 'USD',
                    default_fiat_currency_for_crypto_conversions: 'USD',
                    date_established: null,
                    initial_accounter_year: null,
                },
            },
        });
        const context = await provider.getVerifiedAdminContext();
        expect(context.ownerId).toBe(firstScopedOwnerId);
    });
    it('isolates admin context between concurrent requests', async () => {
        const requestA = createProvider({
            businessId: 'owner-a',
            row: {
                owner_id: 'owner-a',
                default_local_currency: 'USD',
                default_fiat_currency_for_crypto_conversions: 'USD',
                date_established: null,
                initial_accounter_year: null,
            },
        });
        const requestB = createProvider({
            businessId: 'owner-b',
            row: {
                owner_id: 'owner-b',
                default_local_currency: 'EUR',
                default_fiat_currency_for_crypto_conversions: 'EUR',
                date_established: null,
                initial_accounter_year: null,
            },
        });
        const [contextA, contextB] = await Promise.all([
            requestA.provider.getVerifiedAdminContext(),
            requestB.provider.getVerifiedAdminContext(),
        ]);
        expect(contextA.ownerId).toBe('owner-a');
        expect(contextB.ownerId).toBe('owner-b');
        expect(requestA.query).toHaveBeenCalledTimes(1);
        expect(requestB.query).toHaveBeenCalledTimes(1);
    });
    it('caches admin context within a single request', async () => {
        const { provider, query } = createProvider({
            businessId: 'owner-a',
            row: {
                owner_id: 'owner-a',
                default_local_currency: 'USD',
                default_fiat_currency_for_crypto_conversions: 'USD',
                date_established: null,
                initial_accounter_year: null,
            },
        });
        const [first, second] = await Promise.all([
            provider.getVerifiedAdminContext(),
            provider.getVerifiedAdminContext(),
        ]);
        expect(first.ownerId).toBe('owner-a');
        expect(second.ownerId).toBe('owner-a');
        expect(query).toHaveBeenCalledTimes(1);
    });
    it('fails closed when auth context is unavailable (RLS guard path)', async () => {
        const { provider, query } = createProvider({
            businessId: null,
        });
        await expect(provider.getAdminContext()).rejects.toBeInstanceOf(GraphQLError);
        await expect(provider.getAdminContext()).rejects.toMatchObject({
            extensions: { code: 'UNAUTHENTICATED' },
        });
        expect(query).not.toHaveBeenCalled();
    });
});
//# sourceMappingURL=admin-context-integration.test.js.map