import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get_it/get_it.dart';
import 'package:superport/data/datasources/remote/api_client.dart';
import 'package:superport/models/company_model.dart';
import 'package:superport/models/warehouse_location_model.dart';
import 'package:superport/services/auth_service.dart';
import 'package:superport/data/models/auth/login_request.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/services/warehouse_service.dart';
import 'package:superport/services/equipment_service.dart';
import 'package:superport/services/license_service.dart';
import 'package:superport/services/user_service.dart';
import '../../framework/core/screen_test_framework.dart';
import '../../framework/models/test_models.dart';
import '../../framework/models/report_models.dart' as report_models;
import '../../framework/models/error_models.dart';
import 'package:dio/dio.dart';

/// 모든 화면 테스트의 기본 클래스
/// 
/// 이 클래스는 다음과 같은 기능을 제공합니다:
/// - 공통 CRUD 테스트 패턴의 표준화된 구현
/// - 에러 자동 진단 및 수정 플로우
/// - 테스트 데이터 자동 생성/정리
/// - 병렬 테스트 실행을 위한 격리 보장
/// - 화면별 특수 기능 테스트를 위한 확장 포인트
abstract class BaseScreenTest extends ScreenTestFramework {
  final ApiClient apiClient;
  final GetIt getIt;
  
  // 테스트 격리를 위한 고유 식별자
  late final String testSessionId;
  
  // 병렬 실행을 위한 잠금 메커니즘
  static final Map<String, Completer<void>> _resourceLocks = {};
  
  // 자동 재시도 설정
  static const int maxRetryAttempts = 3;
  static const Duration retryDelay = Duration(seconds: 1);
  
  BaseScreenTest({
    required this.apiClient,
    required this.getIt,
    required super.testContext,
    required super.errorDiagnostics,
    required super.autoFixer,
    required super.dataGenerator,
    required super.reportCollector,
  }) {
    // 테스트 세션 ID 생성 (병렬 실행 시 격리 보장)
    testSessionId = '${getScreenMetadata().screenName}_${DateTime.now().millisecondsSinceEpoch}';
  }
  
  /// 화면 메타데이터 가져오기
  ScreenMetadata getScreenMetadata();
  
  /// 서비스 초기화
  Future<void> initializeServices();
  
  /// 테스트 환경 설정
  Future<void> setupTestEnvironment() async {
    _log('테스트 환경 설정 시작 (세션: $testSessionId)');
    
    try {
      // 서비스 초기화
      await initializeServices();
      
      // 인증 확인 (재시도 로직 포함)
      await _retryWithBackoff(
        () => _ensureAuthenticated(),
        '인증 확인',
      );
      
      // 기본 데이터 설정
      await _setupBaseData();
      
      // 화면별 추가 설정
      await performAdditionalSetup();
      
      _log('테스트 환경 설정 완료');
    } catch (e) {
      _log('테스트 환경 설정 실패: $e');
      throw TestSetupError(
        message: '테스트 환경 설정 실패',
        details: {'error': e.toString(), 'sessionId': testSessionId},
      );
    }
  }
  
  /// 테스트 환경 정리
  Future<void> teardownTestEnvironment() async {
    _log('테스트 환경 정리 시작');
    
    try {
      // 화면별 추가 정리
      await performAdditionalCleanup();
      
      // 생성된 데이터 정리 (역순으로 삭제)
      await _cleanupTestData();
      
      // 서비스 정리
      await _cleanupServices();
      
      // 잠금 해제
      _releaseAllLocks();
      
      _log('테스트 환경 정리 완료');
    } catch (e) {
      _log('테스트 환경 정리 중 오류 (무시): $e');
    }
  }
  
