import axios, { AxiosInstance } from 'axios';
import { WatchtowerSDK } from '../../index';
import { APIKey, AppAPIKey, TenantAPIKey, RolledAPIKey } from '../../endpoints/apikey/types';

// Mock axios
jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;

describe('APIKeyEndpoint', () => {
  const baseURL = 'https://watchtower-go-supabase-822142465400.europe-west1.run.app';
  let sdk: WatchtowerSDK;
  let mockAxiosInstance: jest.Mocked<AxiosInstance>;

  beforeEach(() => {
    // Clear all mocks before each test
    jest.clearAllMocks();
    
    // Create mock axios instance
    mockAxiosInstance = {
      get: jest.fn(),
      post: jest.fn(),
      put: jest.fn(),
      delete: jest.fn(),
    } as unknown as jest.Mocked<AxiosInstance>;

    // Mock axios.create to return our mock instance
    mockedAxios.create.mockReturnValue(mockAxiosInstance);
    
    // Create a new SDK instance for each test
    sdk = new WatchtowerSDK(baseURL);
  });

  describe('createOrganization', () => {
    const mockOrgResponse: APIKey = {
      key: 'wt_ORG_abc123',
      type: 'organization',
      organization_id: 'org_123',
      name: 'Test Org',
      status: 'active',
      created_at: '2024-03-13T12:00:00Z',
      updated_at: '2024-03-13T12:00:00Z'
    };

    it('should create an organization and return API key', async () => {
      mockAxiosInstance.post.mockResolvedValue({ data: mockOrgResponse });

      const response = await sdk.apikey.createOrganization({
        client_email: 'noah@sjursen.digital',
        organization_name: 'Test Org'
      });

      expect(response).toEqual(mockOrgResponse);
      expect(mockAxiosInstance.post).toHaveBeenCalledWith('/org', {
        client_email: 'noah@sjursen.digital',
        organization_name: 'Test Org'
      }, undefined);
    });
  });

  describe('createApp', () => {
    const mockAppResponse: AppAPIKey = {
      key: 'wt_APP_xyz789',
      type: 'app',
      organization_id: 'org_123',
      app_id: 'app_456',
      name: 'Test App',
      status: 'active',
      created_at: '2024-03-13T12:00:00Z',
      updated_at: '2024-03-13T12:00:00Z'
    };

    it('should create an app and return API key', async () => {
      mockAxiosInstance.post.mockResolvedValue({ data: mockAppResponse });

      const response = await sdk.apikey.createApp({
        organization_apikey: 'wt_ORG_abc123',
        app_name: 'Test App',
        tenancy_model: 'single'
      });

      expect(response).toEqual(mockAppResponse);
      expect(mockAxiosInstance.post).toHaveBeenCalledWith('/app', {
        organization_apikey: 'wt_ORG_abc123',
        app_name: 'Test App',
        tenancy_model: 'single'
      }, undefined);
    });
  });

  describe('createTenant', () => {
    const mockTenantResponse: TenantAPIKey = {
      key: 'wt_TNT_def456',
      type: 'tenant',
      organization_id: 'org_123',
      app_id: 'app_456',
      tenant_id: 'tenant_789',
      name: 'Test Tenant',
      status: 'active',
      created_at: '2024-03-13T12:00:00Z',
      updated_at: '2024-03-13T12:00:00Z'
    };

    it('should create a tenant and return API key', async () => {
      mockAxiosInstance.post.mockResolvedValue({ data: mockTenantResponse });

      const response = await sdk.apikey.createTenant({
        organization_apikey: 'wt_ORG_abc123',
        app_apikey: 'wt_APP_xyz789',
        client_email: 'noah@sjursen.digital'
      });

      expect(response).toEqual(mockTenantResponse);
      expect(mockAxiosInstance.post).toHaveBeenCalledWith('/tenant', {
        organization_apikey: 'wt_ORG_abc123',
        app_apikey: 'wt_APP_xyz789',
        client_email: 'noah@sjursen.digital'
      }, undefined);
    });
  });

  describe('rollAPIKey', () => {
    const mockRolledResponse: RolledAPIKey = {
      key: 'wt_ORG_new123',
      type: 'organization',
      organization_id: 'org_123',
      name: 'Test Org',
      status: 'active',
      created_at: '2024-03-13T12:00:00Z',
      updated_at: '2024-03-13T12:00:00Z'
    };

    it('should roll an API key and return new key', async () => {
      mockAxiosInstance.post.mockResolvedValue({ data: mockRolledResponse });

      const response = await sdk.apikey.rollAPIKey({
        current_apikey: 'wt_ORG_abc123',
        type: 'organization'
      });

      expect(response).toEqual(mockRolledResponse);
      expect(mockAxiosInstance.post).toHaveBeenCalledWith('/roll', {
        current_apikey: 'wt_ORG_abc123',
        type: 'organization'
      }, undefined);
    });

    it('should handle error responses', async () => {
      mockAxiosInstance.post.mockRejectedValue(new Error('Invalid API key'));

      await expect(sdk.apikey.rollAPIKey({
        current_apikey: 'invalid_key',
        type: 'organization'
      })).rejects.toThrow('Invalid API key');
    });
  });
}); 