import { afterEach, expect, test, vi } from "vitest";
import {
  fetchFilterOptions,
  fetchSocialBiFilterOptions,
  fetchSocialBiKpi,
  fetchSocialBiOverview,
  fetchSocialBiRequirements,
  fetchStatisticsOverview,
  getCurrentAppCode,
  getDefaultAppOptions,
  setCurrentAppCode
} from "./api.js";

afterEach(() => {
  window.localStorage.clear();
  vi.unstubAllGlobals();
});

test("stores the last selected databi app including all apps", () => {
  expect(getCurrentAppCode()).toBe("lalu");

  expect(setCurrentAppCode("YUMI")).toBe("yumi");
  expect(window.localStorage.getItem("hyapp-admin.app-code")).toBe("yumi");
  expect(getCurrentAppCode()).toBe("yumi");

  expect(setCurrentAppCode("")).toBe("");
  expect(window.localStorage.getItem("hyapp-admin.app-code")).toBe("");
  expect(getCurrentAppCode()).toBe("");
});

test("adds fixed databi app options without losing API apps", async () => {
  vi.stubGlobal(
    "fetch",
    vi.fn(async (input) => {
      const url = String(input);
      if (url.includes("/v1/admin/apps")) {
        return jsonResponse({ items: [{ appCode: "huwaa", appName: "Huwaa" }, { app_code: "lalu", name: "Lalu" }] });
      }
      if (url.includes("/v1/admin/regions")) {
        return jsonResponse({ items: [] });
      }
      if (url.includes("/v1/admin/countries")) {
        return jsonResponse({ items: [] });
      }
      return jsonResponse(null, 404);
    })
  );

  const options = await fetchFilterOptions({ appCode: "lalu" });

  expect(options.appOptions).toEqual([
    { code: "", label: "全部", value: "" },
    { code: "huwaa", label: "Huwaa", value: "huwaa" },
    { code: "lalu", label: "Lalu", value: "lalu" },
    { code: "aslan", label: "Aslan", value: "aslan" },
    { code: "yumi", label: "Yumi", value: "yumi" }
  ]);
});

test("provides static databi app options before filter API loads", () => {
  expect(getDefaultAppOptions()).toEqual([
    { code: "", label: "全部", value: "" },
    { code: "lalu", label: "Lalu", value: "lalu" },
    { code: "aslan", label: "Aslan", value: "aslan" },
    { code: "yumi", label: "Yumi", value: "yumi" }
  ]);
});

test("loads social BI apps and operation users from admin APIs", async () => {
  vi.stubGlobal(
    "fetch",
    vi.fn(async (input) => {
      const url = String(input);
      if (url.includes("/v1/admin/apps")) {
        return jsonResponse({ items: [{ appCode: "huwaa", appName: "Huwaa" }] });
      }
      if (url.includes("/v1/teams/2/users")) {
        return jsonResponse({ items: [{ account: "ava", id: 7, name: "Ava Chen", teamName: "运营一部" }] });
      }
      return jsonResponse(null, 404);
    })
  );

  const options = await fetchSocialBiFilterOptions({ appCode: "lalu" });

  expect(options.appOptions).toEqual([
    { label: "全部 App", value: "all" },
    { label: "Huwaa", value: "huwaa" },
    { label: "Aslan", value: "aslan" },
    { label: "Yumi", value: "yumi" }
  ]);
  expect(options.operatorOptions).toEqual([
    { label: "全部人员", searchText: "all 全部人员", value: "all" },
    { label: "Ava Chen", searchText: "ava chen ava 运营一部", value: "7" }
  ]);
  expect(String(fetch.mock.calls[1][0])).toContain("/api/v1/teams/2/users?");
  expect(String(fetch.mock.calls[1][0])).toContain("status=active");
});

test("loads social BI requirements with section role and payer filters", async () => {
  vi.stubGlobal("fetch", vi.fn(async () => jsonResponse({ section: "revenue", total: { recharge_users: 2 } })));
  const controller = new AbortController();

  const data = await fetchSocialBiRequirements({
    appCodes: ["lalu", "huwaa"],
    endMs: 20,
    payerType: "paid",
    regionIds: [9, 11],
    section: "revenue",
    signal: controller.signal,
    startMs: 10,
    statTz: "Asia/Shanghai",
    userRole: "host"
  });

  const requestURL = new URL(String(fetch.mock.calls[0][0]));
  expect(requestURL.pathname).toBe("/api/v1/admin/databi/social/requirements");
  expect(requestURL.searchParams.get("app_codes")).toBe("lalu,huwaa");
  expect(requestURL.searchParams.get("section")).toBe("revenue");
  expect(requestURL.searchParams.get("user_role")).toBe("host");
  expect(requestURL.searchParams.get("payer_type")).toBe("paid");
  expect(requestURL.searchParams.get("region_ids")).toBe("9,11");
  expect(requestURL.searchParams.get("stat_tz")).toBe("Asia/Shanghai");
  expect(fetch.mock.calls[0][1].signal).toBe(controller.signal);
  expect(data.total.recharge_users).toBe(2);
});

test("loads social BI overview with an explicit multi-region Finance scope", async () => {
  vi.stubGlobal("fetch", vi.fn(async () => jsonResponse({ apps: [] })));

  await fetchSocialBiOverview({
    appCodes: ["aslan"],
    endMs: 20,
    regionIds: [9, 11],
    startMs: 10,
    statTz: "Asia/Shanghai"
  });

  const requestURL = new URL(String(fetch.mock.calls[0][0]));
  expect(requestURL.pathname).toBe("/api/v1/admin/databi/social/overview");
  expect(requestURL.searchParams.get("app_codes")).toBe("aslan");
  expect(requestURL.searchParams.get("region_ids")).toBe("9,11");
});

test("loads social BI KPI for the selected operation user", async () => {
  vi.stubGlobal("fetch", vi.fn(async () => jsonResponse({ items: [], summary: {} })));

  await fetchSocialBiKpi({
    appCodes: ["aslan", "yumi"],
    endMs: 20,
    operatorUserId: 9,
    startMs: 10,
    statTz: "Asia/Shanghai"
  });

  const requestURL = new URL(String(fetch.mock.calls[0][0]));
  expect(requestURL.pathname).toBe("/api/v1/admin/databi/social/kpi");
  expect(requestURL.searchParams.get("app_codes")).toBe("aslan,yumi");
  expect(requestURL.searchParams.get("operator_user_id")).toBe("9");
});

test("omits app scope headers and query params for all databi apps", async () => {
  vi.stubGlobal("fetch", vi.fn(async () => jsonResponse({ updated_at_ms: 1 })));

  await fetchStatisticsOverview({
    appCode: "",
    countryId: 0,
    endMs: 2,
    regionId: "all",
    seriesEndMs: 2,
    seriesStartMs: 1,
    startMs: 1,
    statTz: "Asia/Shanghai"
  });

  const [url, init] = fetch.mock.calls[0];
  const requestURL = new URL(String(url));
  expect(requestURL.searchParams.has("app_code")).toBe(false);
  expect(init.headers["X-App-Code"]).toBeUndefined();
});

function jsonResponse(data, status = 200) {
  return new Response(JSON.stringify({ code: status === 200 ? 0 : status, data, message: status === 200 ? "" : "error" }), {
    headers: { "content-type": "application/json" },
    status
  });
}
