import { jsx as _jsx } from "react/jsx-runtime";
// @vitest-environment happy-dom
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
/**
 * Redirects tab with the inline editor pane (design split-pane pattern —
 * previously the `RedirectEditorDrawer` overlay). Pins: row click toggles the
 * 420px pane, "New redirect" opens it in create mode, and save flows through
 * the same `createRedirectRule` / `updateRedirectRule` service calls.
 */
function makeRule(over = {}) {
    return {
        id: 'r1',
        type: 301,
        fromPath: '/old-path',
        toPath: '/new-path',
        enabled: true,
        priority: 0,
        preserveQuery: false,
        hits: 3,
        lastHitAt: null,
        stale: false,
        source: 'manual',
        notes: null,
        createdAt: '2026-06-01T00:00:00Z',
        updatedAt: '2026-06-01T00:00:00Z',
        ...over,
    };
}
const RULES = [makeRule(), makeRule({ id: 'r2', fromPath: '/other', toPath: '/elsewhere' })];
const fetchRedirectRules = vi.fn(async () => RULES);
const createRedirectRule = vi.fn(async (_p) => ({}));
const updateRedirectRule = vi.fn(async (_id, _p) => ({}));
const deleteRedirectRule = vi.fn(async (_id) => ({}));
vi.mock('../../lib/seo-service.js', () => ({
    fetchRedirectOverview: vi.fn(async () => ({
        activeRedirects: 2,
        staleRedirects: 0,
        notFoundCount: 0,
        chainsAndLoops: 0,
    })),
    fetchRedirectRules: () => fetchRedirectRules(),
    fetchRedirectChains: vi.fn(async () => []),
    fetchRedirectSuggestions: vi.fn(async () => []),
    createRedirectRule: (p) => createRedirectRule(p),
    updateRedirectRule: (id, p) => updateRedirectRule(id, p),
    deleteRedirectRule: (id) => deleteRedirectRule(id),
    flattenRedirectChain: vi.fn(async () => ({})),
    generate404RecoverySuggestions: vi.fn(async () => ({})),
    acceptRedirectSuggestion: vi.fn(async () => ({})),
    dismissRedirectSuggestion: vi.fn(async () => ({})),
    exportRedirectsCsv: vi.fn(async () => ({ csv: '' })),
    importRedirectsCsv: vi.fn(async () => ({ imported: 0 })),
    fetchRedirectRecoverySettings: vi.fn(async () => ({
        aiRerank: false,
        autoApply: false,
        autoApplyMinConfidence: 0.85,
    })),
    saveRedirectRecoverySettings: vi.fn(async () => ({})),
}));
vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn(), loading: vi.fn() } }));
const { RedirectsTab } = await import('../../views/seo/RedirectsTab.js');
beforeEach(() => {
    fetchRedirectRules.mockClear();
    createRedirectRule.mockClear();
    updateRedirectRule.mockClear();
    deleteRedirectRule.mockClear();
});
describe('Redirects inline editor pane', () => {
    it('opens the pane on row click with the rule loaded', async () => {
        render(_jsx(RedirectsTab, {}));
        const rowButton = await screen.findByRole('button', { name: '/old-path' });
        expect(rowButton.getAttribute('aria-expanded')).toBe('false');
        fireEvent.click(rowButton);
        expect(screen.getByRole('region', { name: 'Redirect editor' })).toBeTruthy();
        expect(rowButton.getAttribute('aria-expanded')).toBe('true');
        // The form is prefilled from the selected rule.
        expect(screen.getByLabelText('Source path')).toHaveProperty('value', '/old-path');
        expect(screen.getByLabelText('Destination')).toHaveProperty('value', '/new-path');
    });
    it('toggles the pane closed when the same row is clicked again', async () => {
        render(_jsx(RedirectsTab, {}));
        const rowButton = await screen.findByRole('button', { name: '/old-path' });
        fireEvent.click(rowButton);
        expect(screen.getByRole('region', { name: 'Redirect editor' })).toBeTruthy();
        fireEvent.click(rowButton);
        expect(screen.queryByRole('region', { name: 'Redirect editor' })).toBeNull();
    });
    it('collapses the pane via the close button', async () => {
        render(_jsx(RedirectsTab, {}));
        fireEvent.click(await screen.findByRole('button', { name: '/old-path' }));
        expect(screen.getByRole('region', { name: 'Redirect editor' })).toBeTruthy();
        fireEvent.click(screen.getByRole('button', { name: 'Close redirect editor' }));
        expect(screen.queryByRole('region', { name: 'Redirect editor' })).toBeNull();
    });
    it('saves an edited rule through updateRedirectRule and refetches', async () => {
        render(_jsx(RedirectsTab, {}));
        fireEvent.click(await screen.findByRole('button', { name: '/old-path' }));
        const before = fetchRedirectRules.mock.calls.length;
        fireEvent.change(screen.getByLabelText('Destination'), { target: { value: '/moved' } });
        fireEvent.click(screen.getByRole('button', { name: 'Save changes' }));
        await waitFor(() => expect(updateRedirectRule).toHaveBeenCalledWith('r1', expect.objectContaining({ fromPath: '/old-path', toPath: '/moved', type: 301 })));
        // Saving closes the pane and refetches the list.
        await waitFor(() => expect(screen.queryByRole('region', { name: 'Redirect editor' })).toBeNull());
        await waitFor(() => expect(fetchRedirectRules.mock.calls.length).toBeGreaterThan(before));
    });
    it('creates a rule from the New redirect pane', async () => {
        render(_jsx(RedirectsTab, {}));
        await screen.findByRole('button', { name: '/old-path' });
        fireEvent.click(screen.getByRole('button', { name: /New redirect/ }));
        expect(screen.getByRole('region', { name: 'Redirect editor' })).toBeTruthy();
        fireEvent.change(screen.getByLabelText('Source path'), { target: { value: 'legacy' } });
        fireEvent.change(screen.getByLabelText('Destination'), { target: { value: '/fresh' } });
        fireEvent.click(screen.getByRole('button', { name: 'Create redirect' }));
        // Paths are normalized to a leading slash before saving.
        await waitFor(() => expect(createRedirectRule).toHaveBeenCalledWith(expect.objectContaining({ fromPath: '/legacy', toPath: '/fresh', type: 301 })));
    });
    it('shows a validation error instead of saving when the source is missing', async () => {
        render(_jsx(RedirectsTab, {}));
        await screen.findByRole('button', { name: '/old-path' });
        fireEvent.click(screen.getByRole('button', { name: /New redirect/ }));
        fireEvent.click(screen.getByRole('button', { name: 'Create redirect' }));
        expect(await screen.findByRole('alert')).toBeTruthy();
        expect(createRedirectRule).not.toHaveBeenCalled();
    });
});
//# sourceMappingURL=redirects-pane.render.test.js.map