  /// 테스트 실행
  Future<report_models.TestResult> runTests() async {
    final metadata = getScreenMetadata();
    testContext.currentScreen = metadata.screenName;
    
    final startTime = DateTime.now();
    _log('\n${'=' * 60}');
    _log('${metadata.screenName} 테스트 시작');
    _log('${'=' * 60}\n');
    
    try {
      // 환경 설정
      await setupTestEnvironment();
      
      // 기능 감지
      final features = await detectFeatures(metadata);
      _log('감지된 기능: ${features.map((f) => f.featureName).join(', ')}');
      
      // 테스트 실행
      final result = await executeTests(features);
      
      final duration = DateTime.now().difference(startTime);
      _log('\n테스트 완료 (소요시간: ${duration.inSeconds}초)');
      _log('결과: 총 ${result.totalTests}개, 성공 ${result.passedTests}개, 실패 ${result.failedTests}개\n');
      
      return result;
    } catch (e, stackTrace) {
      _log('테스트 실행 중 치명적 오류: $e');
      _log('스택 트레이스: $stackTrace');
      
      // 오류 리포트 생성
      return report_models.TestResult(
        totalTests: 0,
        passedTests: 0,
        failedTests: 1,
        skippedTests: 0,
        failures: [
          report_models.TestFailure(
            feature: metadata.screenName,
            message: '테스트 실행 중 치명적 오류: $e',
            stackTrace: stackTrace.toString(),
          ),
        ],
      );
    } finally {
      // 환경 정리
      await teardownTestEnvironment();
    }
  }
  
  /// 인증 확인
  Future<void> _ensureAuthenticated() async {
    try {
      final authService = getIt.get<AuthService>();
      final isAuthenticated = await authService.isLoggedIn();
      
      if (!isAuthenticated) {
        // 로그인 시도
        final loginRequest = LoginRequest(
          email: testContext.getConfig('testEmail') ?? 'admin@superport.kr',
          password: testContext.getConfig('testPassword') ?? 'admin123!',
        );
        await authService.login(loginRequest);
      }
    } catch (e) {
      throw TestError(
        message: '인증 실패: $e',
        timestamp: DateTime.now(),
        feature: 'Authentication',
      );
    }
  }
  
  /// 기본 데이터 설정
  Future<void> _setupBaseData() async {
    // 회사 데이터 확인/생성
    await _ensureCompanyExists();
    
    // 창고 데이터 확인/생성
    await _ensureWarehouseExists();
  }
  
  /// 회사 데이터 확인/생성
  Future<void> _ensureCompanyExists() async {
    try {
      final companyService = getIt.get<CompanyService>();
      final companies = await companyService.getCompanies(page: 1, perPage: 1);
      
      if (companies.isEmpty) {
        // 테스트용 회사 생성
        final companyData = await dataGenerator.generate(
          GenerationStrategy(
            dataType: Company,
            fields: [],
            relationships: [],
            constraints: {},
          ),
        );
        
        final company = await companyService.createCompany(companyData.data);
        testContext.setData('testCompanyId', company.id);
      } else {
        testContext.setData('testCompanyId', companies.first.id);
      }
    } catch (e) {
      // 회사 생성은 선택사항이므로 에러 무시
      debugPrint('회사 데이터 설정 실패: $e');
    }
  }
  
  /// 창고 데이터 확인/생성
  Future<void> _ensureWarehouseExists() async {
    try {
      final warehouseService = getIt.get<WarehouseService>();
      final companyId = testContext.getData('testCompanyId');
      
      if (companyId != null) {
        final warehouses = await warehouseService.getWarehouseLocations(
          page: 1,
          perPage: 1,
        );
        
        if (warehouses.isEmpty) {
          // 테스트용 창고 생성
          final warehouseData = await dataGenerator.generate(
            GenerationStrategy(
              dataType: WarehouseLocation,
              fields: [],
              relationships: [],
              constraints: {},
            ),
          );
          
          warehouseData.data['company_id'] = companyId;
          final warehouse = await warehouseService.createWarehouseLocation(warehouseData.data);
          testContext.setData('testWarehouseId', warehouse.id);
        } else {
          testContext.setData('testWarehouseId', warehouses.first.id);
        }
      }
    } catch (e) {
      // 창고 생성은 선택사항이므로 에러 무시
      debugPrint('창고 데이터 설정 실패: $e');
    }
  }
  
  /// 테스트 데이터 정리
  Future<void> _cleanupTestData() async {
    final createdIds = testContext.getAllCreatedResourceIds();
    final resourcesByType = <String, List<String>>{};
    
    // createdIds를 resourceType별로 분류
    for (final id in createdIds) {
      final parts = id.split(':');
      if (parts.length == 2) {
        final resourceType = parts[0];
        final resourceId = parts[1];
        resourcesByType.putIfAbsent(resourceType, () => []).add(resourceId);
      }
    }
    
    for (final entry in resourcesByType.entries) {
      final resourceType = entry.key;
      final ids = entry.value;
      
      for (final id in ids) {
        try {
          await _deleteResource(resourceType, id);
        } catch (e) {
          // 삭제 실패는 무시
          debugPrint('리소스 삭제 실패: $resourceType/$id - $e');
        }
      }
    }
  }
  
