import { render, screen } from "@testing-library/react";
import { afterEach, beforeEach, expect, test, vi } from "vitest";
import { MemoryRouter } from "react-router-dom";
import App from "@/app/App.jsx";
import { AppProviders } from "@/app/providers.jsx";
import { adminRoutes } from "@/app/router/routeConfig";
import { setAccessToken } from "@/shared/api/request";

beforeEach(() => {
    window.localStorage.clear();
    vi.stubGlobal(
        "fetch",
        vi.fn(async () => new Response(JSON.stringify({ code: 401, message: "unauthorized" }), { status: 401 })),
    );
});

afterEach(() => {
    vi.unstubAllGlobals();
});

test("renders login route", async () => {
    renderWithRoute("/login");

    expect(await screen.findByText("HYApp 管理平台")).toBeInTheDocument();
});

test("redirects protected route to login when unauthenticated", async () => {
    renderWithRoute("/system/users");

    expect(await screen.findByText("HYApp 管理平台")).toBeInTheDocument();
});

test("redirects a zero-App user to the common workspace", async () => {
    setAccessToken("test-token");
    vi.mocked(fetch).mockImplementation(async (input) => {
        const url = String(input);
        if (url.includes("/v1/auth/refresh") || url.includes("/v1/auth/me")) {
            return jsonResponse({
                accessToken: "test-token",
                permissions: ["overview:view", "finance:view", "resource:view"],
                user: { id: 7, username: "finance" },
            });
        }
        if (url.includes("/v1/admin/apps/visible")) {
            return jsonResponse({ items: [], mode: "none", total: 0 });
        }
        if (url.includes("/v1/admin/navigation/menus")) {
            return jsonResponse([]);
        }
        return jsonResponse(null);
    });

    renderWithRoute("/resources");

    expect(await screen.findByRole("link", { name: /财务工作台/ })).toBeInTheDocument();
    expect(screen.getByText("通用")).toBeInTheDocument();
    expect(screen.queryByText("资源列表")).not.toBeInTheDocument();
});

test("renders resource list route with an authenticated session", async () => {
    setAccessToken("test-token");
    vi.mocked(fetch).mockImplementation(async (input) => {
        const url = String(input);
        if (url.includes("/v1/auth/refresh") || url.includes("/v1/auth/me")) {
            return jsonResponse({
                accessToken: "test-token",
                permissions: ["resource:view"],
                user: { userId: 1, username: "admin" },
            });
        }
        if (url.includes("/v1/admin/apps")) {
            return jsonResponse({ items: [{ appCode: "lalu", name: "Lalu" }], total: 1 });
        }
        if (url.includes("/v1/admin/navigation/menus")) {
            return jsonResponse([]);
        }
        if (url.includes("/v1/admin/resources")) {
            return jsonResponse({ items: [], page: 1, pageSize: 50, total: 0 });
        }
        return jsonResponse(null);
    });

    renderWithRoute("/resources");

    expect((await screen.findAllByText("资源列表")).length).toBeGreaterThan(0);
});

test("renders cp config route with an authenticated session", async () => {
    setAccessToken("test-token");
    vi.mocked(fetch).mockImplementation(async (input) => {
        const url = String(input);
        if (url.includes("/v1/auth/refresh") || url.includes("/v1/auth/me")) {
            return jsonResponse({
                accessToken: "test-token",
                permissions: ["cp-config:view"],
                user: { userId: 1, username: "admin" },
            });
        }
        if (url.includes("/v1/admin/apps")) {
            return jsonResponse({ items: [{ appCode: "lalu", name: "Lalu" }], total: 1 });
        }
        if (url.includes("/v1/admin/navigation/menus")) {
            return jsonResponse([]);
        }
        if (url.includes("/v1/admin/resource-groups")) {
            return jsonResponse({ items: [], page: 1, pageSize: 50, total: 0 });
        }
        if (url.includes("/v1/admin/activity/cp/config")) {
            return jsonResponse({
                appCode: "lalu",
                relations: [
                    cpRelationFixture("cp", "CP", 1),
                    cpRelationFixture("brother", "兄弟", 5),
                    cpRelationFixture("sister", "姐妹", 5),
                ],
            });
        }
        if (url.includes("/v1/admin/activity/cp/relationships")) {
            return jsonResponse({
                items: [
                    {
                        relationshipId: "cp_1001_1002",
                        relationType: "cp",
                        status: "active",
                        userA: { displayUserId: "1001", userId: "1001", username: "A" },
                        userB: { displayUserId: "1002", userId: "1002", username: "B" },
                        intimacyValue: 12000,
                        level: 2,
                        durationDays: 3,
                        gift: { giftId: "rose", giftName: "Rose", giftCount: 1, giftValue: 100 },
                        formedAtMs: 1760000000000,
                    },
                ],
                page: 1,
                pageSize: 50,
                total: 1,
            });
        }
        if (url.includes("/v1/admin/activity/cp/applications")) {
            return jsonResponse({ items: [], page: 1, pageSize: 50, total: 0 });
        }
        return jsonResponse(null);
    });

    renderWithRoute("/activities/cp-config");

    expect((await screen.findAllByText("CP配置")).length).toBeGreaterThan(0);
    expect(await screen.findByText("已加载 1 条 · 共 1 条")).toBeInTheDocument();
    expect(screen.queryByText("共 1 条")).not.toBeInTheDocument();
});

