export type AppleBillingStatus =
  | "active"
  | "expired"
  | "canceled"
  | "refunded"
  | "revoked"
  | "unknown";

export type AppleBillingCandidate = {
  currentPeriodEnd: number;
  plan: "solo" | "annual";
  quantity: 1;
  status: AppleBillingStatus;
};

export const APPLE_ACCESSIBLE_STATUSES: AppleBillingStatus[] = ["active", "canceled"];

export function mapAppleProductToPlan(
  productId: string | null | undefined,
  config: {
    annualProductId: string;
    soloProductId: string;
  }
): "solo" | "annual" | null {
  if (!productId) {
    return null;
  }

  if (productId === config.soloProductId) {
    return "solo";
  }

  if (productId === config.annualProductId) {
    return "annual";
  }

  return null;
}

export function normalizeAppleSubscriptionStatus(
  eventType: string | null | undefined,
  cancelAtPeriodEnd: boolean
): AppleBillingStatus {
  const normalizedEventType = (eventType ?? "").trim().toUpperCase();

  if (normalizedEventType === "EXPIRATION") {
    return "expired";
  }

  if (normalizedEventType === "CANCELLATION") {
    return cancelAtPeriodEnd ? "canceled" : "revoked";
  }

  if (normalizedEventType === "BILLING_ISSUE") {
    return "canceled";
  }

  if (normalizedEventType === "SUBSCRIPTION_PAUSED") {
    return "canceled";
  }

  if (normalizedEventType === "UNCANCELLATION") {
    return "active";
  }

  if (
    normalizedEventType === "INITIAL_PURCHASE" ||
    normalizedEventType === "NON_RENEWING_PURCHASE" ||
    normalizedEventType === "PRODUCT_CHANGE" ||
    normalizedEventType === "RENEWAL" ||
    normalizedEventType === "TRANSFER"
  ) {
    return "active";
  }

  return "unknown";
}

export function toAppleBillingCandidate(input: {
  currentPeriodEnd: string | null;
  now?: Date;
  plan: "solo" | "annual";
  status: AppleBillingStatus;
}): AppleBillingCandidate | null {
  if (!APPLE_ACCESSIBLE_STATUSES.includes(input.status)) {
    return null;
  }

  const currentPeriodEndMs = input.currentPeriodEnd ? Date.parse(input.currentPeriodEnd) : NaN;
  if (Number.isNaN(currentPeriodEndMs)) {
    return null;
  }

  const now = input.now ?? new Date();
  if (currentPeriodEndMs <= now.getTime()) {
    return null;
  }

  return {
    currentPeriodEnd: Math.floor(currentPeriodEndMs / 1000),
    plan: input.plan,
    quantity: 1,
    status: input.status,
  };
}
