import type { Page } from "@playwright/test";

import {
  apiEnvelope,
  chatSendResponse,
  createPaymentOrderResponse,
  createChatSendResponse,
  createPaidImageHistoryResponse,
  createWeeklyLimitChatSendResponse,
  e2eEmailUser,
  emptyChatHistoryResponse,
  emailLoginResponse,
  guestLoginResponse,
  insufficientCreditsUnlockImageResponse,
  insufficientCreditsUnlockVoiceResponse,
  paidImageChatSendResponse,
  paidImageUnlockHistoryResponse,
  paidVoiceHistoryResponse,
  paidPaymentOrderStatusResponse,
  paymentPlansResponse,
  refreshedEmailLoginResponse,
  refreshedGuestLoginResponse,
  userEntitlementsResponse,
  vipStatusResponse,
} from "./test-data";

interface MockCoreApisOptions {
  chatLimitTriggerAt?: number;
  chatSendTokenRefreshFlow?: boolean;
  paidImageFlow?: boolean;
  paidImageInsufficientCreditsFlow?: boolean;
  paidVoiceInsufficientCreditsFlow?: boolean;
}

export async function mockCoreApis(
  page: Page,
  options: MockCoreApisOptions = {},
): Promise<void> {
  const {
    chatLimitTriggerAt,
    chatSendTokenRefreshFlow = false,
    paidImageFlow = false,
    paidImageInsufficientCreditsFlow = false,
    paidVoiceInsufficientCreditsFlow = false,
  } = options;
  let sendCount = 0;
  let hasExpiredChatSend = false;
  let paidImageRequested = false;
  let paidImageUnlocked = false;

  await page.route("**/api/auth/guest", async (route) => {
    const response =
      chatSendTokenRefreshFlow && hasExpiredChatSend
        ? refreshedGuestLoginResponse
        : guestLoginResponse;
    await route.fulfill({ json: apiEnvelope(response) });
  });

  await page.route("**/api/auth/login", async (route) => {
    if (paidImageFlow) {
      paidImageRequested = true;
    }

    await route.fulfill({ json: apiEnvelope(emailLoginResponse) });
  });

  await page.route("**/api/auth/refresh", async (route) => {
    await route.fulfill({ json: apiEnvelope(refreshedEmailLoginResponse) });
  });

  await page.route("**/api/auth/logout", async (route) => {
    await route.fulfill({ json: apiEnvelope(null) });
  });

  await page.route("**/api/user/profile", async (route) => {
    await route.fulfill({ json: apiEnvelope(e2eEmailUser) });
  });

  await page.route("**/api/user/entitlements", async (route) => {
    await route.fulfill({ json: apiEnvelope(userEntitlementsResponse) });
  });

  await page.route("**/api/chat/history**", async (route) => {
    const response =
      paidVoiceInsufficientCreditsFlow
        ? paidVoiceHistoryResponse
        : paidImageInsufficientCreditsFlow
          ? createPaidImageHistoryResponse(false)
        : paidImageFlow && paidImageRequested
        ? createPaidImageHistoryResponse(paidImageUnlocked)
        : emptyChatHistoryResponse;

    await route.fulfill({ json: apiEnvelope(response) });
  });

  await page.route("**/api/chat/send", async (route) => {
    sendCount += 1;
    const requestBody = route.request().postDataJSON() as
      | { message?: unknown }
      | undefined;
    const message =
      typeof requestBody?.message === "string" ? requestBody.message : "";

    if (chatSendTokenRefreshFlow && !hasExpiredChatSend) {
      hasExpiredChatSend = true;
      await route.fulfill({
        status: 401,
        json: {
          message: "expired",
        },
      });
      return;
    }

    const response =
      paidImageFlow && message.includes("给我发图片")
        ? paidImageChatSendResponse
        : chatLimitTriggerAt != null && sendCount >= chatLimitTriggerAt
          ? createWeeklyLimitChatSendResponse(sendCount, chatLimitTriggerAt)
          : chatLimitTriggerAt != null
            ? createChatSendResponse(sendCount)
            : chatSendResponse;

    if (paidImageFlow && message.includes("给我发图片")) {
      paidImageRequested = true;
      paidImageUnlocked = false;
    }

    await route.fulfill({ json: apiEnvelope(response) });
  });

  await page.route("**/api/chat/unlock-history", async (route) => {
    if (paidImageFlow && paidImageRequested) {
      paidImageUnlocked = true;
    }

    const response =
      paidImageFlow && paidImageRequested
        ? paidImageUnlockHistoryResponse
        : {
            unlocked: true,
            reason: "no_locked_messages",
            totalLocked: 0,
            unlockedCount: 0,
            privateCount: 0,
            imageCount: 0,
            voiceCount: 0,
            requiredCredits: 0,
            currentCredits: 0,
            remainingCredits: 0,
            shortfallCredits: 0,
            costsByMessage: {},
            messageIds: [],
          };

    await route.fulfill({ json: apiEnvelope(response) });
  });

  await page.route("**/api/chat/unlock-private", async (route) => {
    const response =
      paidVoiceInsufficientCreditsFlow
        ? insufficientCreditsUnlockVoiceResponse
        : paidImageInsufficientCreditsFlow
          ? insufficientCreditsUnlockImageResponse
          : paidImageFlow && paidImageRequested && !paidImageUnlocked
            ? insufficientCreditsUnlockImageResponse
          : {
              unlocked: true,
              content: "Unlocked message",
              reason: "ok",
              creditBalance: 100,
              creditsCharged: 0,
              requiredCredits: 0,
              shortfallCredits: 0,
              lockDetail: {
                locked: false,
                showContent: true,
                showUpgrade: false,
                reason: null,
                hint: null,
                detail: null,
              },
            };

    await route.fulfill({ json: apiEnvelope(response) });
  });

  await page.route("**/api/payment/plans**", async (route) => {
    await route.fulfill({ json: apiEnvelope(paymentPlansResponse) });
  });

  await page.route("**/api/payment/create-order", async (route) => {
    await route.fulfill({ json: apiEnvelope(createPaymentOrderResponse) });
  });

  await page.route("**/api/payment/order-status**", async (route) => {
    if (paidImageFlow && paidImageRequested) {
      paidImageUnlocked = true;
    }

    await route.fulfill({ json: apiEnvelope(paidPaymentOrderStatusResponse) });
  });

  await page.route("**/api/payment/vip-status**", async (route) => {
    await route.fulfill({ json: apiEnvelope(vipStatusResponse) });
  });
}
