import { describe, it, expect, vi, beforeEach } from 'vitest';

// Mock apiClient
vi.mock('../client', () => ({
  default: {
    get: vi.fn(),
    post: vi.fn(),
  },
}));

import {
  getSandboxStatus,
  toggleSandboxMode,
  resetSandboxData,
} from '../sandbox';
import apiClient from '../client';

describe('sandbox API', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('getSandboxStatus', () => {
    it('fetches sandbox status from API', async () => {
      const mockStatus = {
        sandbox_mode: true,
        sandbox_enabled: true,
        sandbox_schema: 'test_business_sandbox',
      };
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockStatus });

      const result = await getSandboxStatus();

      expect(apiClient.get).toHaveBeenCalledWith('/sandbox/status/');
      expect(result).toEqual(mockStatus);
    });

    it('returns sandbox disabled status', async () => {
      const mockStatus = {
        sandbox_mode: false,
        sandbox_enabled: false,
        sandbox_schema: null,
      };
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockStatus });

      const result = await getSandboxStatus();

      expect(result.sandbox_mode).toBe(false);
      expect(result.sandbox_enabled).toBe(false);
      expect(result.sandbox_schema).toBeNull();
    });

    it('returns sandbox enabled but not active', async () => {
      const mockStatus = {
        sandbox_mode: false,
        sandbox_enabled: true,
        sandbox_schema: 'test_business_sandbox',
      };
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockStatus });

      const result = await getSandboxStatus();

      expect(result.sandbox_mode).toBe(false);
      expect(result.sandbox_enabled).toBe(true);
      expect(result.sandbox_schema).toBe('test_business_sandbox');
    });
  });

  describe('toggleSandboxMode', () => {
    it('enables sandbox mode', async () => {
      const mockResponse = {
        data: {
          sandbox_mode: true,
          message: 'Sandbox mode enabled',
        },
      };
      vi.mocked(apiClient.post).mockResolvedValue(mockResponse);

      const result = await toggleSandboxMode(true);

      expect(apiClient.post).toHaveBeenCalledWith('/sandbox/toggle/', {
        sandbox: true,
      });
      expect(result.sandbox_mode).toBe(true);
      expect(result.message).toBe('Sandbox mode enabled');
    });

    it('disables sandbox mode', async () => {
      const mockResponse = {
        data: {
          sandbox_mode: false,
          message: 'Sandbox mode disabled',
        },
      };
      vi.mocked(apiClient.post).mockResolvedValue(mockResponse);

      const result = await toggleSandboxMode(false);

      expect(apiClient.post).toHaveBeenCalledWith('/sandbox/toggle/', {
        sandbox: false,
      });
      expect(result.sandbox_mode).toBe(false);
      expect(result.message).toBe('Sandbox mode disabled');
    });

    it('handles toggle with true parameter', async () => {
      const mockResponse = {
        data: {
          sandbox_mode: true,
          message: 'Switched to test data',
        },
      };
      vi.mocked(apiClient.post).mockResolvedValue(mockResponse);

      await toggleSandboxMode(true);

      expect(apiClient.post).toHaveBeenCalledWith('/sandbox/toggle/', {
        sandbox: true,
      });
    });

    it('handles toggle with false parameter', async () => {
      const mockResponse = {
        data: {
          sandbox_mode: false,
          message: 'Switched to live data',
        },
      };
      vi.mocked(apiClient.post).mockResolvedValue(mockResponse);

      await toggleSandboxMode(false);

      expect(apiClient.post).toHaveBeenCalledWith('/sandbox/toggle/', {
        sandbox: false,
      });
    });
  });

  describe('resetSandboxData', () => {
    it('resets sandbox data successfully', async () => {
      const mockResponse = {
        data: {
          message: 'Sandbox data reset successfully',
          sandbox_schema: 'test_business_sandbox',
        },
      };
      vi.mocked(apiClient.post).mockResolvedValue(mockResponse);

      const result = await resetSandboxData();

      expect(apiClient.post).toHaveBeenCalledWith('/sandbox/reset/');
      expect(result.message).toBe('Sandbox data reset successfully');
      expect(result.sandbox_schema).toBe('test_business_sandbox');
    });

    it('returns schema name after reset', async () => {
      const mockResponse = {
        data: {
          message: 'Data reset complete',
          sandbox_schema: 'my_company_sandbox',
        },
      };
      vi.mocked(apiClient.post).mockResolvedValue(mockResponse);

      const result = await resetSandboxData();

      expect(result.sandbox_schema).toBe('my_company_sandbox');
    });

    it('calls reset endpoint without parameters', async () => {
      const mockResponse = {
        data: {
          message: 'Reset successful',
          sandbox_schema: 'test_sandbox',
        },
      };
      vi.mocked(apiClient.post).mockResolvedValue(mockResponse);

      await resetSandboxData();

      expect(apiClient.post).toHaveBeenCalledWith('/sandbox/reset/');
      expect(apiClient.post).toHaveBeenCalledTimes(1);
    });
  });

  describe('error handling', () => {
    it('propagates errors from getSandboxStatus', async () => {
      const error = new Error('Network error');
      vi.mocked(apiClient.get).mockRejectedValue(error);

      await expect(getSandboxStatus()).rejects.toThrow('Network error');
    });

    it('propagates errors from toggleSandboxMode', async () => {
      const error = new Error('Unauthorized');
      vi.mocked(apiClient.post).mockRejectedValue(error);

      await expect(toggleSandboxMode(true)).rejects.toThrow('Unauthorized');
    });

    it('propagates errors from resetSandboxData', async () => {
      const error = new Error('Forbidden');
      vi.mocked(apiClient.post).mockRejectedValue(error);

      await expect(resetSandboxData()).rejects.toThrow('Forbidden');
    });
  });
});
