import { assertBrand, SeedNameSchema, BrandSchema, createTestClient, assertCart, fixtures, AddItemPayloadSchema, CartItemSchema, CheckoutResponseSchema } from '../chunk-7PAQR3VC.mjs';
import '../chunk-BRVIXGUW.mjs';
import '../chunk-NWUEWUX2.mjs';
import '../chunk-7BM56JET.mjs';
import '../chunk-TD3AY34U.mjs';
import '../chunk-AMZXALF6.mjs';
import '../chunk-3G6RQLXK.mjs';
import { describe, it, expect, beforeEach, afterEach } from 'vitest';

var PLACEHOLDER_PHRASES = [
  "lorem ipsum",
  "todo",
  "fixme",
  "placeholder",
  "your business name",
  "your store"
];
function createBrandSuite(opts) {
  describe(opts.label ?? "brand schema", () => {
    it("conforms to the Cimplify brand contract", () => {
      expect(() => assertBrand(opts.brand)).not.toThrow();
    });
    it("declares a known mock seed", () => {
      const b = opts.brand;
      expect(SeedNameSchema.safeParse(b.mock?.seed).success).toBe(true);
    });
    it("has no placeholder copy left in", () => {
      const offenders = [];
      const walk = (node, path) => {
        if (typeof node === "string") {
          const lower = node.toLowerCase();
          for (const phrase of PLACEHOLDER_PHRASES) {
            if (lower.includes(phrase)) offenders.push({ path, phrase, value: node });
          }
          return;
        }
        if (Array.isArray(node)) {
          for (let i = 0; i < node.length; i++) walk(node[i], `${path}[${i}]`);
          return;
        }
        if (node && typeof node === "object") {
          for (const [k, v] of Object.entries(node)) walk(v, path ? `${path}.${k}` : k);
        }
      };
      walk(opts.brand, "");
      if (offenders.length > 0) {
        const msg = offenders.map((o) => `  \u2022 ${o.path}: "${o.value}" contains "${o.phrase}"`).join("\n");
        throw new Error(`brand contains placeholder copy:
${msg}`);
      }
    });
    it("uses the bus_ businessId convention", () => {
      const b = opts.brand;
      expect(b.mock?.businessId).toMatch(/^bus_/);
    });
    it("zod-parses cleanly", () => {
      const result = BrandSchema.safeParse(opts.brand);
      if (!result.success) {
        throw new Error(
          "Brand schema violations:\n" + result.error.issues.map((i) => `  \u2022 brand.${i.path.join(".")}: ${i.message}`).join("\n")
        );
      }
      expect(result.success).toBe(true);
    });
    opts.extend?.(it);
  });
}
function createCartFlowSuite(opts = {}) {
  describe(opts.label ?? "cart flow against in-process mock", () => {
    let h;
    beforeEach(() => {
      h = createTestClient(opts);
    });
    afterEach(() => h.dispose());
    it("starts with an empty cart matching the canonical shape", async () => {
      const res = await h.client.cart.get();
      expect(res.ok).toBe(true);
      if (!res.ok) return;
      expect(() => assertCart(res.value)).not.toThrow();
      expect(res.value.items).toHaveLength(0);
    });
    it("adds the first product, persists it, and returns a shape-valid cart", async () => {
      const { product, variantId } = await fixtures.addFirstProduct(h.client);
      expect(product.id).toBeTruthy();
      const get = await h.client.cart.get();
      expect(get.ok).toBe(true);
      if (!get.ok) return;
      expect(() => assertCart(get.value)).not.toThrow();
      expect(get.value.items).toHaveLength(1);
      expect(get.value.items[0]?.item_id).toBe(product.id);
      if (variantId) {
        expect(get.value.items[0]?.variant_id).toBe(variantId);
        const variantInfo = get.value.items[0]?.variant_info;
        expect(variantInfo?.display_attributes).toBeDefined();
      }
      expect(parseFloat(String(get.value.pricing.subtotal))).toBeGreaterThan(0);
    });
    it("dedupes by line_key when adding the same product twice", async () => {
      await fixtures.addFirstProduct(h.client);
      await fixtures.addFirstProduct(h.client);
      const res = await h.client.cart.get();
      expect(res.ok).toBe(true);
      if (!res.ok) return;
      expect(res.value.items).toHaveLength(1);
      expect(res.value.items[0]?.quantity).toBe(2);
    });
    it("removes items and zeroes the subtotal", async () => {
      await fixtures.addFirstProduct(h.client);
      const before = await h.client.cart.get();
      if (!before.ok) throw before.error;
      const itemId = before.value.items[0]?.id;
      expect(itemId).toBeTruthy();
      const removed = await h.client.cart.removeItem(itemId);
      expect(removed.ok).toBe(true);
      const after = await h.client.cart.get();
      if (!after.ok) throw after.error;
      expect(after.value.items).toHaveLength(0);
      expect(parseFloat(String(after.value.pricing.subtotal))).toBe(0);
    });
    if (opts.businessId) {
      it("returns the brand's businessId on cart responses", async () => {
        const res = await h.client.cart.get();
        if (!res.ok) throw res.error;
        expect(res.value.business_id).toBe(opts.businessId);
      });
    }
    opts.extend?.({ getHandle: () => h, it });
  });
}
function createContractSuite(opts = {}) {
  describe(opts.label ?? "SDK \u2194 mock contract", () => {
    let h;
    beforeEach(() => {
      h = createTestClient(opts);
    });
    afterEach(() => h.dispose());
    it("AddItemPayload schema accepts a minimal valid body", () => {
      const result = AddItemPayloadSchema.safeParse({ item_id: "prod_x", quantity: 1 });
      expect(result.success).toBe(true);
    });
    it("AddItemPayload schema rejects negative quantity", () => {
      const result = AddItemPayloadSchema.safeParse({ item_id: "prod_x", quantity: -1 });
      expect(result.success).toBe(false);
    });
    it("AddItemPayload schema rejects empty item_id", () => {
      const result = AddItemPayloadSchema.safeParse({ item_id: "", quantity: 1 });
      expect(result.success).toBe(false);
    });
    it("Cart line items returned by the mock match CartItemSchema", async () => {
      const { product } = await fixtures.addFirstProduct(h.client);
      const get = await h.client.cart.get();
      if (!get.ok) throw get.error;
      expect(get.value.items.length).toBeGreaterThan(0);
      for (const item of get.value.items) {
        const result = CartItemSchema.safeParse(item);
        if (!result.success) {
          const issues = result.error.issues.map((i) => `  \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
          throw new Error(`Cart item shape mismatch for ${product.name}:
${issues}`);
        }
        expect(result.success).toBe(true);
      }
    });
    it("CheckoutResponse from the mock includes bill_token", async () => {
      await fixtures.addFirstProduct(h.client);
      const cartRes = await h.client.cart.get();
      if (!cartRes.ok) throw cartRes.error;
      const checkout = await h.client.checkout.process({
        cart_id: cartRes.value.id,
        customer: fixtures.customer(),
        order_type: "delivery",
        payment_method: "mobile_money",
        mobile_money_details: { phone_number: "+233244000000", provider: "mtn" }
      });
      expect(checkout.ok).toBe(true);
      if (!checkout.ok) return;
      const result = CheckoutResponseSchema.safeParse(checkout.value);
      if (!result.success) {
        const issues = result.error.issues.map((i) => `  \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
        throw new Error(`CheckoutResponse shape mismatch:
${issues}`);
      }
      expect(checkout.value.bill_token).toBeTruthy();
      expect(checkout.value.order_id).toBeTruthy();
    });
    opts.extend?.({ getHandle: () => h, it });
  });
}

export { createBrandSuite, createCartFlowSuite, createContractSuite };
