class FileUtils {
  static String safeDecodePathSegment(String value, {int maxPasses = 5}) {
    var decoded = value;

    for (var i = 0; i < maxPasses; i++) {
      try {
        final next = Uri.decodeComponent(decoded);
        if (next == decoded) break;
        decoded = next;
      } on FormatException {
        break;
      } on ArgumentError {
        break;
      }
    }

    return decoded;
  }

  static String decodePathForDisplay(String path) {
    return path
        .split('/')
        .map((segment) => safeDecodePathSegment(segment))
        .join('/');
  }

  static String toCloudreveUri(String path) {
    if (path.startsWith('cloudreve://')) return path;
    if (path == '/' || path.isEmpty) return 'cloudreve://my';
    final cleanPath = path.startsWith('/') ? path.substring(1) : path;
    return 'cloudreve://my/$cleanPath';
  }

  static String toCloudreveUriWithQuery(
    String path,
    Map<String, String> queryParameters,
  ) {
    final uri = Uri.parse(toCloudreveUri(path));
    return uri.replace(queryParameters: queryParameters).toString();
  }

  static String getFileExtension(String fileName) {
    final dotIndex = fileName.lastIndexOf('.');
    if (dotIndex == -1) return '';
    return fileName.substring(dotIndex + 1).toLowerCase();
  }

  static bool isImageFile(String fileName) {
    const imageExtensions = [
      'jpg',
      'jpeg',
      'png',
      'gif',
      'webp',
      'bmp',
      'svg',
      'heic',
      'heif',
      'avif',
      'tif',
      'tiff',
    ];
    return imageExtensions.contains(getFileExtension(fileName));
  }

  static bool isFlutterRenderableImageFile(String fileName) {
    const renderableImageExtensions = [
      'jpg',
      'jpeg',
      'png',
      'gif',
      'webp',
      'bmp',
    ];
    return renderableImageExtensions.contains(getFileExtension(fileName));
  }

  static bool isVideoFile(String fileName) {
    const videoExtensions = [
      'mp4',
      'webm',
      'mkv',
      'avi',
      'mov',
      'flv',
      'wmv',
      'm4v',
      'mpg',
      'mpeg',
      '3gp',
      'ts',
      'm2ts',
    ];
    return videoExtensions.contains(getFileExtension(fileName));
  }

  static bool isAudioFile(String fileName) {
    const audioExtensions = ['mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a'];
    return audioExtensions.contains(getFileExtension(fileName));
  }

  static bool isPsdFile(String fileName) {
    const psdExtensions = ['psd', 'psb'];
    return psdExtensions.contains(getFileExtension(fileName));
  }

  static bool isThumbnailableFile(String fileName) {
    final ext = getFileExtension(fileName);
    if (ext.isEmpty || ext == 'svg') return false;
    return isImageFile(fileName) || isVideoFile(fileName) || isPsdFile(fileName);
  }

  static bool isPdfFile(String fileName) {
    return getFileExtension(fileName) == 'pdf';
  }

  static bool isTextFile(String fileName) {
    const textExtensions = [
      'txt',
      'md',
      'json',
      'xml',
      'yaml',
      'yml',
      'ini',
      'conf',
    ];
    return textExtensions.contains(getFileExtension(fileName));
  }

  static bool isCodeFile(String fileName) {
    const codeExtensions = [
      'js',
      'ts',
      'tsx',
      'jsx',
      'dart',
      'java',
      'py',
      'c',
      'cpp',
      'h',
      'hpp',
      'cs',
      'php',
      'rb',
      'go',
      'rs',
      'swift',
      'kt',
      'html',
      'css',
      'scss',
      'less',
      'sql',
      'sh',
      'bat',
    ];
    return codeExtensions.contains(getFileExtension(fileName));
  }

  static bool isArchiveFile(String fileName) {
    const archiveExtensions = ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'];
    return archiveExtensions.contains(getFileExtension(fileName));
  }

  static bool isDocumentFile(String fileName) {
    const docExtensions = [
      'doc',
      'docx',
      'xls',
      'xlsx',
      'ppt',
      'pptx',
      'odt',
      'ods',
      'odp',
    ];
    return docExtensions.contains(getFileExtension(fileName));
  }

  static bool isPreviewable(String fileName) {
    return isImageFile(fileName) ||
        isVideoFile(fileName) ||
        isPdfFile(fileName) ||
        isTextFile(fileName) ||
        isCodeFile(fileName);
  }

  static String getMimeType(String fileName) {
    final ext = getFileExtension(fileName);
    final mimeTypes = {
      'jpg': 'image/jpeg',
      'jpeg': 'image/jpeg',
      'png': 'image/png',
      'gif': 'image/gif',
      'webp': 'image/webp',
      'svg': 'image/svg+xml',
      'bmp': 'image/bmp',
      'heic': 'image/heic',
      'heif': 'image/heif',
      'avif': 'image/avif',
      'tif': 'image/tiff',
      'tiff': 'image/tiff',
      'psd': 'image/vnd.adobe.photoshop',
      'psb': 'image/vnd.adobe.photoshop',
      'mp4': 'video/mp4',
      'webm': 'video/webm',
      'mkv': 'video/x-matroska',
      'avi': 'video/x-msvideo',
      'mov': 'video/quicktime',
      'flv': 'video/x-flv',
      'wmv': 'video/x-ms-wmv',
      'm4v': 'video/x-m4v',
      'mpg': 'video/mpeg',
      'mpeg': 'video/mpeg',
      '3gp': 'video/3gpp',
      'ts': 'video/mp2t',
      'm2ts': 'video/mp2t',
      'mp3': 'audio/mpeg',
      'wav': 'audio/wav',
      'ogg': 'audio/ogg',
      'flac': 'audio/flac',
      'aac': 'audio/aac',
      'm4a': 'audio/mp4',
      'pdf': 'application/pdf',
      'txt': 'text/plain',
      'json': 'application/json',
      'xml': 'application/xml',
      'html': 'text/html',
      'css': 'text/css',
      'js': 'application/javascript',
    };
    return mimeTypes[ext] ?? 'application/octet-stream';
  }

  static String getFileIcon(String fileName) {
    if (isImageFile(fileName)) return 'assets/icons/image.svg';
    if (isVideoFile(fileName)) return 'assets/icons/video.svg';
    if (isAudioFile(fileName)) return 'assets/icons/audio.svg';
    if (isPdfFile(fileName)) return 'assets/icons/pdf.svg';
    if (isTextFile(fileName)) return 'assets/icons/text.svg';
    if (isCodeFile(fileName)) return 'assets/icons/code.svg';
    if (isArchiveFile(fileName)) return 'assets/icons/archive.svg';
    if (isDocumentFile(fileName)) return 'assets/icons/document.svg';

    return 'assets/icons/file.svg';
  }
}