test("renders cp weekly rank route with an authenticated session", async () => {
    setAccessToken("test-token");
    vi.mocked(fetch).mockImplementation(async (input) => {
        const url = String(input);
        if (url.includes("/v1/auth/refresh") || url.includes("/v1/auth/me")) {
            return jsonResponse({
                accessToken: "test-token",
                permissions: ["cp-weekly-rank:view"],
                user: { userId: 1, username: "admin" },
            });
        }
        if (url.includes("/v1/admin/apps")) {
            return jsonResponse({ items: [{ appCode: "lalu", name: "Lalu" }], total: 1 });
        }
        if (url.includes("/v1/admin/navigation/menus")) {
            return jsonResponse([]);
        }
        if (url.includes("/v1/admin/resource-groups")) {
            return jsonResponse({ items: [], page: 1, pageSize: 50, total: 0 });
        }
        if (url.includes("/v1/admin/activity/cp-weekly-rank/config")) {
            return jsonResponse({
                activityCode: "cp_weekly_rank",
                enabled: true,
                relationType: "cp",
                rewards: [
                    { rankNo: 1, resourceGroupId: 1001 },
                    { rankNo: 2, resourceGroupId: 1002 },
                    { rankNo: 3, resourceGroupId: 1003 },
                ],
                topCount: 3,
            });
        }
        if (url.includes("/v1/admin/activity/cp-weekly-rank/settlements")) {
            return jsonResponse({
                items: [
                    {
                        periodStartMs: 1760918400000,
                        periodEndMs: 1761523200000,
                        rankNo: 1,
                        relationshipId: "cp_1001_1002",
                        score: 12000,
                        settlementId: "settlement_1",
                        status: "granted",
                        userId: "1001",
                    },
                ],
                total: 1,
            });
        }
        return jsonResponse(null);
    });

    renderWithRoute("/activities/cp-weekly-rank");

    expect((await screen.findAllByText("CP排行活动")).length).toBeGreaterThan(0);
    expect(await screen.findByText("已发放")).toBeInTheDocument();
});

test("renders the shareable app user detail route with the detail header", async () => {
    setAccessToken("test-token");
    vi.mocked(fetch).mockImplementation(async (input) => {
        const url = String(input);
        if (url.includes("/v1/auth/refresh") || url.includes("/v1/auth/me")) {
            return jsonResponse({
                accessToken: "test-token",
                permissions: ["app-user:view"],
                user: { userId: 1, username: "admin" },
            });
        }
        if (url.includes("/v1/admin/apps")) {
            return jsonResponse({ items: [{ appCode: "lalu", name: "Lalu" }], total: 1 });
        }
        if (url.includes("/v1/admin/navigation/menus")) {
            return jsonResponse([]);
        }
        if (url.includes("/v1/app/users/10001")) {
            return jsonResponse({
                display_user_id: "163337",
                status: "active",
                user_id: "10001",
                username: "detail-user",
            });
        }
        return jsonResponse(null);
    });

    renderWithRoute("/app/users/10001");

    expect(await screen.findByRole("heading", { level: 1, name: "用户详情" })).toBeInTheDocument();
    expect((await screen.findAllByText("detail-user")).length).toBeGreaterThan(0);
});

test("admin routes declare menu code and permission", () => {
    expect(adminRoutes.length).toBeGreaterThan(0);
    expect(adminRoutes.every((route) => route.menuCode && route.permission)).toBe(true);
});

function renderWithRoute(route) {
    return render(
        <AppProviders>
            <MemoryRouter initialEntries={[route]}>
                <App />
            </MemoryRouter>
        </AppProviders>,
    );
}

function jsonResponse(data) {
    return new Response(JSON.stringify({ code: 0, data }), { status: 200 });
}

function cpRelationFixture(relationType, displayName, maxCountPerUser) {
    return {
        relationType,
        displayName,
        maxCountPerUser,
        applicationExpireHours: 24,
        status: "active",
        levels: Array.from({ length: 5 }, (_, index) => ({
            level: index + 1,
            intimacyThreshold: index * 10000,
            rewardResourceGroupId: 0,
            levelIconUrl: "",
            status: "active",
        })),
    };
}
