import { describe, it, expect, beforeEach, vi } from 'vitest';
import { TestDataManager, getTestDataManager } from '../test-data-manager';

global.fetch = vi.fn();

describe('TestDataManager', () => {
  let manager: TestDataManager;

  beforeEach(() => {
    manager = TestDataManager.getInstance();
    manager.clearTracking();
    vi.clearAllMocks();
  });

  it('should be a singleton', () => {
    const instance1 = getTestDataManager();
    const instance2 = getTestDataManager();
    expect(instance1).toBe(instance2);
  });

  it('should create user and track it', async () => {
    const mockUserId = 'user-123';
    (global.fetch as any).mockResolvedValueOnce({
      ok: true,
      json: async () => ({ data: { id: mockUserId } })
    });

    const userData = {
      username: 'testuser',
      password: 'Test@123',
      email: 'test@example.com',
    };

    const result = await manager.createUser(userData);

    expect(result.id).toBe(mockUserId);
    expect(result.type).toBe('user');
    expect(result.data.username).toBe('testuser');
    expect(manager.getCreatedData('user')).toHaveLength(1);
  });

  it('should create role and track it', async () => {
    const mockRoleId = 'role-456';
    (global.fetch as any).mockResolvedValueOnce({
      ok: true,
      json: async () => ({ data: { id: mockRoleId } })
    });

    const roleData = {
      roleName: '测试角色',
      roleKey: 'test_role',
    };

    const result = await manager.createRole(roleData);

    expect(result.id).toBe(mockRoleId);
    expect(result.type).toBe('role');
    expect(manager.getCreatedData('role')).toHaveLength(1);
  });

  it('should cleanup created data', async () => {
    (global.fetch as any)
      .mockResolvedValueOnce({
        ok: true,
        json: async () => ({ data: { id: 'user-1' } })
      })
      .mockResolvedValueOnce({
        ok: true,
        json: async () => ({ data: { id: 'user-2' } })
      })
      .mockResolvedValueOnce({ ok: true })
      .mockResolvedValueOnce({ ok: true });

    await manager.createUser({ username: 'user1', password: 'Test@123', email: 'user1@test.com' });
    await manager.createUser({ username: 'user2', password: 'Test@123', email: 'user2@test.com' });

    expect(manager.getCreatedData('user')).toHaveLength(2);

    await manager.cleanup('user');

    expect(manager.getCreatedData('user')).toHaveLength(0);
    expect(global.fetch).toHaveBeenCalledTimes(4); // 2 creates + 2 deletes
  });

  it('should cleanup all data types when no type specified', async () => {
    (global.fetch as any)
      .mockResolvedValueOnce({
        ok: true,
        json: async () => ({ data: { id: 'user-1' } })
      })
      .mockResolvedValueOnce({
        ok: true,
        json: async () => ({ data: { id: 'role-1' } })
      })
      .mockResolvedValueOnce({ ok: true })
      .mockResolvedValueOnce({ ok: true });

    await manager.createUser({ username: 'user1', password: 'Test@123', email: 'user1@test.com' });
    await manager.createRole({ roleName: '角色1', roleKey: 'role1' });

    await manager.cleanup();

    expect(manager.getCreatedData('user')).toHaveLength(0);
    expect(manager.getCreatedData('role')).toHaveLength(0);
  });

  it('should throw error on creation failure', async () => {
    (global.fetch as any).mockResolvedValueOnce({
      ok: false,
      statusText: 'Bad Request'
    });

    await expect(
      manager.createUser({ username: 'test', password: 'Test@123', email: 'test@test.com' })
    ).rejects.toThrow('Failed to create user');
  });
});
