/**
 * Fully-Typed Contract Client Tests
 *
 * Demonstrates that:
 * 1. Response types are fully inferred from schema
 * 2. POST body types are fully inferred from schema
 * 3. Mock adapter returns parsed, typed data from fixtures
 *
 * If this file compiles, type inference is working correctly!
 */

import { describe, it, expect } from 'vitest';
import { createClient } from '@abapify/speci/rest';
import { fixtures } from '@abapify/adt-fixtures';
import { createMockAdapter } from './contracts/base/mock-adapter';

// Import contracts - using actual generated contracts
import { transportrequestsContract } from '../src/generated/adt/sap/bc/adt/cts/transportrequests';
import { worklistsContract } from '../src/generated/adt/sap/bc/adt/atc/worklists';
import { packagesContract } from '../src/generated/adt/sap/bc/adt/packages';

// =============================================================================
// Type-Safe GET Response Tests
// =============================================================================

describe('Typed Client - GET Response', () => {
  it('transport request response is fully typed', async () => {
    const adapter = createMockAdapter([
      {
        method: 'GET',
        path: /\/sap\/bc\/adt\/cts\/transportrequests/,
        response: { status: 200, body: fixtures.transport.single },
      },
    ]);

    const client = createClient(transportrequestsContract, {
      baseUrl: '',
      adapter,
    });

    // Call the typed client - using actual method name from contract
    // transportrequestsContract.transportrequests(params?) is the GET method
    const result = await client.transportrequests();

    // ✅ TYPE CHECK: result should be typed as the parsed transport schema
    // If this compiles, the response type is correctly inferred!
    expect(result).toBeDefined();

    // Access nested properties - these would fail compilation if types were wrong
    // The exact structure depends on the schema, but we verify it's an object
    expect(typeof result).toBe('object');
  });

  it('package response is fully typed', async () => {
    const adapter = createMockAdapter([
      {
        method: 'GET',
        path: /\/sap\/bc\/adt\/packages\//,
        response: { status: 200, body: fixtures.packages.tmp },
      },
    ]);

    const client = createClient(packagesContract, {
      baseUrl: '',
      adapter,
    });

    // packagesContract.properties(object_name, params?) is the GET method
    const result = await client.properties('$TMP');

    // ✅ TYPE CHECK: result is typed
    expect(result).toBeDefined();
    expect(typeof result).toBe('object');
  });

  it('atc worklist response is fully typed', async () => {
    const adapter = createMockAdapter([
      {
        method: 'GET',
        path: /\/sap\/bc\/adt\/atc\/worklists\//,
        response: { status: 200, body: fixtures.atc.worklist },
      },
    ]);

    const client = createClient(worklistsContract, {
      baseUrl: '',
      adapter,
    });

    // worklistsContract.get(worklistId, params?) is the GET method
    const result = await client.get('WL123');

    // ✅ TYPE CHECK: result is typed as worklist schema
    expect(result).toBeDefined();
    expect(typeof result).toBe('object');
  });
});

// =============================================================================
// Type Inference Compile-Time Verification
// =============================================================================

describe('Typed Client - Compile-Time Type Safety', () => {
  /**
   * This test verifies type inference at compile time.
   * The actual assertions are secondary - if this file compiles,
   * the types are correctly inferred.
   */
  it('demonstrates type inference works', async () => {
    const adapter = createMockAdapter([
      {
        path: /./,
        response: { status: 200, body: fixtures.transport.single },
      },
    ]);

    const client = createClient(transportrequestsContract, {
      baseUrl: '',
      adapter,
    });

    // ✅ COMPILE-TIME CHECK: These method signatures are typed
    // Contract methods match the actual generated contract structure:
    // - client.transportrequests(params?) - list transports
    // - client.attribute(name, params?) - get attribute valuehelp
    // - client.target(name, params?) - get target valuehelp

    // The fact that this compiles proves:
    // 1. Contract methods are correctly typed
    // 2. Parameters are inferred from contract definition
    // 3. Return types are inferred from response schemas

    expect(typeof client.transportrequests).toBe('function');
    expect(typeof client.attribute).toBe('function');
    expect(typeof client.target).toBe('function');
  });
});

// =============================================================================
// Response Schema Parsing Tests
// =============================================================================

describe('Typed Client - Schema Parsing', () => {
  it('parses XML response using schema.parse()', async () => {
    const adapter = createMockAdapter([
      {
        method: 'GET',
        path: /\/sap\/bc\/adt\/cts\/transportrequests/,
        response: { status: 200, body: fixtures.transport.single },
      },
    ]);

    const client = createClient(transportrequestsContract, {
      baseUrl: '',
      adapter,
    });

    const result = await client.transportrequests();

    // The mock adapter uses schema.parse() from the contract's responses
    // So result should be a parsed object, not raw XML
    expect(result).toBeDefined();
    expect(typeof result).toBe('object');

    // Should NOT be a string (raw XML)
    expect(typeof result).not.toBe('string');
  });
});
