import { describe, expect, it, vi } from 'vitest';
import { buildSearchEnginePings, buildSitemapUrl, notifySitemapOnPublish, } from '../../seo/sitemap-notify.js';
import { DEFAULT_SEO_MODULE_SETTINGS } from '../../seo/config-store.js';
const baseSettings = {
    sitemapEnabled: DEFAULT_SEO_MODULE_SETTINGS.sitemapEnabled,
    autoRegenerateSitemapOnPublish: DEFAULT_SEO_MODULE_SETTINGS.autoRegenerateSitemapOnPublish,
    pingSearchEnginesOnPublish: DEFAULT_SEO_MODULE_SETTINGS.pingSearchEnginesOnPublish,
};
function okFetch() {
    return vi.fn(async () => new Response('', { status: 200 }));
}
describe('buildSitemapUrl', () => {
    it('derives /sitemap.xml from the site origin', () => {
        expect(buildSitemapUrl('https://example.com')).toBe('https://example.com/sitemap.xml');
        expect(buildSitemapUrl('https://example.com/blog/')).toBe('https://example.com/sitemap.xml');
    });
    it('returns null for empty or non-http(s) URLs', () => {
        expect(buildSitemapUrl('')).toBeNull();
        expect(buildSitemapUrl(null)).toBeNull();
        expect(buildSitemapUrl('not a url')).toBeNull();
        expect(buildSitemapUrl('ftp://example.com')).toBeNull();
    });
});
describe('buildSearchEnginePings', () => {
    it('encodes the sitemap URL into google + bing targets', () => {
        const pings = buildSearchEnginePings('https://example.com/sitemap.xml');
        expect(pings.map((p) => p.name)).toEqual(['google', 'bing']);
        for (const p of pings) {
            expect(p.url).toContain(encodeURIComponent('https://example.com/sitemap.xml'));
        }
    });
});
describe('notifySitemapOnPublish', () => {
    it('does nothing when the sitemap is disabled', async () => {
        const fetchImpl = okFetch();
        const res = await notifySitemapOnPublish({
            settings: { ...baseSettings, sitemapEnabled: false },
            siteUrl: 'https://example.com',
            fetchImpl,
            allowNonProduction: true,
        });
        expect(res.invalidateCache).toBe(false);
        expect(res.regenerated).toBe(false);
        expect(res.pinged).toEqual([]);
        expect(fetchImpl).not.toHaveBeenCalled();
        expect(res.skipped).toContainEqual({ target: 'sitemap', reason: 'sitemap-disabled' });
    });
    it('does not invalidate or write when auto-regenerate is off', async () => {
        const fetchImpl = okFetch();
        const res = await notifySitemapOnPublish({
            settings: { ...baseSettings, autoRegenerateSitemapOnPublish: false },
            siteUrl: 'https://example.com',
            fetchImpl,
            allowNonProduction: true,
        });
        expect(res.invalidateCache).toBe(false);
        expect(res.regenerated).toBe(false);
        expect(fetchImpl).not.toHaveBeenCalled();
        expect(res.skipped).toContainEqual({ target: 'sitemap', reason: 'auto-regenerate-disabled' });
    });
    it('regenerates but does not ping when auto-regenerate on, ping off', async () => {
        const fetchImpl = okFetch();
        const res = await notifySitemapOnPublish({
            settings: { ...baseSettings, pingSearchEnginesOnPublish: false },
            siteUrl: 'https://example.com',
            fetchImpl,
            allowNonProduction: true,
        });
        expect(res.invalidateCache).toBe(true);
        expect(res.regenerated).toBe(true);
        expect(fetchImpl).not.toHaveBeenCalled();
        expect(res.skipped).toContainEqual({ target: 'ping', reason: 'ping-disabled' });
    });
    it('debounces the write + ping but still invalidates cache within the window', async () => {
        const fetchImpl = okFetch();
        const res = await notifySitemapOnPublish({
            settings: baseSettings,
            siteUrl: 'https://example.com',
            environment: 'production',
            lastGeneratedAt: new Date(Date.now() - 5_000).toISOString(),
            debounceMs: 60_000,
            fetchImpl,
        });
        // Cache still drops (cheap, correctness), but no write + no ping.
        expect(res.invalidateCache).toBe(true);
        expect(res.regenerated).toBe(false);
        expect(fetchImpl).not.toHaveBeenCalled();
        expect(res.skipped).toContainEqual({ target: 'sitemap', reason: 'debounced' });
    });
    it('regenerates once the debounce window has elapsed', async () => {
        const fetchImpl = okFetch();
        const res = await notifySitemapOnPublish({
            settings: baseSettings,
            siteUrl: 'https://example.com',
            environment: 'production',
            lastGeneratedAt: new Date(Date.now() - 120_000).toISOString(),
            debounceMs: 60_000,
            fetchImpl,
        });
        expect(res.invalidateCache).toBe(true);
        expect(res.regenerated).toBe(true);
        expect(res.pinged.sort()).toEqual(['bing', 'google']);
    });
    it('skips pinging outside production unless explicitly allowed', async () => {
        const fetchImpl = okFetch();
        const res = await notifySitemapOnPublish({
            settings: baseSettings,
            siteUrl: 'https://example.com',
            environment: 'preview',
            fetchImpl,
        });
        expect(res.regenerated).toBe(true);
        expect(fetchImpl).not.toHaveBeenCalled();
        expect(res.skipped).toContainEqual({ target: 'ping', reason: 'non-production:preview' });
    });
    it('pings google + bing in production with a valid https site URL', async () => {
        const fetchImpl = okFetch();
        const res = await notifySitemapOnPublish({
            settings: baseSettings,
            siteUrl: 'https://example.com',
            environment: 'production',
            fetchImpl,
        });
        expect(res.regenerated).toBe(true);
        expect(res.sitemapUrl).toBe('https://example.com/sitemap.xml');
        expect(res.pinged.sort()).toEqual(['bing', 'google']);
        expect(fetchImpl).toHaveBeenCalledTimes(2);
    });
    it('refuses to ping when the site URL is missing', async () => {
        const fetchImpl = okFetch();
        const res = await notifySitemapOnPublish({
            settings: baseSettings,
            siteUrl: null,
            environment: 'production',
            fetchImpl,
        });
        expect(res.regenerated).toBe(true);
        expect(fetchImpl).not.toHaveBeenCalled();
        expect(res.skipped).toContainEqual({ target: 'ping', reason: 'missing-or-invalid-site-url' });
    });
    it('refuses to ping when the production site URL is http (not https)', async () => {
        const fetchImpl = okFetch();
        const res = await notifySitemapOnPublish({
            settings: baseSettings,
            siteUrl: 'http://example.com',
            environment: 'production',
            fetchImpl,
        });
        expect(fetchImpl).not.toHaveBeenCalled();
        expect(res.skipped).toContainEqual({ target: 'ping', reason: 'non-https-site-url' });
    });
    it('refuses to ping when the site URL resolves to a private/internal host', async () => {
        const fetchImpl = okFetch();
        const res = await notifySitemapOnPublish({
            settings: baseSettings,
            siteUrl: 'http://127.0.0.1',
            environment: 'production',
            fetchImpl,
            allowNonProduction: true,
        });
        expect(fetchImpl).not.toHaveBeenCalled();
        expect(res.skipped.some((s) => s.target === 'ping' && s.reason.startsWith('unsafe-site-url'))).toBe(true);
    });
    it('records non-2xx ping responses as skipped, not pinged', async () => {
        const fetchImpl = vi.fn(async (url) => url.includes('google')
            ? new Response('', { status: 404 })
            : new Response('', { status: 200 }));
        const res = await notifySitemapOnPublish({
            settings: baseSettings,
            siteUrl: 'https://example.com',
            environment: 'production',
            fetchImpl,
        });
        expect(res.pinged).toEqual(['bing']);
        expect(res.skipped).toContainEqual({ target: 'google', reason: 'http-404' });
    });
    it('never throws when fetch rejects', async () => {
        const fetchImpl = vi.fn(async () => {
            throw new Error('network down');
        });
        const res = await notifySitemapOnPublish({
            settings: baseSettings,
            siteUrl: 'https://example.com',
            environment: 'production',
            fetchImpl,
        });
        expect(res.pinged).toEqual([]);
        expect(res.skipped.some((s) => s.reason.startsWith('fetch-error'))).toBe(true);
    });
});
//# sourceMappingURL=sitemap-notify.test.js.map