  /// 리소스 삭제
  Future<void> _deleteResource(String resourceType, String id) async {
    switch (resourceType) {
      case 'equipment':
        final service = getIt.get<EquipmentService>();
        await service.deleteEquipment(int.parse(id));
        break;
      case 'license':
        final service = getIt.get<LicenseService>();
        await service.deleteLicense(int.parse(id));
        break;
      case 'user':
        final service = getIt.get<UserService>();
        await service.deleteUser(int.parse(id));
        break;
      case 'warehouse':
        final service = getIt.get<WarehouseService>();
        await service.deleteWarehouseLocation(int.parse(id));
        break;
      case 'company':
        final service = getIt.get<CompanyService>();
        await service.deleteCompany(int.parse(id));
        break;
    }
  }
  
  /// 서비스 정리
  Future<void> _cleanupServices() async {
    // 필요시 서비스 정리 로직 추가
  }
  
  /// 공통 CRUD 작업 구현 - Create
  @override
  Future<void> performCreate(TestData data) async {
    _log('[CREATE] 시작: ${getResourceType()}');
    
    try {
      // 생성 전 데이터 검증
      await validateDataBeforeCreate(data);
      
      // 서비스 호출 (재시도 로직 포함)
      final result = await _retryWithBackoff(
        () => performCreateOperation(data),
        'CREATE 작업',
      );
      
      // 생성된 리소스 ID 저장
      final resourceId = extractResourceId(result);
      testContext.addCreatedResourceId(getResourceType(), resourceId.toString());
      testContext.setData('lastCreatedId', resourceId);
      testContext.setData('lastCreatedResource', result);
      
      _log('[CREATE] 성공: ID=$resourceId');
    } catch (e) {
      _log('[CREATE] 실패: $e');
      
      // 에러 자동 진단 및 수정 시도
      final fixed = await _handleCrudError(e, 'CREATE', data);
      if (!fixed) {
        rethrow;
      }
    }
  }
  
  @override
  Future<void> verifyCreate(TestData data) async {
    final lastCreatedId = testContext.getData('lastCreatedId');
    expect(lastCreatedId, isNotNull, reason: '리소스 생성 실패');
    
    // 생성된 리소스 조회하여 검증
    final service = getService();
    final result = await service.getById(lastCreatedId);
    expect(result, isNotNull, reason: '생성된 리소스를 찾을 수 없음');
  }
  
  @override
  Future<void> performRead(TestData data) async {
    _log('[READ] 시작: ${getResourceType()}');
    
    try {
      // 읽기 작업 수행 (재시도 로직 포함)
      final results = await _retryWithBackoff(
        () => performReadOperation(data),
        'READ 작업',
      );
      
      testContext.setData('readResults', results);
      testContext.setData('readCount', results is List ? results.length : 1);
      
      _log('[READ] 성공: ${results is List ? results.length : 1}개 항목');
    } catch (e) {
      _log('[READ] 실패: $e');
      
      // 에러 자동 진단 및 수정 시도
      final fixed = await _handleCrudError(e, 'READ', data);
      if (!fixed) {
        rethrow;
      }
    }
  }
  
  @override
  Future<void> verifyRead(TestData data) async {
    final readResults = testContext.getData('readResults');
    expect(readResults, isNotNull, reason: '목록 조회 실패');
    expect(readResults, isA<List>(), reason: '올바른 목록 형식이 아님');
  }
  
  @override
  Future<void> performUpdate(TestData data) async {
    _log('[UPDATE] 시작: ${getResourceType()}');
    
    try {
      // 업데이트할 리소스 확보
      final resourceId = await _ensureResourceForUpdate(data);
      
      // 업데이트 데이터 준비
      final updateData = await prepareUpdateData(data, resourceId);
      
      // 업데이트 수행 (재시도 로직 포함)
      final result = await _retryWithBackoff(
        () => performUpdateOperation(resourceId, updateData),
        'UPDATE 작업',
      );
      
      testContext.setData('updateResult', result);
      testContext.setData('lastUpdatedId', resourceId);
      
      _log('[UPDATE] 성공: ID=$resourceId');
    } catch (e) {
      _log('[UPDATE] 실패: $e');
      
      // 에러 자동 진단 및 수정 시도
      final fixed = await _handleCrudError(e, 'UPDATE', data);
      if (!fixed) {
        rethrow;
      }
    }
  }
  
