import 'dart:io';
import 'dart:typed_data';

import 'package:wolf_3d_data_types/wolf_3d_data_types.dart';

import '../wl_parser.dart';

/// dart:io implementation for directory discovery.
Future<Map<GameVersion, WolfensteinData>> discoverInDirectory({
  String? directoryPath,
  bool recursive = false,
}) async {
  final dir = Directory(directoryPath ?? Directory.current.path);
  if (!await dir.exists()) {
    print('Warning: Directory does not exist -> ${dir.path}');
    return {};
  }

  final allFiles = await dir
      .list(recursive: recursive)
      .where((entity) => entity is File)
      .cast<File>()
      .toList();

  final Map<GameVersion, WolfensteinData> loadedVersions = {};

  for (final version in GameVersion.values) {
    final ext = version.fileExtension.toUpperCase();
    final Map<GameFile, File> foundFiles = {};

    for (final requiredFile in GameFile.values) {
      final expectedName = '${requiredFile.baseName}.$ext';

      final match = allFiles.where((file) {
        final fileName = file.uri.pathSegments.last.toUpperCase();
        return fileName == expectedName;
      }).firstOrNull;

      if (match != null) {
        foundFiles[requiredFile] = match;
      }
    }

    if (foundFiles.isEmpty) continue;

    if (foundFiles.length < GameFile.values.length) {
      final missingFiles = GameFile.values
          .where((f) => !foundFiles.containsKey(f))
          .map((f) => '${f.baseName}.$ext')
          .join(', ');
      print('Found partial data for ${version.name}. Missing: $missingFiles');
      continue;
    }

    try {
      final data = WLParser.load(
        version: version,
        vswap: await _readFile(foundFiles[GameFile.vswap]!),
        mapHead: await _readFile(foundFiles[GameFile.mapHead]!),
        gameMaps: await _readFile(foundFiles[GameFile.gameMaps]!),
        vgaDict: await _readFile(foundFiles[GameFile.vgaDict]!),
        vgaHead: await _readFile(foundFiles[GameFile.vgaHead]!),
        vgaGraph: await _readFile(foundFiles[GameFile.vgaGraph]!),
        audioHed: await _readFile(foundFiles[GameFile.audioHed]!),
        audioT: await _readFile(foundFiles[GameFile.audioT]!),
      );

      loadedVersions[version] = data;
    } catch (e) {
      print('Error parsing data for ${version.name}: $e');
    }
  }

  return loadedVersions;
}

Future<ByteData> _readFile(File file) async {
  final bytes = await file.readAsBytes();
  return bytes.buffer.asByteData();
}
