/**
 * Digital download entitlements for an order.
 *
 * Entitlements are derived, not snapshotted: a paid order entitles the
 * customer to the CURRENT digitalAssets of every product on the order
 * (Shopify Digital Downloads behaves the same — replacing a file updates
 * what customers download). The order document only tracks per-file usage
 * counters against the product's downloadLimit.
 */

import { PAYMENT_STATUS } from "@/config/app.config";
import { Product } from "@/models";

export type DigitalEntitlementFile = {
  assetId: string;
  productId: string;
  productName: string;
  filename: string;
  size?: number;
  mimeType?: string;
  /** 0 = unlimited. */
  downloadLimit: number;
  downloadedCount: number;
  /** null = unlimited. */
  remainingDownloads: number | null;
};

type OrderLike = {
  items?: { productId?: unknown }[];
  paymentStatus?: string;
  digitalDownloads?: { assetId: string; count?: number }[];
};

/** Digital files are delivered only once the order is fully paid. */
export function isOrderEntitledToDownloads(order: OrderLike): boolean {
  return order.paymentStatus === PAYMENT_STATUS.PAID;
}

function orderProductIds(order: OrderLike): string[] {
  const ids = new Set<string>();
  for (const item of order.items ?? []) {
    if (!item.productId) continue;
    // productId may be an ObjectId, a string, or a populated document.
    const raw = item.productId as { _id?: unknown };
    ids.add(String(raw._id ?? item.productId));
  }
  return [...ids];
}

/**
 * List every digital file the given (already ownership-checked) order grants
 * access to, with usage counters applied.
 */
export async function getOrderDigitalEntitlements(
  order: OrderLike,
): Promise<DigitalEntitlementFile[]> {
  const productIds = orderProductIds(order);
  if (productIds.length === 0) return [];

  const products = await Product.find({
    _id: { $in: productIds },
    "digitalAssets.0": { $exists: true },
  })
    .select("name digitalAssets digitalDelivery")
    .lean();

  const counts = new Map(
    (order.digitalDownloads ?? []).map((d) => [d.assetId, d.count ?? 0]),
  );

  const files: DigitalEntitlementFile[] = [];
  for (const product of products) {
    const downloadLimit = product.digitalDelivery?.downloadLimit ?? 0;
    const assets = [...(product.digitalAssets ?? [])].sort(
      (a, b) => (a.position ?? 0) - (b.position ?? 0),
    );
    for (const asset of assets) {
      const downloadedCount = counts.get(asset._id) ?? 0;
      files.push({
        assetId: asset._id,
        productId: String(product._id),
        productName: product.name,
        filename: asset.filename,
        size: asset.size,
        mimeType: asset.mimeType,
        downloadLimit,
        downloadedCount,
        remainingDownloads:
          downloadLimit > 0
            ? Math.max(0, downloadLimit - downloadedCount)
            : null,
      });
    }
  }
  return files;
}

/**
 * Does any product on this order carry digital files? Used by the order
 * confirmation email to decide whether to show the downloads notice.
 */
export async function orderHasDigitalItems(order: OrderLike): Promise<boolean> {
  const productIds = orderProductIds(order);
  if (productIds.length === 0) return false;
  const count = await Product.countDocuments({
    _id: { $in: productIds },
    "digitalAssets.0": { $exists: true },
  });
  return count > 0;
}