  @override
  Future<void> verifyUpdate(TestData data) async {
    final updateResult = testContext.getData('updateResult');
    expect(updateResult, isNotNull, reason: '업데이트 실패');
    
    // 업데이트된 내용 확인
    final lastCreatedId = testContext.getData('lastCreatedId');
    final service = getService();
    final result = await service.getById(lastCreatedId);
    
    expect(result.name, contains('Updated'), reason: '업데이트가 반영되지 않음');
  }
  
  @override
  Future<void> performDelete(TestData data) async {
    _log('[DELETE] 시작: ${getResourceType()}');
    
    try {
      // 삭제할 리소스 확보
      final resourceId = await _ensureResourceForDelete(data);
      
      // 삭제 수행 (재시도 로직 포함)
      await _retryWithBackoff(
        () => performDeleteOperation(resourceId),
        'DELETE 작업',
      );
      
      testContext.setData('deleteCompleted', true);
      testContext.setData('lastDeletedId', resourceId);
      
      // 생성된 리소스 목록에서 제거
      testContext.removeCreatedResourceId(getResourceType(), resourceId.toString());
      
      _log('[DELETE] 성공: ID=$resourceId');
    } catch (e) {
      _log('[DELETE] 실패: $e');
      
      // 에러 자동 진단 및 수정 시도
      final fixed = await _handleCrudError(e, 'DELETE', data);
      if (!fixed) {
        rethrow;
      }
    }
  }
  
  @override
  Future<void> verifyDelete(TestData data) async {
    final deleteCompleted = testContext.getData('deleteCompleted');
    expect(deleteCompleted, isTrue, reason: '삭제 작업이 완료되지 않음');
    
    // 삭제된 리소스 조회 시도
    final lastCreatedId = testContext.getData('lastCreatedId');
    final service = getService();
    
    try {
      await service.getById(lastCreatedId);
      fail('삭제된 리소스가 여전히 존재함');
    } catch (e) {
      // 예상된 에러 - 리소스를 찾을 수 없음
    }
  }
  
  @override
  Future<void> performSearch(TestData data) async {
    // 검색할 데이터 먼저 생성
    await performCreate(data);
    
    final service = getService();
    final searchKeyword = data.data['name']?.toString().split(' ').first ?? 'test';
    
    final results = await service.search(searchKeyword);
    testContext.setData('searchResults', results);
    testContext.setData('searchKeyword', searchKeyword);
  }
  
  @override
  Future<void> verifySearch(TestData data) async {
    final searchResults = testContext.getData('searchResults');
    final searchKeyword = testContext.getData('searchKeyword');
    
    expect(searchResults, isNotNull, reason: '검색 결과가 없음');
    expect(searchResults, isA<List>(), reason: '올바른 검색 결과 형식이 아님');
    
    if (searchResults.isNotEmpty) {
      // 검색 결과가 키워드를 포함하는지 확인
      final firstResult = searchResults.first;
      expect(
        firstResult.toString().toLowerCase(),
        contains(searchKeyword.toLowerCase()),
        reason: '검색 결과가 키워드를 포함하지 않음',
      );
    }
  }
  
  @override
  Future<void> performFilter(TestData data) async {
    final service = getService();
    
    // 필터 조건 설정
    final filters = getDefaultFilters();
    final results = await service.getListWithFilters(filters);
    
    testContext.setData('filterResults', results);
    testContext.setData('appliedFilters', filters);
  }
  
  @override
  Future<void> verifyFilter(TestData data) async {
    final filterResults = testContext.getData('filterResults');
    
    expect(filterResults, isNotNull, reason: '필터 결과가 없음');
    expect(filterResults, isA<List>(), reason: '올바른 필터 결과 형식이 아님');
  }
  
  @override
  Future<void> performPagination(TestData data) async {
    final service = getService();
    
    // 첫 페이지 조회
    final page1 = await service.getList(page: 1, perPage: 5);
    testContext.setData('page1Results', page1);
    
    // 두 번째 페이지 조회
    final page2 = await service.getList(page: 2, perPage: 5);
    testContext.setData('page2Results', page2);
  }
  
