import { expect } from "vitest";
import { ok, type CommandContext, type QueryContext } from "@tailor-platform/erp-kit/core";

export const commandCtx: CommandContext = {
  actorId: "test-actor",
  permissions: ["purchase:*"],
};

export const queryCtx: QueryContext = {
  actorId: "test-actor",
  permissions: ["purchase:*"],
};

interface OkResult<T> {
  ok: true;
  value: T;
}

interface ErrResult {
  ok: false;
  error: unknown;
}

export function expectErr(
  result: OkResult<unknown> | ErrResult,
  errorClass: abstract new (...args: never[]) => Error,
) {
  expect(result.ok).toBe(false);
  if (!result.ok) {
    expect(result.error).toBeInstanceOf(errorClass);
  }
}

export function expectOk<T>(result: OkResult<T> | ErrResult) {
  expect(result.ok).toBe(true);
  if (!result.ok) {
    throw result.error;
  }
  return result.value;
}

/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/require-await, @typescript-eslint/no-unsafe-assignment */
export function mockBPQueries(
  overrides: { partner?: any; partnerRole?: any; identifications?: any[] } = {},
) {
  return {
    getPartner: async () => ok({ partner: overrides.partner ?? null }),
    getPartnerRole: async () => ok({ partnerRole: overrides.partnerRole ?? null }),
    listPartnerIdentificationsByPartner: async () =>
      ok({ items: overrides.identifications ?? [], hasNextPage: false }),
  };
}

export function mockItemQueries(overrides: { item?: any } = {}) {
  return {
    getItem: async () => ok({ item: overrides.item ?? null }),
  };
}

export function mockUnitQueries(overrides: { unit?: any } = {}) {
  return {
    getUnit: async () => ok({ unit: overrides.unit ?? null }),
  };
}

export function mockInventoryCommands() {
  return {
    createStockMovement: async () =>
      ok({
        stockMovement: {
          id: "stock-movement-1",
          movementType: "GOODS_RECEIPT" as const,
          reasonCode: null,
          status: "DRAFT" as const,
          executedAt: null,
          createdAt: new Date(),
          updatedAt: null,
        },
        stockMoveLines: [] as {
          id: string;
          stockMovementId: string;
          itemId: string;
          quantity: number;
          sourceLocationId: string | null;
          destinationLocationId: string | null;
          lotId: string | null;
          serialNumberId: string | null;
          createdAt: Date;
          updatedAt: Date | null;
        }[],
      }),
  };
}
