import { GoogleAuth } from "google-auth-library";

const ANDROID_PUBLISHER_SCOPE = "https://www.googleapis.com/auth/androidpublisher";
const API_BASE = "https://androidpublisher.googleapis.com/androidpublisher/v3/applications";
const PACKAGE_NAME = "com.makecdev.coderemotemanager";
const PRODUCT_ID = "pro_multi_account";

export function createGooglePlayClient({
  auth = new GoogleAuth({ scopes: [ANDROID_PUBLISHER_SCOPE] }),
  fetch = globalThis.fetch,
  packageName,
  productId,
}) {
  if (
    packageName !== PACKAGE_NAME
    || productId !== PRODUCT_ID
    || typeof auth?.getRequestHeaders !== "function"
    || typeof fetch !== "function"
  ) throw googlePlayError("invalid_google_play_config", 500, "Google Play configuration is invalid.");

  const packageSegment = encodeURIComponent(packageName);
  const productSegment = encodeURIComponent(productId);

  async function request(url, options) {
    try {
      const authorization = await auth.getRequestHeaders(url);
      const headers = new Headers(authorization);
      for (const [name, value] of Object.entries(options.headers ?? {})) headers.set(name, value);
      return await fetch(url, { ...options, headers });
    } catch {
      throw unavailable();
    }
  }

  async function fetchPurchase(tokenSegment) {
    const url = `${API_BASE}/${packageSegment}/purchases/productsv2/tokens/${tokenSegment}`;
    const response = await request(url, { method: "GET" });
    if ([404, 410].includes(response?.status)) {
      throw googlePlayError("purchase_not_valid", 400, "The purchase is invalid.");
    }
    if (!response?.ok) throw unavailable();
    try {
      return normalizePurchase(await response.json());
    } catch (error) {
      if (error?.googlePlaySafe) throw error;
      throw unavailable();
    }
  }

  async function acknowledge(tokenSegment) {
    const url = `${API_BASE}/${packageSegment}/purchases/products/${productSegment}/tokens/${tokenSegment}:acknowledge`;
    const response = await request(url, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: "{}",
    });
    if (response?.ok) return;
    if (response?.status === 409) {
      const confirmed = await fetchPurchase(tokenSegment);
      if (confirmed.acknowledged) return;
    }
    throw unavailable();
  }

  return {
    async verifyPurchase(purchaseToken) {
      if (typeof purchaseToken !== "string" || purchaseToken.length === 0 || purchaseToken.length > 4096) {
        throw googlePlayError("purchase_not_valid", 400, "The purchase is invalid.");
      }
      const tokenSegment = encodeURIComponent(purchaseToken);
      const purchase = await fetchPurchase(tokenSegment);
      if (!purchase.acknowledged) await acknowledge(tokenSegment);
      return { ...purchase, acknowledged: true };
    },
  };
}

function normalizePurchase(value) {
  const state = value?.purchaseStateContext?.purchaseState;
  if (state === "PENDING") throw googlePlayError("purchase_pending", 409, "The purchase is pending.");
  if (state === "CANCELLED") throw googlePlayError("purchase_canceled", 402, "The purchase is canceled.");
  if (state !== "PURCHASED") throw googlePlayError("purchase_not_valid", 400, "The purchase is invalid.");

  if (!Array.isArray(value.productLineItem) || value.productLineItem.length !== 1) {
    throw googlePlayError("purchase_not_valid", 400, "The purchase is invalid.");
  }
  const line = value.productLineItem[0];
  const offer = line?.productOfferDetails;
  if (line?.productId !== PRODUCT_ID || !offer || !Number.isInteger(offer.quantity) || offer.quantity < 1) {
    throw googlePlayError("purchase_not_valid", 400, "The purchase is invalid.");
  }
  if (!Number.isInteger(offer.refundableQuantity) || offer.refundableQuantity < 1) {
    throw googlePlayError("purchase_refunded", 402, "The purchase is refunded.");
  }
  if (offer.refundableQuantity > offer.quantity) {
    throw googlePlayError("purchase_not_valid", 400, "The purchase is invalid.");
  }
  if (offer.consumptionState === "CONSUMPTION_STATE_CONSUMED") {
    throw googlePlayError("purchase_consumed", 409, "The purchase has been consumed.");
  }
  if (offer.consumptionState !== "CONSUMPTION_STATE_YET_TO_BE_CONSUMED") {
    throw googlePlayError("purchase_not_valid", 400, "The purchase is invalid.");
  }
  if (typeof value.purchaseCompletionTime !== "string" || !Number.isFinite(Date.parse(value.purchaseCompletionTime))) {
    throw googlePlayError("purchase_not_valid", 400, "The purchase is invalid.");
  }

  let acknowledged;
  if (value.acknowledgementState === "ACKNOWLEDGEMENT_STATE_PENDING") acknowledged = false;
  else if (value.acknowledgementState === "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED") acknowledged = true;
  else throw googlePlayError("purchase_not_valid", 400, "The purchase is invalid.");

  return {
    state: "purchased",
    acknowledged,
    purchaseCompletionTime: value.purchaseCompletionTime,
  };
}

function unavailable() {
  return googlePlayError("google_play_unavailable", 503, "Google Play verification is unavailable.");
}

function googlePlayError(code, status, message) {
  const error = new Error(message);
  error.code = code;
  error.status = status;
  error.googlePlaySafe = true;
  return error;
}
