import { APIRequestContext } from '@playwright/test';

export interface TestUser {
  username: string;
  nickname?: string;
  email: string;
  phone: string;
  password: string;
  roleIds?: number[];
}

export interface TestRole {
  roleName: string;
  roleKey: string;
  roleSort: string;
  status: string;
  remark?: string;
}

export class TestDataManager {
  private static testData: Map<string, any> = new Map();
  private static apiBaseUrl: string;

  static initialize(apiBaseUrl: string = 'http://localhost:8084') {
    this.apiBaseUrl = apiBaseUrl;
  }

  static generateTimestamp(): string {
    return Date.now().toString();
  }

  static generateTestUser(override?: Partial<TestUser>): TestUser {
    const timestamp = this.generateTimestamp();
    return {
      username: `testuser_${timestamp}`,
      nickname: `测试用户${timestamp}`,
      email: `test_${timestamp}@example.com`,
      phone: '13800138000',
      password: 'Test123!@#',
      roleIds: [],
      ...override,
    };
  }

  static generateTestRole(override?: Partial<TestRole>): TestRole {
    const timestamp = this.generateTimestamp();
    return {
      roleName: `测试角色_${timestamp}`,
      roleKey: `test_role_${timestamp}`,
      roleSort: '1',
      status: '1',
      remark: `测试角色备注_${timestamp}`,
      ...override,
    };
  }

  static async createTestUser(request: APIRequestContext, userData: TestUser): Promise<any> {
    const response = await request.post(`${this.apiBaseUrl}/api/users`, {
      data: userData,
    });
    
    if (!response.ok()) {
      throw new Error(`Failed to create test user: ${await response.text()}`);
    }
    
    const result = await response.json();
    const userId = result.data?.id || result.id;
    
    this.testData.set(`user_${userData.username}`, {
      id: userId,
      ...userData,
    });
    
    return result;
  }

  static async createTestRole(request: APIRequestContext, roleData: TestRole): Promise<any> {
    const response = await request.post(`${this.apiBaseUrl}/api/roles`, {
      data: roleData,
    });
    
    if (!response.ok()) {
      throw new Error(`Failed to create test role: ${await response.text()}`);
    }
    
    const result = await response.json();
    const roleId = result.data?.id || result.id;
    
    this.testData.set(`role_${roleData.roleKey}`, {
      id: roleId,
      ...roleData,
    });
    
    return result;
  }

  static async deleteTestUser(request: APIRequestContext, username: string): Promise<void> {
    const userData = this.testData.get(`user_${username}`);
    if (!userData || !userData.id) {
      return;
    }
    
    const response = await request.delete(`${this.apiBaseUrl}/api/users/${userData.id}`);
    if (!response.ok()) {
      console.warn(`Failed to delete test user ${username}: ${await response.text()}`);
    }
    
    this.testData.delete(`user_${username}`);
  }

  static async deleteTestRole(request: APIRequestContext, roleKey: string): Promise<void> {
    const roleData = this.testData.get(`role_${roleKey}`);
    if (!roleData || !roleData.id) {
      return;
    }
    
    const response = await request.delete(`${this.apiBaseUrl}/api/roles/${roleData.id}`);
    if (!response.ok()) {
      console.warn(`Failed to delete test role ${roleKey}: ${await response.text()}`);
    }
    
    this.testData.delete(`role_${roleKey}`);
  }

  static async cleanupTestData(request: APIRequestContext): Promise<void> {
    const cleanupPromises: Promise<void>[] = [];
    
    const entries = Array.from(this.testData.entries());
    for (const [key, data] of entries) {
      if (key.startsWith('user_')) {
        cleanupPromises.push(this.deleteTestUser(request, data.username));
      } else if (key.startsWith('role_')) {
        cleanupPromises.push(this.deleteTestRole(request, data.roleKey));
      }
    }
    
    await Promise.allSettled(cleanupPromises);
    this.testData.clear();
  }

  static getTestData(key: string): any {
    return this.testData.get(key);
  }

  static getAllTestData(): Map<string, any> {
    return new Map(this.testData);
  }

  static clearTestData(): void {
    this.testData.clear();
  }
}

export class DatabaseHelper {
  private static apiBaseUrl: string;

  static initialize(apiBaseUrl: string = 'http://localhost:8084') {
    this.apiBaseUrl = apiBaseUrl;
  }

  static async resetDatabase(request: APIRequestContext): Promise<void> {
    const response = await request.post(`${this.apiBaseUrl}/api/test/reset-database`);
    if (!response.ok()) {
      throw new Error(`Failed to reset database: ${await response.text()}`);
    }
  }

  static async clearTestData(request: APIRequestContext): Promise<void> {
    const response = await request.post(`${this.apiBaseUrl}/api/test/clear-test-data`);
    if (!response.ok()) {
      throw new Error(`Failed to clear test data: ${await response.text()}`);
    }
  }

  static async seedTestData(request: APIRequestContext): Promise<void> {
    const response = await request.post(`${this.apiBaseUrl}/api/test/seed-test-data`);
    if (!response.ok()) {
      throw new Error(`Failed to seed test data: ${await response.text()}`);
    }
  }
}
