//  @ts-ignore
import reportErrorToRollbar from "./rollbar.mjs";
import provideConfig from "./provideConfig";
import { ResolvedEmbeddableConfig } from "./defineConfig";
import Rollbar from "rollbar";
import * as path from "node:path";
import * as fs from "node:fs/promises";
import { jwtDecode } from "jwt-decode";

const config = {
  applicationEnvironment: "test",
  client: {
    rootDir: "rootDir",
  },
};

vi.mock("node:fs/promises", () => ({
  writeFile: vi.fn(),
  readFile: vi.fn(),
}));

vi.mock("./provideConfig", () => ({
  default: vi.fn(),
}));

vi.mock("jwt-decode", () => ({
  jwtDecode: vi.fn(),
}));

vi.mock("node:path", async () => {
  const actual = await vi.importActual("path");
  return {
    ...actual,
    resolve: vi.fn(),
  };
});

vi.mock("resolvedPath", () => ({
  default: vi.fn(),
  devDependencies: {
    "@embeddable.com/sdk-utils": "0.1.2",
  },
  dependencies: {
    "@embeddable.com/core": "1.0.0",
    "@embeddable.com/sdk-core": "1.2.3",
  },
}));

// Mock rollbar - define everything inside factory to avoid hoisting issues
vi.mock("rollbar", () => {
  const mockInstance = {
    error: vi.fn(),
    configure: vi.fn(),
  };
  // Store on globalThis so tests can access it
  (globalThis as any).__rollbarMockInstance = mockInstance;
  
  // Return a constructor function that returns the same instance
  function RollbarMock() {
    return mockInstance;
  }
  
  return {
    default: RollbarMock,
  };
});

describe("rollbar", () => {
  let rollbarInstance: any;

  beforeEach(() => {
    vi.mocked(provideConfig).mockResolvedValue(
      config as ResolvedEmbeddableConfig,
    );
    vi.mocked(path.resolve).mockReturnValue("resolvedPath");

    vi.mocked(fs.readFile).mockResolvedValue("{}");
    vi.mocked(jwtDecode).mockReturnValue({ sub: "test", iss: "iss" });
    
    // Get the mock instance that will be returned by constructor
    rollbarInstance = (globalThis as any).__rollbarMockInstance;
    rollbarInstance.error.mockClear();
    rollbarInstance.configure.mockClear();
  });

  it("should call Rollbar.error with the error", async () => {
    const error = new Error("test error");
    await reportErrorToRollbar(error);

    expect(rollbarInstance.configure).toHaveBeenCalledWith({
      payload: {
        person: {
          id: "iss@test",
        },
      },
    });

    expect(rollbarInstance.error).toHaveBeenCalledWith(error, {
      custom: {
        code_version: '{"core":"1.0.0","sdk_core":"1.2.3"}',
      },
    });
  });
});