  @override
  Future<void> verifyPagination(TestData data) async {
    final page1Results = testContext.getData('page1Results');
    final page2Results = testContext.getData('page2Results');
    
    expect(page1Results, isNotNull, reason: '첫 페이지 결과가 없음');
    expect(page2Results, isNotNull, reason: '두 번째 페이지 결과가 없음');
    
    // 페이지별 결과가 다른지 확인 (데이터가 충분한 경우)
    if (page1Results.isNotEmpty && page2Results.isNotEmpty) {
      expect(
        page1Results.first.id != page2Results.first.id,
        isTrue,
        reason: '페이지네이션이 올바르게 작동하지 않음',
      );
    }
  }
  
  // ===== 하위 클래스에서 구현해야 할 추상 메서드들 =====
  
  /// 서비스 인스턴스 가져오기
  dynamic getService();
  
  /// 리소스 타입 가져오기
  String getResourceType();
  
  /// 기본 필터 설정 가져오기
  Map<String, dynamic> getDefaultFilters();
  
  // ===== CRUD 작업 구현을 위한 추상 메서드들 =====
  
  /// 실제 생성 작업 수행
  Future<dynamic> performCreateOperation(TestData data);
  
  /// 실제 읽기 작업 수행
  Future<dynamic> performReadOperation(TestData data);
  
  /// 실제 업데이트 작업 수행
  Future<dynamic> performUpdateOperation(dynamic resourceId, Map<String, dynamic> updateData);
  
  /// 실제 삭제 작업 수행
  Future<void> performDeleteOperation(dynamic resourceId);
  
  /// 생성된 객체에서 ID 추출
  dynamic extractResourceId(dynamic resource);
  
  // ===== 선택적 구현 메서드들 (기본 구현 제공) =====
  
  /// 생성 전 데이터 검증
  Future<void> validateDataBeforeCreate(TestData data) async {
    // 기본적으로 검증 없음, 필요시 오버라이드
  }
  
  /// 업데이트 데이터 준비
  Future<Map<String, dynamic>> prepareUpdateData(TestData data, dynamic resourceId) async {
    // 기본 구현: 이름에 'Updated' 추가
    final updateData = Map<String, dynamic>.from(data.data);
    if (updateData.containsKey('name')) {
      updateData['name'] = '${updateData['name']} - Updated';
    }
    return updateData;
  }
  
  /// 추가 설정 수행 (setupTestEnvironment에서 호출)
  Future<void> performAdditionalSetup() async {
    // 기본적으로 추가 설정 없음, 필요시 오버라이드
  }
  
  /// 추가 정리 수행 (teardownTestEnvironment에서 호출)
  Future<void> performAdditionalCleanup() async {
    // 기본적으로 추가 정리 없음, 필요시 오버라이드
  }
  
  // ===== 에러 처리 및 자동 수정 메서드들 =====
  
  /// CRUD 작업 중 발생한 에러 처리
  Future<bool> _handleCrudError(dynamic error, String operation, TestData data) async {
    _log('에러 자동 처리 시작: $operation');
    
    try {
      // DioException으로 변환
      final dioError = _convertToDioException(error);
      
      // API 에러로 변환
      final apiError = ApiError(
        originalError: dioError,
        requestUrl: dioError.requestOptions.path,
        requestMethod: dioError.requestOptions.method,
        statusCode: dioError.response?.statusCode,
        message: error.toString(),
        requestBody: data.data,
        timestamp: DateTime.now(),
      );
      
      // 에러 진단
      final diagnosis = await errorDiagnostics.diagnose(apiError);
      _log('진단 결과: ${diagnosis.errorType} - ${diagnosis.description}');
      
      // 자동 수정 시도
      if (diagnosis.confidence > 0.7) {
        final fixResult = await autoFixer.attemptAutoFix(diagnosis);
        
        if (fixResult.success) {
          _log('자동 수정 성공: ${fixResult.executedActions.length}개 액션 적용');
          
          // 수정 액션 적용 (AutoFixResult는 String 액션을 반환)
          // TODO: String 액션을 FixAction으로 변환하거나 별도 처리 필요
          // for (final action in fixResult.executedActions) {
          //   await _applyFixAction(action, data);
          // }
          
          return true;
        } else {
          _log('자동 수정 실패: $fixResult.error');
        }
      }
    } catch (e) {
      _log('에러 처리 중 예외 발생: $e');
    }
    
    return false;
  }
  
