/**
 * Testkit for testing dealer BI events.
 *
 * Provides a singleton-style API similar to biTestkit from @wix/bex-core/bi/testkit.
 * Captures dealer reportEvent HTTP calls and provides utilities to assert on events.
 *
 * @example
 * ```typescript
 * import dealerBITestkit from '../test-utils/DealerBIMock';
 *
 * describe('MyComponent', () => {
 *   const setup = () => {
 *     const driver = new MyDriver({
 *       httpMocks: [
 *         // ... other mocks
 *         dealerBITestkit.httpMock,
 *       ],
 *     });
 *     return { driver };
 *   };
 *
 *   it('sends view event', async () => {
 *     setup();
 *     // ... trigger the view event
 *
 *     expect(dealerBITestkit.view.last()).toEqual(
 *       expect.objectContaining({
 *         offerId: 'offer-1',
 *       }),
 *     );
 *   });
 * });
 * ```
 */

import { whenRequest } from '@wix/yoshi-flow-bm/testkit/http-client';
import { reportEvent } from '@wix/bex-utils/@wix/ambassador-dealer-v1-offer-event/http';
import type { AnyScenario } from '@wix/http-client-testkit';

// Re-export EventType for convenience
export { EventType } from '@wix/bex-utils/@wix/ambassador-dealer-v1-offer-event/types';

interface ReportEventData {
  event?: {
    type?: string;
    offerId?: string;
    realEstateId?: string;
    [key: string]: unknown;
  };
  [key: string]: unknown;
}

interface EventTypeAccessor {
  /** Get all events of this type */
  all: () => ReportEventData[];
  /** Get the last event of this type */
  last: () => ReportEventData | undefined;
  /** Get event count of this type */
  count: () => number;
}

interface DealerBITestkit {
  /** The HTTP mock - add this to your driver's httpMocks array */
  httpMock: AnyScenario;

  /** Access VIEW events */
  view: EventTypeAccessor;
  /** Access CLICK events */
  click: EventTypeAccessor;

  /** Get all captured events (any type) */
  all: () => ReportEventData[];
  /** Get the last captured event (any type) */
  last: () => ReportEventData | undefined;
  /** Clear all captured events - call in beforeEach for test isolation */
  clear: () => void;
}

// Singleton spy to capture all events
const eventsSpy = jest.fn();

// Create HTTP mock once
const httpMock = whenRequest(reportEvent)
  .reply(async (data) => {
    eventsSpy(data);
    return { status: 200, data: {} };
  })
  .persist() as AnyScenario;

const _getAllEventsOfType = (type?: string): ReportEventData[] =>
  type
    ? eventsSpy.mock.calls
        .filter((call) => call[0]?.event?.type === type)
        .map((call) => call[0])
    : eventsSpy.mock.calls.map((call) => call[0]);

const createEventTypeAccessor = (type: string): EventTypeAccessor => ({
  all: () => _getAllEventsOfType(type),
  last: () => {
    const events = _getAllEventsOfType(type);
    return events.length > 0 ? events[events.length - 1] : undefined;
  },
  count: () => _getAllEventsOfType(type).length,
});

const dealerBITestkit: DealerBITestkit = {
  httpMock,

  view: createEventTypeAccessor('VIEW'),
  click: createEventTypeAccessor('CLICK'),

  all: _getAllEventsOfType,
  last: () => {
    const events = _getAllEventsOfType();
    return events.length > 0 ? events[events.length - 1] : undefined;
  },
  clear: () => eventsSpy.mockClear(),
};

export default dealerBITestkit;

// Also export named for flexibility
export { dealerBITestkit };
