import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:path/path.dart' as path;
import 'package:lanebow/utils/test_config.dart';

/// 테스트 진단 및 문제 해결을 위한 유틸리티 클래스
class TestDiagnostics {
  static TestDiagnostics? _instance;
  
  // 진단 로그 저장 경로
  final String _logDir;
  // 진단 로그 파일 경로
  final String _logFilePath;
  // 진단 로그 파일
  IOSink? _logSink;
  // 테스트 실패 카운트
  int _failureCount = 0;
  // 테스트 경고 카운트
  int _warningCount = 0;
  // 시작 시간
  final DateTime _startTime = DateTime.now();
  
  /// 싱글톤 인스턴스 반환
  static TestDiagnostics get instance {
    _instance ??= TestDiagnostics._internal();
    return _instance!;
  }
  
  TestDiagnostics._internal() : 
    _logDir = path.join(Directory.current.path, 'test_diagnostics'),
    _logFilePath = path.join(
      Directory.current.path, 
      'test_diagnostics', 
      'test_diagnostics_${DateTime.now().millisecondsSinceEpoch}.log'
    ) {
    _initializeLogDir();
  }
  
  /// 로그 디렉토리 초기화
  void _initializeLogDir() {
    try {
      final dir = Directory(_logDir);
      if (!dir.existsSync()) {
        dir.createSync(recursive: true);
      }
      
      // 로그 파일 생성
      _logSink = File(_logFilePath).openWrite(mode: FileMode.writeOnly);
      _log('테스트 진단 시작: ${DateTime.now()}');
      _log('환경 정보: ${Platform.operatingSystem} ${Platform.operatingSystemVersion}');
      _log('테스트 설정: asyncTimeout=${TestConfig.instance.asyncTimeout}ms, testDelay=${TestConfig.instance.testDelay}ms');
    } catch (e) {
      if (kDebugMode) {
        print('TestDiagnostics: 로그 디렉토리 초기화 중 오류 - $e');
      }
    }
  }
  
  /// 로그 기록
  void _log(String message) {
    final timestamp = DateTime.now().toIso8601String();
    final logMessage = '[$timestamp] $message';
    
    _logSink?.writeln(logMessage);
    
    if (kDebugMode) {
      print('TestDiagnostics: $message');
    }
  }
  
  /// 테스트 실패 기록
  void recordFailure(String testName, String errorMessage, {StackTrace? stackTrace}) {
    _failureCount++;
    _log('테스트 실패 #$_failureCount: $testName');
    _log('오류 메시지: $errorMessage');
    
    if (stackTrace != null) {
      _log('스택 트레이스:\n$stackTrace');
    }
    
    // 시스템 정보 수집
    _collectSystemInfo();
  }
  
  /// 테스트 경고 기록
  void recordWarning(String testName, String warningMessage) {
    _warningCount++;
    _log('테스트 경고 #$_warningCount: $testName');
    _log('경고 메시지: $warningMessage');
  }
  
  /// 시스템 정보 수집
  Future<void> _collectSystemInfo() async {
    try {
      _log('--- 시스템 정보 수집 시작 ---');
      
      // 메모리 사용량 정보 수집 (필요시 구현)
      
      // 프로세스 정보 (플랫폼별 처리)
      if (Platform.isLinux || Platform.isMacOS) {
        try {
          final result = await Process.run('ps', ['-o', 'pid,ppid,rss,vsz,pcpu,pmem,command', '-p', '${currentPid}']);
          _log('프로세스 정보:\n${result.stdout}');
        } catch (e) {
          _log('프로세스 정보 수집 실패: $e');
        }
      }
      
      // 실행 중인 테스트 프로세스 목록
      try {
        final result = await Process.run('ps', ['aux', '|', 'grep', 'flutter test']);
        _log('테스트 프로세스 목록:\n${result.stdout}');
      } catch (e) {
        _log('테스트 프로세스 목록 수집 실패: $e');
      }
      
      // 시스템 부하 정보
      if (Platform.isLinux || Platform.isMacOS) {
        try {
          final result = await Process.run('uptime', []);
          _log('시스템 부하 정보:\n${result.stdout}');
        } catch (e) {
          _log('시스템 부하 정보 수집 실패: $e');
        }
      }
      
      _log('--- 시스템 정보 수집 완료 ---');
    } catch (e) {
      _log('시스템 정보 수집 중 오류: $e');
    }
  }
  
  /// 테스트 진단 요약 생성
  Future<String> generateSummary() async {
    final duration = DateTime.now().difference(_startTime);
    final summary = StringBuffer();
    
    summary.writeln('=== 테스트 진단 요약 ===');
    summary.writeln('실행 시간: ${duration.inSeconds}초');
    summary.writeln('실패 수: $_failureCount');
    summary.writeln('경고 수: $_warningCount');
    summary.writeln('테스트 설정:');
    summary.writeln('  - asyncTimeout: ${TestConfig.instance.asyncTimeout}ms');
    summary.writeln('  - testDelay: ${TestConfig.instance.testDelay}ms');
    summary.writeln('  - retryCount: ${TestConfig.instance.retryCount}');
    summary.writeln('  - isolationMode: ${TestConfig.instance.isolationMode}');
    summary.writeln('  - CI 환경: ${TestConfig.instance.isCI}');
    
    final summaryText = summary.toString();
    _log(summaryText);
    
    return summaryText;
  }
  
  /// 테스트 진단 종료
  Future<void> close() async {
    await generateSummary();
    
    _log('테스트 진단 종료: ${DateTime.now()}');
    await _logSink?.flush();
    await _logSink?.close();
    _logSink = null;
    
    if (kDebugMode) {
      print('TestDiagnostics: 진단 로그 저장됨 - $_logFilePath');
    }
  }
  
  /// 테스트 실패 시 최소 재현 스크립트 생성
  Future<String> generateMinimalReproductionScript(String testName) async {
    final scriptPath = path.join(_logDir, 'reproduce_${testName.replaceAll(RegExp(r'[^\w]'), '_')}.sh');
    final script = File(scriptPath);
    
    final buffer = StringBuffer();
    buffer.writeln('#!/bin/bash');
    buffer.writeln('# $testName 테스트 실패 재현 스크립트');
    buffer.writeln('# 생성일: ${DateTime.now()}');
    buffer.writeln('');
    buffer.writeln('# 환경 변수 설정');
    buffer.writeln('export FLUTTER_TEST_TIMEOUT_OVERRIDE=${TestConfig.instance.asyncTimeout}');
    buffer.writeln('export FLUTTER_TEST_RETRY_COUNT=${TestConfig.instance.retryCount}');
    buffer.writeln('');
    buffer.writeln('# 테스트 실행');
    buffer.writeln('cd "\$(dirname "\$0")/.."');
    buffer.writeln('flutter test --name="$testName" --verbose');
    
    await script.writeAsString(buffer.toString());
    
    // 실행 권한 부여
    if (Platform.isLinux || Platform.isMacOS) {
      await Process.run('chmod', ['+x', scriptPath]);
    }
    
    _log('재현 스크립트 생성됨: $scriptPath');
    return scriptPath;
  }
  
  /// 현재 프로세스 ID
  static int get currentPid => pid;
}