  /// 수정 액션 적용
  Future<void> _applyFixAction(FixAction action, TestData data) async {
    switch (action.type) {
      case FixActionType.updateField:
        final field = action.parameters['field'] as String?;
        final value = action.parameters['value'];
        if (field != null && value != null) {
          data.data[field] = value;
          _log('필드 업데이트: $field = $value');
        }
        break;
      case FixActionType.createMissingResource:
        final resourceType = action.parameters['resourceType'] as String?;
        if (resourceType != null) {
          await _createMissingResource(resourceType, action.parameters);
        }
        break;
      case FixActionType.retryWithDelay:
        final delay = action.parameters['delay'] as int? ?? 1000;
        await Future.delayed(Duration(milliseconds: delay));
        _log('${delay}ms 대기 후 재시도');
        break;
      default:
        _log('알 수 없는 수정 액션: $action.type');
    }
  }
  
  /// 누락된 리소스 생성
  Future<void> _createMissingResource(String resourceType, Map<String, dynamic> metadata) async {
    _log('누락된 리소스 자동 생성: $resourceType');
    
    switch (resourceType.toLowerCase()) {
      case 'company':
        await _ensureCompanyExists();
        break;
      case 'warehouse':
        await _ensureCompanyExists();
        await _ensureWarehouseExists();
        break;
      default:
        _log('자동 생성을 지원하지 않는 리소스 타입: $resourceType');
    }
  }
  
  /// 일반 에러를 DioException으로 변환
  DioException _convertToDioException(dynamic error) {
    if (error is DioException) {
      return error;
    }
    
    return DioException(
      requestOptions: RequestOptions(
        path: '/api/v1/${getResourceType()}',
        method: 'POST',
      ),
      message: error.toString(),
      type: DioExceptionType.unknown,
    );
  }
  
  // ===== 재시도 및 병렬 실행 지원 메서드들 =====
  
  /// 백오프를 포함한 재시도 로직
  Future<T> _retryWithBackoff<T>(
    Future<T> Function() operation,
    String operationName,
  ) async {
    int attempt = 0;
    dynamic lastError;
    
    while (attempt < maxRetryAttempts) {
      try {
        return await operation();
      } catch (e) {
        lastError = e;
        attempt++;
        
        if (attempt < maxRetryAttempts) {
          final delay = retryDelay * attempt;
          _log('$operationName 실패 (시도 $attempt/$maxRetryAttempts), ${delay.inSeconds}초 후 재시도...');
          await Future.delayed(delay);
        }
      }
    }
    
    _log('$operationName 최종 실패 ($maxRetryAttempts회 시도)');
    throw lastError;
  }
  
  
  /// 모든 잠금 해제
  void _releaseAllLocks() {
    for (final entry in _resourceLocks.entries) {
      if (entry.key.contains(testSessionId)) {
        entry.value.complete();
      }
    }
    _resourceLocks.removeWhere((key, _) => key.contains(testSessionId));
  }
  
  // ===== 헬퍼 메서드들 =====
  
  /// 업데이트를 위한 리소스 확보
  Future<dynamic> _ensureResourceForUpdate(TestData data) async {
    var resourceId = testContext.getData('lastCreatedId');
    
    if (resourceId == null) {
      _log('업데이트할 리소스가 없어 새로 생성');
      await performCreate(data);
      resourceId = testContext.getData('lastCreatedId');
    }
    
    return resourceId;
  }
  
  /// 삭제를 위한 리소스 확보
  Future<dynamic> _ensureResourceForDelete(TestData data) async {
    var resourceId = testContext.getData('lastCreatedId');
    
    if (resourceId == null) {
      _log('삭제할 리소스가 없어 새로 생성');
      await performCreate(data);
      resourceId = testContext.getData('lastCreatedId');
    }
    
    return resourceId;
  }
  
  /// 로깅 메서드
  void _log(String message) {
    final screenName = getScreenMetadata().screenName;
    
    // 리포트 수집기에 로그 추가 (print 대신 사용)
    reportCollector.addStep(
      report_models.StepReport(
        stepName: screenName,
        timestamp: DateTime.now(),
        success: !message.contains('실패') && !message.contains('에러'),
        message: message,
        details: {'sessionId': testSessionId},
      ),
    );
  }
}

/// 테스트 설정 오류
class TestSetupError implements Exception {
  final String message;
  final Map<String, dynamic> details;
  
  TestSetupError({
    required this.message,
    required this.details,
  });
  
  @override
  String toString() => 'TestSetupError: $message ($details)';
}