import test from "node:test";
import assert from "node:assert/strict";
import { Money } from "../src/shared/money.ts";
import type { Listing } from "../src/modules/marketplace/listings.ts";
import { assertBuyerOrderAccess, assertCartCompatible, assertSellerOrderAccess, createOrderFromListing, type Order } from "../src/modules/orders/orders.ts";
import type { InventoryItem } from "../src/modules/inventory/inventory.ts";
import { authorizeBuyerSecretRead, markInventoryDelivered, markInventoryFunded } from "../src/modules/inventory/delivery.ts";
import { buyerOverview, sellerOverview } from "../src/modules/dashboard/projections.ts";

const listing = (overrides: Partial<Listing> = {}): Listing => ({ id: "listing-1", sellerId: "seller-1", kind: "game_key", deliveryMode: "instant_code", region: "GLOBAL", title: "Original game key", unitPrice: Money.ofMinor(2_500n, "USD"), status: "active", version: 1, ...overrides });

test("order snapshots server-owned listing price and rejects self-purchase", () => {
  const order = createOrderFromListing(listing(), "buyer-1", 2, "CRK20260913AB");
  assert.equal(order.price.subtotal.minor, 5_000n);
  assert.equal(order.titleSnapshot, "Original game key");
  assert.throws(() => createOrderFromListing(listing(), "seller-1", 1, "CRK20260913AC"), { code: "SELF_PURCHASE_FORBIDDEN" });
});

test("buyer and seller order access are isolated", () => {
  const order = createOrderFromListing(listing(), "buyer-1", 1, "CRK20260913AD");
  assert.doesNotThrow(() => assertBuyerOrderAccess(order, "buyer-1"));
  assert.doesNotThrow(() => assertSellerOrderAccess(order, "seller-1"));
  assert.throws(() => assertBuyerOrderAccess(order, "buyer-2"), { code: "FORBIDDEN" });
  assert.throws(() => assertSellerOrderAccess(order, "seller-2"), { code: "FORBIDDEN" });
});

test("cart accepts compatible codes and rejects currency/manual delivery mixing", () => {
  assert.doesNotThrow(() => assertCartCompatible([listing(), listing({ id: "listing-2" })]));
  assert.throws(() => assertCartCompatible([listing(), listing({ id: "listing-2", unitPrice: Money.ofMinor(1_000n, "PHP") })]), { code: "CART_CURRENCY_MISMATCH" });
  assert.throws(() => assertCartCompatible([listing({ deliveryMode: "manual_trade" })]), { code: "CART_DELIVERY_INCOMPATIBLE" });
});

test("digital secret follows funded-delivered lifecycle and only buyer can read", () => {
  const base = createOrderFromListing(listing(), "buyer-1", 1, "CRK20260913AE");
  const funded: Order = { ...base, status: "funded" };
  const reserved: InventoryItem = { id: "inventory-1", listingId: listing().id, sellerId: "seller-1", secretCiphertext: new Uint8Array([9, 8, 7]), secretFingerprint: "fingerprint", status: "reserved", orderId: funded.id, reservedUntil: new Date() };
  assert.throws(() => authorizeBuyerSecretRead(reserved, funded, "buyer-1"), { code: "DELIVERY_NOT_AVAILABLE" });
  const sold = markInventoryFunded(reserved, funded);
  const deliveredItem = markInventoryDelivered(sold, funded);
  assert.deepEqual(authorizeBuyerSecretRead(deliveredItem, { ...funded, status: "delivered" }, "buyer-1"), new Uint8Array([9, 8, 7]));
  assert.throws(() => authorizeBuyerSecretRead(deliveredItem, { ...funded, status: "delivered" }, "buyer-2"), { code: "FORBIDDEN" });
});

test("dashboard projections cannot leak another user's orders or listings", () => {
  const buyerOrder = createOrderFromListing(listing(), "buyer-1", 1, "CRK20260913AF");
  const otherOrder = createOrderFromListing(listing({ id: "listing-2", sellerId: "seller-2" }), "buyer-2", 1, "CRK20260913AG");
  const buyer = buyerOverview("buyer-1", [buyerOrder, otherOrder]);
  assert.deepEqual(buyer.recentOrders.map((order) => order.id), [buyerOrder.id]);
  const seller = sellerOverview("seller-1", [listing(), listing({ id: "listing-2", sellerId: "seller-2" })], [buyerOrder, otherOrder]);
  assert.equal(seller.activeListings, 1);
  assert.deepEqual(seller.recentOrders.map((order) => order.id), [buyerOrder.id]);
});
