import { act, render, screen, within } from "@testing-library/react";
import { afterEach, beforeEach, expect, test, vi } from "vitest";
import { DatabiApp } from "./DatabiApp.jsx";
import { fetchFilterOptions, fetchSelfGameStatisticsOverview, fetchStatisticsOverview } from "./api.js";

vi.mock("./api.js", () => ({
  fetchFilterOptions: vi.fn(),
  fetchSelfGameStatisticsOverview: vi.fn(),
  fetchStatisticsOverview: vi.fn(),
  getCurrentAppCode: vi.fn(() => "lalu"),
  setCurrentAppCode: vi.fn((value) => String(value || "lalu").toLowerCase())
}));

vi.mock("./charts/EChart.jsx", () => ({
  EChart: () => <div data-testid="databi-chart" />
}));

beforeEach(() => {
  vi.useFakeTimers();
  vi.setSystemTime(new Date("2026-06-06T08:00:00Z"));
  fetchFilterOptions.mockResolvedValue({
    appOptions: [{ code: "lalu", label: "Lalu", value: "lalu" }],
    countryOptions: [{ countryCode: "", id: 0, label: "全部国家", regionIds: [], searchText: "全部国家 all", value: 0 }],
    regionOptions: [{ countryCodes: [], id: "all", label: "全部区域", value: "all" }]
  });
  fetchSelfGameStatisticsOverview.mockResolvedValue({});
});

afterEach(() => {
  vi.useRealTimers();
  vi.clearAllMocks();
});

test("keeps current data visible during scheduled refresh", async () => {
  const overview = { active_users: 10, paid_users: 2, recharge_usd_minor: 100, updated_at_ms: 1 };
  fetchStatisticsOverview
    .mockResolvedValueOnce(overview)
    .mockResolvedValueOnce(overview)
    .mockImplementationOnce(() => new Promise(() => {}));

  render(<DatabiApp />);

  await flushEffects();
  expect(screen.getAllByText("$1").length).toBeGreaterThan(0);
  expect(document.querySelector(".metric-card.is-loading")).toBeNull();

  await act(async () => {
    vi.advanceTimersByTime(60_000);
  });

  expect(fetchStatisticsOverview).toHaveBeenCalledTimes(3);
  expect(screen.getAllByText("$1").length).toBeGreaterThan(0);
  expect(document.querySelector(".metric-card.is-loading")).toBeNull();
});

test("queries China natural day statistics when display timezone is Beijing", async () => {
  fetchStatisticsOverview.mockResolvedValue({ active_users: 10, paid_users: 2, recharge_usd_minor: 100, updated_at_ms: 1 });

  render(<DatabiApp />);

  await flushEffects();

  expect(fetchStatisticsOverview).toHaveBeenCalledWith(expect.objectContaining({
    endMs: Date.UTC(2026, 5, 6, 15, 59, 59),
    seriesEndMs: Date.UTC(2026, 5, 6, 15, 59, 59),
    seriesStartMs: Date.UTC(2026, 4, 30, 16, 0, 0),
    startMs: Date.UTC(2026, 5, 5, 16, 0, 0),
    statTz: "Asia/Shanghai"
  }));
});

test("loads self game statistics from the big screen switch", async () => {
  fetchStatisticsOverview.mockResolvedValue({ active_users: 10, paid_users: 2, recharge_usd_minor: 100, updated_at_ms: 1 });
  fetchSelfGameStatisticsOverview.mockResolvedValue({
    events: [{ event_name: "page_open", event_count: 8, user_count: 5 }],
    match_totals: { created_matches: 3, matched_matches: 2, settled_matches: 1 },
    retention: { cohort_users: 5, day1_rate: 0.2, day7_rate: 0.1 }
  });

  render(<DatabiApp />);

  await flushEffects();
  await act(async () => {
    screen.getByRole("button", { name: "自研游戏" }).click();
  });
  await flushEffects();

  expect(fetchSelfGameStatisticsOverview).toHaveBeenCalledWith(expect.objectContaining({ appCode: "lalu", gameId: "all", statTz: "Asia/Shanghai" }));
  expect(screen.getByText("Dice / Rock H5 聚合统计")).toBeTruthy();
  expect(screen.getByText("创建局")).toBeTruthy();
});

test("renders real-room robot gift cards in a separate row", async () => {
  fetchStatisticsOverview.mockResolvedValue({
    real_room_robot_avg_room_gift_coin: 300,
    real_room_robot_gift_room_count: 2,
    real_room_robot_lucky_gift_coin: 200,
    real_room_robot_normal_gift_coin: 100,
    real_room_robot_super_gift_coin: 300,
    updated_at_ms: 1
  });

  render(<DatabiApp />);

  await flushEffects();

  const businessSection = screen.getByLabelText("业务指标");
  const robotGiftSection = screen.getByLabelText("真人房机器人送礼指标");
  expect(within(businessSection).queryByText("真人房机器人普通礼物")).toBeNull();
  expect(within(robotGiftSection).getByText("真人房机器人普通礼物")).toBeTruthy();
  expect(within(robotGiftSection).getByText("真人房机器人幸运礼物")).toBeTruthy();
  expect(within(robotGiftSection).getByText("真人房机器人超级幸运礼物")).toBeTruthy();
  expect(within(robotGiftSection).getByText("真人房机器人房均礼物")).toBeTruthy();
});

async function flushEffects() {
  await act(async () => {
    for (let index = 0; index < 10; index += 1) {
      await Promise.resolve();
    }
  });
}
