/**
 * Tests for components/subscription-manager.js — renderSubscriptionCard.
 *
 * The card is built by template-string interpolation, so the assertions
 * focus on data correctness (escaping, branching) rather than CSS class
 * spelling. Covers active vs paused, optional folder/notes, and the
 * data-subscription-id round-trip used by the action buttons.
 *
 * Kept in its own file (instead of extending subscription-manager.test.js)
 * so it can land alongside / independently of PR #4297 without merge
 * conflicts on a freshly-created test file.
 */

// Load xss-protection.js first so window.escapeHtml is defined: the card
// renderer escapes user fields via the global helper (the class no longer
// ships its own escapeHtml). In production, base.html loads xss-protection.js
// before subscription-manager.js with matching `defer` ordering.
import '@js/security/xss-protection.js';
import '@js/components/subscription-manager.js';

let manager;

beforeAll(() => {
    // The module wires up its singleton inside a DOMContentLoaded listener;
    // dispatch it manually if happy-dom already fired before the dynamic
    // import settled.
    if (!window.subscriptionManager) {
        document.dispatchEvent(new Event('DOMContentLoaded'));
    }
    manager = window.subscriptionManager;
});

function makeSubscription(overrides = {}) {
    // A baseline subscription that exercises the always-present fields.
    // Use a far-future next_refresh so the computed timeUntil is stable
    // (e.g. "365d" rather than something time-sensitive).
    const oneYearMs = 365 * 24 * 60 * 60 * 1000;
    return {
        id: 'sub-abc-123',
        query_or_topic: 'AI safety',
        refresh_interval_minutes: 60,
        next_refresh: new Date(Date.now() + oneYearMs).toISOString(),
        status: 'active',
        ...overrides,
    };
}

describe('subscriptionManager.renderSubscriptionCard', () => {
    it('includes core fields (id, query, interval) in the output', () => {
        const html = manager.renderSubscriptionCard(makeSubscription());
        expect(html).toContain('data-subscription-id="sub-abc-123"');
        expect(html).toContain('AI safety');
        expect(html).toContain('Every 60 min');
    });

    it('shows a Pause button + pause icon when status is active', () => {
        const html = manager.renderSubscriptionCard(
            makeSubscription({ status: 'active' })
        );
        expect(html).toContain('title="Pause"');
        expect(html).toContain('bi-pause');
        expect(html).not.toContain('title="Resume"');
        expect(html).not.toContain('bi-play');
    });

    it('shows a Resume button + play icon when status is not active (paused)', () => {
        const html = manager.renderSubscriptionCard(
            makeSubscription({ status: 'paused' })
        );
        expect(html).toContain('title="Resume"');
        expect(html).toContain('bi-play');
        expect(html).not.toContain('title="Pause"');
    });

    it('omits the folder span when subscription has no folder', () => {
        const html = manager.renderSubscriptionCard(
            makeSubscription({ folder: undefined })
        );
        expect(html).not.toContain('bi-folder');
    });

    it('renders the folder span when a folder is set', () => {
        const html = manager.renderSubscriptionCard(
            makeSubscription({ folder: 'Research' })
        );
        expect(html).toContain('bi-folder');
        expect(html).toContain('Research');
    });

    it('omits the notes paragraph when no notes are provided', () => {
        const html = manager.renderSubscriptionCard(
            makeSubscription({ notes: undefined })
        );
        // The notes branch is the only <p> in the card template.
        expect(html).not.toContain('<p ');
    });

    it('renders notes when provided', () => {
        const html = manager.renderSubscriptionCard(
            makeSubscription({ notes: 'Important topic' })
        );
        expect(html).toContain('Important topic');
        expect(html).toContain('<p ');
    });

    it('escapes HTML in user-supplied fields (XSS protection)', () => {
        const html = manager.renderSubscriptionCard(
            makeSubscription({
                query_or_topic: '<script>alert(1)</script>',
                folder: '<img src=x>',
                notes: '<svg onload=alert(1)>',
            })
        );
        // Local escapeHtml uses div+textContent+innerHTML, which escapes
        // `<` to `&lt;`. The literal `<script>` substring must not appear.
        expect(html).not.toContain('<script>');
        expect(html).not.toContain('<img src=x>');
        expect(html).not.toContain('<svg onload=alert(1)>');
        // The escaped form should be present.
        expect(html).toContain('&lt;script&gt;');
    });

    it('embeds the formatTimeUntil output near "Next:"', () => {
        // Sanity check that the formatTimeUntil method is being called and
        // its output is interpolated into the card. The exact number depends
        // on system time, so just assert that a unit suffix follows "Next:".
        const html = manager.renderSubscriptionCard(makeSubscription());
        expect(html).toMatch(/Next:\s*\d+[mhd]/);
    });
});
