import '../services/adb_service.dart';
import 'adb_device.dart';
import 'pending_install.dart';

enum InstallAttemptOutcome { success, failure }

class InstallAttemptResult {
  const InstallAttemptResult({
    required this.pendingInstall,
    required this.device,
    required this.result,
  });

  final PendingInstall pendingInstall;
  final AdbDevice device;
  final AdbInstallResult result;

  InstallAttemptOutcome get outcome => result.succeeded
      ? InstallAttemptOutcome.success
      : InstallAttemptOutcome.failure;

  bool get succeeded => outcome == InstallAttemptOutcome.success;

  bool get failed => outcome == InstallAttemptOutcome.failure;

  String get artifactLabel =>
      '#${pendingInstall.buildNumber} · ${pendingInstall.jobName} · '
      '${pendingInstall.fileName}';

  String get outputSummary {
    final stdout = result.stdout.trim();
    final stderr = result.stderr.trim();
    if (succeeded) {
      return [stdout, stderr].where((it) => it.isNotEmpty).join('\n');
    }

    if (stderr.isNotEmpty) return _firstNonEmptyLine(stderr);
    if (stdout.isNotEmpty) return _firstNonEmptyLine(stdout);
    return '설치 실패';
  }

  String get maskedOutputSummary => _maskSensitive(outputSummary);

  String get maskedDeviceSerial => _maskSerial(device.serial);

  String get maskedReport {
    final lines = [
      'AppSok 설치 리포트',
      '결과: ${succeeded ? '성공' : '실패'}',
      'exitCode: ${result.exitCode}',
      'Build: $artifactLabel',
      'Device: ${device.displayName} ($maskedDeviceSerial)',
      if (maskedOutputSummary.isNotEmpty) '요약: $maskedOutputSummary',
      if (result.stdout.trim().isNotEmpty)
        'stdout:\n${_maskSensitive(result.stdout.trim())}',
      if (result.stderr.trim().isNotEmpty)
        'stderr:\n${_maskSensitive(result.stderr.trim())}',
    ];
    return lines.join('\n');
  }

  String _firstNonEmptyLine(String text) {
    final lines = text
        .split('\n')
        .map((line) => line.trim())
        .where((line) => line.isNotEmpty);
    return lines.isEmpty ? '' : lines.first;
  }

  String _maskSensitive(String value) {
    final masked = value
        .replaceAll(RegExp(r'https?:\/\/[^\s]+'), '[masked-url]')
        .replaceAllMapped(
          RegExp(
            r'\b(authorization)\s*[:=]\s*bearer\s+[A-Za-z0-9._~+/=-]+',
            caseSensitive: false,
          ),
          (match) => '${match.group(1)}: [masked]',
        )
        .replaceAllMapped(
          RegExp(
            r'\b(api[_-]?token|token|password|passwd|secret)\s*[:=]\s*[^\s&]+',
            caseSensitive: false,
          ),
          (match) => '${match.group(1)}=[masked]',
        );
    return device.serial.isEmpty
        ? masked
        : masked.replaceAll(device.serial, maskedDeviceSerial);
  }

  String _maskSerial(String serial) {
    if (serial.isEmpty) return '[masked-serial]';
    if (serial.length <= 4) return '*' * serial.length;
    final prefix = serial.substring(0, 2);
    final suffix = serial.substring(serial.length - 2);
    return '$prefix${'*' * (serial.length - 4)}$suffix';
  }
}
