import { describe, expect, it } from 'vitest';
import { buildRecommendations, listTeamMembers, getUserStats, workspaceDomainFromUrl, } from '../../auth/team.js';
const DAY = 24 * 60 * 60 * 1000;
function member(over) {
    return {
        id: 'm1',
        name: 'Test User',
        email: 'test@actuatemedia.com',
        initials: 'TU',
        role: 'EDITOR',
        roleName: 'Editor',
        status: 'active',
        mfaEnabled: true,
        mfaRequired: false,
        externalDomain: false,
        authProvider: null,
        lastLoginAt: new Date().toISOString(),
        lastActiveAt: new Date().toISOString(),
        acceptedInviteAt: new Date(Date.now() - 30 * DAY).toISOString(),
        createdAt: new Date(Date.now() - 60 * DAY).toISOString(),
        isCurrentUser: false,
        ...over,
    };
}
describe('buildRecommendations', () => {
    it('flags an Owner without MFA as critical', () => {
        const recs = buildRecommendations([member({ id: 'o1', roleName: 'Owner', role: 'OWNER', mfaEnabled: false })], [], new Set());
        expect(recs[0].type).toBe('owner_without_mfa');
        expect(recs[0].severity).toBe('critical');
    });
    it('flags an Admin without MFA as high', () => {
        const recs = buildRecommendations([member({ id: 'a1', roleName: 'Admin', role: 'ADMIN', mfaEnabled: false })], [], new Set());
        expect(recs[0].type).toBe('admin_without_mfa');
        expect(recs[0].severity).toBe('high');
    });
    it('combines inactive + external into one high recommendation', () => {
        const recs = buildRecommendations([
            member({
                id: 'x1',
                roleName: 'Viewer',
                role: 'VIEWER',
                externalDomain: true,
                lastLoginAt: new Date(Date.now() - 94 * DAY).toISOString(),
            }),
        ], [], new Set());
        expect(recs[0].type).toBe('inactive_user');
        expect(recs[0].severity).toBe('high');
        expect(recs[0].description).toContain('94 days');
        expect(recs[0].description).toContain('external');
    });
    it('flags stale pending invites and sorts highest severity first', () => {
        const recs = buildRecommendations([member({ id: 'a1', roleName: 'Admin', role: 'ADMIN', mfaEnabled: false })], [
            {
                id: 'inv1',
                email: 'old@x.com',
                createdAt: new Date(Date.now() - 10 * DAY).toISOString(),
            },
        ], new Set());
        expect(recs).toHaveLength(2);
        expect(recs[0].severity).toBe('high'); // admin_without_mfa before stale_invite (medium)
        expect(recs.some((r) => r.type === 'stale_invite')).toBe(true);
    });
    it('filters out dismissed recommendations', () => {
        const recs = buildRecommendations([member({ id: 'o1', roleName: 'Owner', role: 'OWNER', mfaEnabled: false })], [], new Set(['owner_without_mfa:o1']));
        expect(recs).toHaveLength(0);
    });
    it('does not flag a healthy active member', () => {
        const recs = buildRecommendations([member({})], [], new Set());
        expect(recs).toHaveLength(0);
    });
});
describe('listTeamMembers + getUserStats', () => {
    function db(users, invites) {
        return {
            user: { findMany: async () => users },
            invite: {
                findMany: async ({ where } = {}) => invites.filter((i) => !where?.status || i.status === where.status),
                count: async ({ where } = {}) => invites.filter((i) => !where?.status || i.status === where.status).length,
            },
        };
    }
    const baseUser = (over) => ({
        id: 'u',
        name: 'U',
        email: 'u@actuatemedia.com',
        role: 'EDITOR',
        isActive: true,
        totpEnabled: true,
        createdAt: new Date(),
        ...over,
    });
    it('excludes users that still have a pending invite', async () => {
        const d = db([
            baseUser({ id: 'u1', email: 'a@actuatemedia.com' }),
            baseUser({ id: 'u2', email: 'pending@actuatemedia.com' }),
        ], [{ id: 'i1', email: 'pending@actuatemedia.com', status: 'PENDING' }]);
        const members = await listTeamMembers(d, {}, { workspaceDomain: 'actuatemedia.com' });
        expect(members.map((m) => m.email)).toEqual(['a@actuatemedia.com']);
    });
    it('marks external-domain members', async () => {
        const d = db([baseUser({ id: 'u1', email: 'free@elsewhere.io' })], []);
        const members = await listTeamMembers(d, {}, { workspaceDomain: 'actuatemedia.com' });
        expect(members[0].externalDomain).toBe(true);
    });
    it('counts members, admins, pending invites and seats', async () => {
        const d = db([
            baseUser({ id: 'u1', role: 'OWNER', email: 'owner@actuatemedia.com' }),
            baseUser({ id: 'u2', role: 'ADMIN', email: 'admin@actuatemedia.com' }),
            baseUser({ id: 'u3', role: 'EDITOR', email: 'ed@actuatemedia.com' }),
            baseUser({
                id: 'u4',
                role: 'EDITOR',
                email: 'sus@actuatemedia.com',
                suspendedAt: new Date(),
            }),
        ], [{ id: 'i1', email: 'p@actuatemedia.com', status: 'PENDING' }]);
        const stats = await getUserStats(d, { seatLimit: 10 });
        expect(stats.members).toBe(3); // suspended excluded
        expect(stats.admins).toBe(2); // owner + admin
        expect(stats.pendingInvites).toBe(1);
        expect(stats.seatsUsed).toBe(4); // 3 active + 1 pending
        expect(stats.seatsAvailable).toBe(6);
    });
    it('reports unlimited seats when no limit is set', async () => {
        const d = db([baseUser({ id: 'u1' })], []);
        const stats = await getUserStats(d, {});
        expect(stats.seatLimit).toBeNull();
        expect(stats.seatsAvailable).toBeNull();
    });
});
describe('workspaceDomainFromUrl', () => {
    it('strips protocol and www', () => {
        expect(workspaceDomainFromUrl('https://www.actuatemedia.com')).toBe('actuatemedia.com');
        expect(workspaceDomainFromUrl('https://app.actuatemedia.com/admin')).toBe('app.actuatemedia.com');
        expect(workspaceDomainFromUrl(null)).toBeNull();
        expect(workspaceDomainFromUrl('not a url')).toBeNull();
    });
});
//# sourceMappingURL=team.test.js.map