import { render, screen } from "@testing-library/react";
import { beforeEach, expect, test, vi } from "vitest";

const mocks = vi.hoisted(() => ({ dataMounts: 0, page: null }));

vi.mock("@mui/material/TablePagination", () => ({ default: () => <div data-testid="pagination" /> }));

vi.mock("@/features/activity-templates/hooks/useActivityTemplatesPage.js", () => ({
    useActivityTemplatesPage: () => mocks.page,
}));

vi.mock("@/features/activity-templates/components/ActivityTemplateStatusBadge.jsx", () => ({
    ActivityTemplateStatusBadge: () => <span />,
}));

vi.mock("@/features/activity-templates/components/ActivityTemplateOverlaySkeletons.jsx", () => ({
    ActivityTemplateCloneDialogSkeleton: () => <div data-testid="clone-fallback" />,
    ActivityTemplateDrawerSkeleton: () => <div data-testid="drawer-fallback" />,
}));

vi.mock("@/features/activity-templates/components/ActivityTemplateCloneDialog.jsx", () => ({
    ActivityTemplateCloneDialog: () => <div data-testid="clone-overlay" />,
}));

vi.mock("@/features/activity-templates/components/ActivityTemplateEditorDrawer.jsx", () => ({
    ActivityTemplateEditorDrawer: () => <div data-testid="editor-overlay" />,
}));

vi.mock("@/features/activity-templates/components/ActivityTemplateVersionsDrawer.jsx", () => ({
    ActivityTemplateVersionsDrawer: () => <div data-testid="versions-overlay" />,
}));

vi.mock("@/features/activity-templates/components/ActivityTemplateDataDrawer.jsx", () => ({
    ActivityTemplateDataDrawer: ({ source }) => (
        <div
            data-testid="data-overlay"
            ref={(node) => {
                if (node && !node.dataset.mountCounted) {
                    node.dataset.mountCounted = "true";
                    mocks.dataMounts += 1;
                }
            }}
        >
            {source.templateId}
        </div>
    ),
}));

vi.mock("@/shared/ui/AdminListLayout.jsx", () => ({
    AdminActionIconButton: ({ children, label, onClick }) => (
        <button aria-label={label} type="button" onClick={onClick}>
            {children}
        </button>
    ),
    AdminFilterResetButton: ({ onClick }) => (
        <button type="button" onClick={onClick}>
            重置
        </button>
    ),
    AdminFilterSelect: () => <div />,
    AdminListBody: ({ children }) => <div>{children}</div>,
    AdminListPage: ({ children }) => <main>{children}</main>,
    AdminListToolbar: ({ actions, filters }) => (
        <div>
            {filters}
            {actions}
        </div>
    ),
    AdminRowActions: ({ children }) => <div>{children}</div>,
    AdminSearchBox: () => <input aria-label="搜索" />,
}));

vi.mock("@/shared/ui/Button.jsx", () => ({
    Button: ({ children, startIcon, ...props }) => (
        <button type="button" {...props}>
            {startIcon}
            {children}
        </button>
    ),
}));

vi.mock("@/shared/ui/DataState.jsx", () => ({ DataState: ({ children }) => children }));
vi.mock("@/shared/ui/DataTable.jsx", () => ({ DataTable: () => <div data-testid="data-table" /> }));
vi.mock("@/shared/ui/RegionFilterControl.jsx", () => ({ RegionFilterControl: () => <div /> }));
vi.mock("@/shared/ui/TimeRangeFilter.jsx", () => ({ TimeRangeFilter: () => <div /> }));

import { ActivityTemplatesPage } from "./ActivityTemplatesPage.jsx";

beforeEach(() => {
    mocks.dataMounts = 0;
    mocks.page = createPageState();
});

test("keeps lazy overlays unmounted until their state opens", async () => {
    const view = render(<ActivityTemplatesPage />);

    expect(screen.queryByTestId("editor-overlay")).not.toBeInTheDocument();
    expect(screen.queryByTestId("clone-overlay")).not.toBeInTheDocument();
    expect(screen.queryByTestId("versions-overlay")).not.toBeInTheDocument();
    expect(screen.queryByTestId("data-overlay")).not.toBeInTheDocument();

    mocks.page.editorMode = "create";
    view.rerender(<ActivityTemplatesPage />);
    expect(await screen.findByTestId("editor-overlay")).toBeInTheDocument();
});

test("remounts the data center when the source template identity changes", async () => {
    mocks.page.dataSource = { publishedVersion: 2, templateId: "template-a" };
    const view = render(<ActivityTemplatesPage />);

    expect(await screen.findByText("template-a")).toBeInTheDocument();
    expect(mocks.dataMounts).toBe(1);

    mocks.page.dataSource = { publishedVersion: 1, templateId: "template-b" };
    view.rerender(<ActivityTemplatesPage />);
    expect(await screen.findByText("template-b")).toBeInTheDocument();
    expect(mocks.dataMounts).toBe(2);
});

function createPageState() {
    const handler = vi.fn();
    return {
        abilities: {
            canCreate: true,
            canData: true,
            canDelete: true,
            canExport: true,
            canPublish: true,
            canRetry: true,
            canUpdate: true,
            canView: true,
        },
        archiveTemplate: handler,
        changePageSize: handler,
        changeStatus: handler,
        cloneForm: { name: "", sourceVersion: 0, templateCode: "" },
        cloneSource: null,
        cloneVersion: handler,
        closeClone: handler,
        closeData: handler,
        closeEditor: handler,
        closeVersions: handler,
        data: { items: [], total: 0 },
        dataSource: null,
        disableFromEditor: handler,
        editorDirty: false,
        editorLoading: false,
        editorMode: "",
        error: "",
        form: { templateId: "" },
        gifts: [],
        giftsLoading: false,
        keyword: "",
        loading: false,
        loadingAction: "",
        loadingRegions: false,
        openClone: handler,
        openCreate: handler,
        openData: handler,
        openEdit: handler,
        openVersions: handler,
        openView: handler,
        page: 1,
        pageSize: 20,
        previewVersion: handler,
        regionId: "",
        regionOptions: [],
        reload: handler,
        reloadEditor: handler,
        reloadVersions: handler,
        resetFilters: handler,
        resourceGroups: [],
        saveAndPublish: handler,
        setForm: handler,
        setKeyword: handler,
        setPage: handler,
        setRegionId: handler,
        setStatus: handler,
        setTimeRange: handler,
        setVersionPage: handler,
        status: "",
        submitClone: handler,
        submitForm: handler,
        timeRange: { endMs: "", startMs: "" },
        updateCloneForm: handler,
        validationIssues: [],
        versionPage: 1,
        versionSource: null,
        versions: { items: [], pageSize: 20, total: 0 },
        versionsError: "",
        versionsLoading: false,
    };
}
