generateReport method
Generate a human-readable diagnostic report.
remoteResult is included only when --remote was requested; the
closing note names the one thing no local (or remote) check can ever
prove: that a real device matches the link.
Implementation
String generateReport(
{bool verbose = false, RemoteCheckResult? remoteResult}) {
final buffer = StringBuffer();
buffer.writeln('Magic Deeplink — Doctor Report');
buffer.writeln('=' * 50);
buffer.writeln();
final configExists = checkConfigExists();
buffer.writeln('Configuration File: ${configExists ? '✓' : '✗'}');
if (verbose) {
buffer.writeln(' Path: lib/config/deeplink.dart');
}
buffer.writeln();
buffer.writeln('Config Validation:');
if (!configExists) {
buffer.writeln(' ✗ Skipped — config file missing');
} else {
final configIssues = validateConfig();
if (configIssues.isEmpty) {
buffer.writeln(' ✓ All config checks passed');
} else {
for (final issue in configIssues) {
buffer.writeln(' ✗ $issue');
}
}
}
buffer.writeln();
final platformStatus =
configExists ? checkPlatformSetup() : <String, dynamic>{};
if (platformStatus.isEmpty) {
if (configExists) {
buffer.writeln('Platform Setup: no platforms detected');
buffer.writeln();
}
} else {
for (final entry in platformStatus.entries) {
final section = entry.key;
final status = entry.value as Map<String, dynamic>;
final configured = status['configured'] as bool;
final exists = status['exists'] as bool;
final issues = status['issues'] as List;
final warnings = status['warnings'] as List? ?? const [];
buffer.write('${_sectionTitle(section)}: ');
if (configured && warnings.isEmpty) {
buffer.writeln('✓ Configured');
} else if (exists) {
buffer.writeln('⚠ Needs attention');
} else {
buffer.writeln('✗ Not found');
}
if (verbose) {
for (final issue in issues) {
buffer.writeln(' ✗ $issue');
}
for (final warning in warnings) {
buffer.writeln(' ⚠ $warning');
}
}
}
buffer.writeln();
}
if (remoteResult != null) {
buffer.writeln('Remote (--remote):');
if (remoteResult.issues.isEmpty && remoteResult.warnings.isEmpty) {
buffer.writeln(' ✓ Both association files served correctly');
} else {
for (final issue in remoteResult.issues) {
buffer.writeln(' ✗ $issue');
}
for (final warning in remoteResult.warnings) {
buffer.writeln(' ⚠ $warning');
}
}
buffer.writeln();
}
final missing = configExists ? getMissingRequirements() : validateConfig();
final warnings = configExists ? getWarnings() : const <String>[];
final allIssues = [
...missing,
...remoteResult?.issues.map((i) => '[remote] $i') ?? const <String>[],
];
final allWarnings = [
...warnings,
...remoteResult?.warnings.map((w) => '[remote] $w') ?? const <String>[],
];
if (allIssues.isEmpty && allWarnings.isEmpty) {
buffer.writeln('✓ All requirements met!');
}
if (allIssues.isNotEmpty) {
buffer.writeln('Missing Requirements:');
for (final issue in allIssues) {
buffer.writeln(' ✗ $issue');
}
}
if (allWarnings.isNotEmpty) {
buffer.writeln('Warnings:');
for (final warning in allWarnings) {
buffer.writeln(' ⚠ $warning');
}
}
buffer.writeln();
buffer.writeln(
'Note: no local check can prove a device actually matches this link. '
'`swcutil verify` needs root and Android verifies at install time — the '
'last mile is always a real device.',
);
return buffer.toString();
}