import { describe, expect, it, vi } from 'vitest';
import { GraphQLError } from 'graphql';
import { emailIngestionControlResolver } from '../resolvers/email-ingestion-control.resolver.js';
import { EmailIngestionControlProvider } from '../providers/email-ingestion-control.provider.js';
// ---------------------------------------------------------------------------
// Mock helpers
// ---------------------------------------------------------------------------
const GRANT_TTL_MS = 5 * 60 * 1000; // 5 minutes
const baseInput = {
    recipientAlias: 'invoice@tenant.example.com',
    messageId: 'msg-abc-123',
    rawMessageHash: 'sha256-abc',
    receivedAt: new Date().toISOString(),
    correlationId: 'corr-xyz-001',
};
const mockGrant = {
    jti: 'jti-uuid',
    tenantId: 'tenant-uuid-1',
    messageId: 'msg-abc-123',
    rawMessageHash: 'sha256-abc',
    action: 'ingest',
    expiresAt: new Date(Date.now() + GRANT_TTL_MS),
    decisionId: 'decision-uuid',
    auditId: 'audit-uuid',
};
function makeInjector(overrides = {}) {
    const controlProvider = {
        resolveAlias: vi.fn().mockResolvedValue({ found: true, tenantId: 'tenant-uuid-1' }),
        recognizeBusiness: vi.fn().mockResolvedValue({ businessId: null, config: {} }),
        issueGrant: vi.fn().mockResolvedValue(mockGrant),
        ...overrides,
    };
    return {
        get: (token) => {
            if (token === EmailIngestionControlProvider)
                return controlProvider;
            throw new Error(`Unexpected provider: ${String(token)}`);
        },
    };
}
// ---------------------------------------------------------------------------
// Mutation.requestIngestControl resolver
// ---------------------------------------------------------------------------
describe('Mutation.requestIngestControl', () => {
    const resolver = emailIngestionControlResolver.Mutation.requestIngestControl;
    it('resolves alias and returns IngestControlDecision on success', async () => {
        const injector = makeInjector();
        const result = await resolver({}, { input: baseInput }, { injector }, {});
        expect(result).toMatchObject({
            tenantId: 'tenant-uuid-1',
            decisionId: 'decision-uuid',
            auditId: 'audit-uuid',
            grant: expect.objectContaining({
                jti: 'jti-uuid',
                tenantId: 'tenant-uuid-1',
                action: 'ingest',
            }),
        });
    });
    it('calls resolveAlias with the recipientAlias from input', async () => {
        const resolveAlias = vi.fn().mockResolvedValue({ found: true, tenantId: 'tenant-uuid-1' });
        const injector = makeInjector({ resolveAlias, issueGrant: vi.fn().mockResolvedValue(mockGrant) });
        await resolver({}, { input: { ...baseInput, recipientAlias: 'test@example.com' } }, { injector }, {});
        expect(resolveAlias).toHaveBeenCalledWith('test@example.com');
    });
    it('returns CommonError when alias is unknown', async () => {
        const injector = makeInjector({
            resolveAlias: vi.fn().mockResolvedValue({ found: false, reason: 'UNKNOWN_ALIAS' }),
        });
        const result = await resolver({}, { input: baseInput }, { injector }, {});
        expect(result).toMatchObject({
            __typename: 'CommonError',
            message: expect.stringContaining('UNKNOWN_ALIAS'),
        });
    });
    it('does not call issueGrant when alias resolution fails', async () => {
        const issueGrant = vi.fn();
        const injector = makeInjector({
            resolveAlias: vi.fn().mockResolvedValue({ found: false, reason: 'UNKNOWN_ALIAS' }),
            issueGrant,
        });
        await resolver({}, { input: baseInput }, { injector }, {});
        expect(issueGrant).not.toHaveBeenCalled();
    });
    it('throws GraphQLError on unexpected provider failure', async () => {
        const injector = makeInjector({
            resolveAlias: vi.fn().mockRejectedValue(new Error('DB down')),
        });
        await expect(resolver({}, { input: baseInput }, { injector }, {})).rejects.toThrow(GraphQLError);
    });
    it('passes correlationId and messageId to issueGrant', async () => {
        const issueGrant = vi.fn().mockResolvedValue(mockGrant);
        const injector = makeInjector({ issueGrant });
        await resolver({}, { input: { ...baseInput, correlationId: 'corr-999' } }, { injector }, {});
        const callArg = issueGrant.mock.calls[0][0];
        expect(callArg.correlationId).toBe('corr-999');
        expect(callArg.messageId).toBe(baseInput.messageId);
    });
    it('selects the issuer from senderEvidence and returns the business config', async () => {
        const recognizeBusiness = vi.fn().mockResolvedValue({
            businessId: 'biz-1',
            config: {
                emailBody: true,
                attachments: ['PDF'],
                internalEmailLinks: ['https://acme.com/inv'],
            },
        });
        const injector = makeInjector({ recognizeBusiness });
        const result = await resolver({}, { input: { ...baseInput, senderEvidence: { from: 'vendor@acme.com' } } }, { injector }, {});
        expect(recognizeBusiness).toHaveBeenCalledWith('tenant-uuid-1', 'vendor@acme.com');
        expect(result).toMatchObject({
            businessEmailConfig: {
                businessId: 'biz-1',
                emailBody: true,
                attachments: ['PDF'],
                internalEmailLinks: ['https://acme.com/inv'],
            },
        });
    });
    it('returns null businessEmailConfig when no business is recognized', async () => {
        const injector = makeInjector();
        const result = await resolver({}, { input: baseInput }, { injector }, {});
        expect(result.businessEmailConfig).toBeNull();
    });
    it('binds the recognized businessId into the issued grant', async () => {
        const issueGrant = vi.fn().mockResolvedValue(mockGrant);
        const recognizeBusiness = vi.fn().mockResolvedValue({ businessId: 'biz-7', config: {} });
        const injector = makeInjector({ issueGrant, recognizeBusiness });
        await resolver({}, { input: { ...baseInput, senderEvidence: { from: 'vendor@acme.com' } } }, { injector }, {});
        expect(issueGrant.mock.calls[0][0].businessId).toBe('biz-7');
    });
});
//# sourceMappingURL=email-ingestion-control.resolver.test.js.map