/**
 * Copyright IBM Corp. 2024, 2025
 */

jest.mock('../../../src/service/log-wrapper.js', () => ({
  LogWrapper: {
    logWarn: jest.fn(),
    logInfo: jest.fn(),
    logError: jest.fn(),
    logDebug: jest.fn(),
  },
}));

import { HttpClient } from '../../../src/engine/protocol/http-client.js';
import { RestHandler } from '../../../src/engine/protocol/rest-handler.js';
import { VCM } from '../../../src/engine/variable-context-manager/context-manager.js';
import { Request } from '../../../src/schemas/test.schema.js';

describe('Sample testing', () => {
  let mockHttpClient: jest.Mocked<HttpClient>;
  const sessionId = 'restHandlerContext';

  beforeAll(() => {
    VCM.createContext(sessionId).setVariable('id', '1');
  });

  beforeEach(() => {
    mockHttpClient = {
      request: jest.fn(),
    };
  });

  afterEach(() => {});

  it('run sample httprequest', async () => {
    const step: Request = {
      method: 'GET',
      resource: 'data',
      endpoint: 'https://jsonplaceholder.typicode.com/posts/${id}',
      headers: [{ key: 'Accept', value: 'application/json' }],
    };

    const resp = await new RestHandler().execute(step, sessionId);
    expect(resp.data).toStrictEqual({
      userId: 1,
      id: 1,
      title:
        'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
      body: 'quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto',
    });
  });

  it('run sample httprequest for array response', async () => {
    const step: Request = {
      method: 'GET',
      resource: 'data',
      endpoint: 'https://jsonplaceholder.typicode.com/posts/${id}/comments',
      headers: [{ key: 'Accept', value: 'application/json' }],
    };

    const resp = await new RestHandler().execute(step, sessionId);

    expect(resp.data).toStrictEqual([
      {
        postId: 1,
        id: 1,
        name: 'id labore ex et quam laborum',
        email: 'Eliseo@gardner.biz',
        body: 'laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora quo necessitatibus\ndolor quam autem quasi\nreiciendis et nam sapiente accusantium',
      },
      {
        postId: 1,
        id: 2,
        name: 'quo vero reiciendis velit similique earum',
        email: 'Jayne_Kuhic@sydney.com',
        body: 'est natus enim nihil est dolore omnis voluptatem numquam\net omnis occaecati quod ullam at\nvoluptatem error expedita pariatur\nnihil sint nostrum voluptatem reiciendis et',
      },
      {
        postId: 1,
        id: 3,
        name: 'odio adipisci rerum aut animi',
        email: 'Nikita@garfield.biz',
        body: 'quia molestiae reprehenderit quasi aspernatur\naut expedita occaecati aliquam eveniet laudantium\nomnis quibusdam delectus saepe quia accusamus maiores nam est\ncum et ducimus et vero voluptates excepturi deleniti ratione',
      },
      {
        postId: 1,
        id: 4,
        name: 'alias odio sit',
        email: 'Lew@alysha.tv',
        body: 'non et atque\noccaecati deserunt quas accusantium unde odit nobis qui voluptatem\nquia voluptas consequuntur itaque dolor\net qui rerum deleniti ut occaecati',
      },
      {
        postId: 1,
        id: 5,
        name: 'vero eaque aliquid doloribus et culpa',
        email: 'Hayden@althea.biz',
        body: 'harum non quasi et ratione\ntempore iure ex voluptates in ratione\nharum architecto fugit inventore cupiditate\nvoluptates magni quo et',
      },
    ]);
  });

  it('should throw error if HTTP url is missing', async () => {
    const step: Request = { method: 'GET', resource: 'data' };
    const handler = new RestHandler(mockHttpClient);
    await expect(handler.execute(step, sessionId)).rejects.toThrow(
      'Endpoint is required',
    );
  });

  it('should interpolate variables from context', async () => {
    const step: Request = {
      method: 'GET',
      resource: 'data',
      endpoint: 'https://api.com/users/${id}',
    };
    const handler = new RestHandler(mockHttpClient);

    mockHttpClient.request.mockResolvedValue({ status: 200 });

    await handler.execute(step, sessionId);
    const mockCall = mockHttpClient.request.mock.calls[0];
    expect(mockCall[0]).toEqual({
      url: 'https://api.com/users/1',
      method: 'GET',
      resource: 'data',
      data: undefined,
      headers: {},
      params: {},
      validateSSL: undefined,
    });
  });

  it('should interpolate arrays correctly', async () => {
    const step: Request = {
      method: 'POST',
      resource: 'data',
      endpoint: 'https://api.com/data',
      payload: {
        raw: {
          json: '["${id}", "${id}"]',
        },
      },
    };
    const handler = new RestHandler(mockHttpClient);
    mockHttpClient.request.mockResolvedValue({ status: 200 });

    await handler.execute(step, sessionId);

    const mockCall = mockHttpClient.request.mock.calls[0];
    expect(mockCall[0]).toEqual({
      data: '["1", "1"]',
      headers: {},
      method: 'POST',
      params: {},
      resource: 'data',
      url: 'https://api.com/data',
      validateSSL: undefined,
    });
  });
});
