import 'dart:io';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:open_filex/open_filex.dart';
import 'package:gal/gal.dart';

class DownloadHelper {
  static const String API_BASE_URL = "https://www.taxglide.amrithaa.net/api/";

  /// Request storage permission based on Android version
  static Future<bool> requestStoragePermission() async {
    if (!Platform.isAndroid) return true;

    try {
      final androidInfo = await DeviceInfoPlugin().androidInfo;
      final sdkInt = androidInfo.version.sdkInt;

      print("📱 Android SDK: $sdkInt");

      // Android 13+ (API 33+)
      if (sdkInt >= 33) {
        final photoStatus = await Permission.photos.request();
        final videoStatus = await Permission.videos.request();

        print("✅ Android 13+ - Media permissions requested");
        return photoStatus.isGranted || videoStatus.isGranted;
      }

      // Android 11-12 (API 30-32)
      if (sdkInt >= 30) {
        if (await Permission.manageExternalStorage.isGranted) {
          return true;
        }

        var status = await Permission.manageExternalStorage.request();
        if (status.isGranted) return true;

        status = await Permission.storage.request();
        return status.isGranted;
      }

      // Android 10 and below (API 29 and below)
      final status = await Permission.storage.request();
      return status.isGranted;
    } catch (e) {
      print("❌ Permission error: $e");
      return false;
    }
  }

  /// ⭐ NEW: Get TaxGlide folder in PUBLIC Downloads
  static Future<Directory> getTaxGlideFolder() async {
    try {
      await requestStoragePermission();

      if (Platform.isAndroid) {
        // Use public Downloads folder for all Android versions
        final publicTaxGlide = Directory(
          '/storage/emulated/0/Download/TaxGlide',
        );

        if (!await publicTaxGlide.exists()) {
          await publicTaxGlide.create(recursive: true);
          print(
            "✅ TaxGlide folder created in public Downloads: ${publicTaxGlide.path}",
          );
        }

        return publicTaxGlide;
      } else {
        // iOS - use app documents
        final baseDirectory = await getApplicationDocumentsDirectory();
        final taxGlideFolder = Directory('${baseDirectory.path}/TaxGlide');

        if (!await taxGlideFolder.exists()) {
          await taxGlideFolder.create(recursive: true);
        }

        return taxGlideFolder;
      }
    } catch (e) {
      print("❌ Error creating TaxGlide folder: $e");
      // Fallback to app-specific storage if public storage fails
      final fallbackDir = await getExternalStorageDirectory();
      final taxGlideFolder = Directory('${fallbackDir!.path}/TaxGlide');

      if (!await taxGlideFolder.exists()) {
        await taxGlideFolder.create(recursive: true);
        print("⚠️ Using app-specific storage as fallback");
      }

      return taxGlideFolder;
    }
  }

  /// ⭐ Get Received folder in PUBLIC Downloads
  static Future<Directory> getReceivedFolder() async {
    final taxGlideFolder = await getTaxGlideFolder();
    final receivedFolder = Directory('${taxGlideFolder.path}/Received');

    if (!await receivedFolder.exists()) {
      await receivedFolder.create(recursive: true);
      print("✅ Received folder created: ${receivedFolder.path}");
    }

    return receivedFolder;
  }

  /// ⭐ Get Send folder in PUBLIC Downloads
  static Future<Directory> getSendFolder() async {
    final taxGlideFolder = await getTaxGlideFolder();
    final sendFolder = Directory('${taxGlideFolder.path}/Send');

    if (!await sendFolder.exists()) {
      await sendFolder.create(recursive: true);
      print("✅ Send folder created: ${sendFolder.path}");
    }

    return sendFolder;
  }

  /// Save file to Gallery (for images/videos only)
  static Future<bool> saveToGallery(String filePath) async {
    try {
      final file = File(filePath);
      if (!await file.exists()) {
        print("❌ File does not exist: $filePath");
        return false;
      }

      final fileName = filePath.split('/').last;

      // Request permissions
      final hasPermission = await requestStoragePermission();
      if (!hasPermission) {
        print("⚠️ No permission to save to gallery");
        return false;
      }

      // Only save images/videos to Gallery
      if (isImageFile(filePath)) {
        await Gal.putImage(filePath, album: 'TaxGlide');
        print("✅ Image saved to Gallery: $fileName");
        return true;
      } else if (isVideoFile(filePath)) {
        await Gal.putVideo(filePath, album: 'TaxGlide');
        print("✅ Video saved to Gallery: $fileName");
        return true;
      }

      return false;
    } catch (e) {
      print("❌ Error saving to gallery: $e");
      return false;
    }
  }

  /// Build download URL
  static String buildDownloadUrl(String filePath) {
    if (filePath.startsWith('http://') || filePath.startsWith('https://')) {
      return filePath;
    }
    return '${API_BASE_URL}chat/download/$filePath';
  }

  /// Check if file exists in Received folder
  static Future<String?> checkFileExistsInReceived(String url) async {
    try {
      final fileName = url.contains('/')
          ? url.split('/').last.split('?').first
          : url.split('?').first;

      final receivedFolder = await getReceivedFolder();
      final filePath = '${receivedFolder.path}/$fileName';
      final file = File(filePath);

      if (await file.exists()) {
        print("✅ File already exists in Received: $filePath");
        return filePath;
      }
      return null;
    } catch (e) {
      print("❌ Error checking file existence: $e");
      return null;
    }
  }

  /// Backward compatibility
  static Future<String?> checkFileExists(String url) async {
    return await checkFileExistsInReceived(url);
  }

  /// ⭐ Download file to Received folder (now in public Downloads) and Gallery
  static Future<Map<String, dynamic>> downloadFileToReceived(String url) async {
    try {
      final fullUrl = buildDownloadUrl(url);
      print("🔗 Downloading from: $fullUrl");

      // Check if file already exists
      final existingFilePath = await checkFileExistsInReceived(fullUrl);
      if (existingFilePath != null) {
        print("📂 File already exists, opening it...");
        await openDownloadedFile(existingFilePath);
        return {
          'filePath': existingFilePath,
          'isNewDownload': false,
          'success': true,
        };
      }

      // Request permissions
      await requestStoragePermission();

      // Get filename and prepare save path
      String fileName = fullUrl.split('/').last.split('?').first;
      fileName = fileName.replaceAll(RegExp(r'[^\w\s\-\.]'), '_');

      final receivedFolder = await getReceivedFolder();
      final savePath = "${receivedFolder.path}/$fileName";

      print("Download Started: Downloading $fileName...");

      // Download file to Received folder (now in public Downloads)
      Dio dio = Dio();
      await dio.download(
        fullUrl,
        savePath,
        onReceiveProgress: (received, total) {
          if (total != -1) {
            final progress = (received / total * 100).toStringAsFixed(0);
            print("📊 Download progress: $progress%");
          }
        },
      );

      // Also save images/videos to Gallery
      bool savedToGallery = false;
      try {
        savedToGallery = await saveToGallery(savePath);
      } catch (e) {
        print("⚠️ Could not save to gallery: $e");
      }

      if (savedToGallery) {
        print(
          "Download Complete: $fileName saved to Gallery & Downloads/TaxGlide/Received",
        );
      } else {
        print(
          "Download Complete: $fileName saved to Downloads/TaxGlide/Received",
        );
      }

      print("✅ File downloaded to: $savePath");

      // Open the downloaded file
      await openDownloadedFile(savePath);

      return {
        'filePath': savePath,
        'isNewDownload': true,
        'success': true,
        'savedToGallery': savedToGallery,
      };
    } catch (e) {
      print("❌ Download error: $e");
      print("Download Failed: Error: ${e.toString()}");
      return {'success': false, 'error': e.toString()};
    }
  }

  /// Backward compatibility
  static Future<Map<String, dynamic>> downloadFile(String url) async {
    return await downloadFileToReceived(url);
  }

  /// ⭐ Save file to Send folder (now in public Downloads)
  static Future<String> saveToSendFolder(File file) async {
    try {
      if (!await file.exists()) {
        throw Exception("Source file does not exist: ${file.path}");
      }

      final sendFolder = await getSendFolder();
      final originalFileName = file.path.split('/').last;
      final timestamp = DateTime.now().millisecondsSinceEpoch;
      final fileName = '${timestamp}_$originalFileName';
      final savePath = '${sendFolder.path}/$fileName';

      final savedFile = await file.copy(savePath);

      print("✅ File saved to Send folder (Downloads/TaxGlide/Send): $savePath");

      // Also save images/videos to Gallery
      try {
        await saveToGallery(savePath);
      } catch (e) {
        print("⚠️ Could not save to gallery: $e");
      }

      return savedFile.path;
    } catch (e) {
      print("❌ Error saving to Send folder: $e");
      print("⚠️ Using original file path: ${file.path}");
      return file.path;
    }
  }

  /// Save multiple files to Send folder
  static Future<List<File>> saveMultipleToSendFolder(List<File> files) async {
    List<File> savedFiles = [];

    for (File file in files) {
      try {
        final savedPath = await saveToSendFolder(file);
        savedFiles.add(File(savedPath));
      } catch (e) {
        print("❌ Error saving file: ${file.path}, using original");
        savedFiles.add(file);
      }
    }

    return savedFiles;
  }

  /// Open file with appropriate viewer
  static Future<void> openDownloadedFile(String path) async {
    print("🔓 Opening file: $path");

    try {
      final file = File(path);
      if (!await file.exists()) {
        print("❌ File not found at $path");
        print("Error: File not found");
        return;
      }

      final result = await OpenFilex.open(path);

      if (result.type != ResultType.done) {
        print("⚠️ Could not open file: ${result.message}");
        print("Notice: File saved but no app found to open it");
      }
    } catch (e) {
      print("❌ Error opening file: $e");
      print("Error: Could not open file");
    }
  }

  /// Get all files from Send folder
  static Future<List<File>> getSentFiles() async {
    try {
      final sendFolder = await getSendFolder();
      if (await sendFolder.exists()) {
        return sendFolder.listSync().whereType<File>().toList()..sort(
          (a, b) => b.lastModifiedSync().compareTo(a.lastModifiedSync()),
        );
      }
      return [];
    } catch (e) {
      print("❌ Error getting sent files: $e");
      return [];
    }
  }

  /// Get all files from Received folder
  static Future<List<File>> getReceivedFiles() async {
    try {
      final receivedFolder = await getReceivedFolder();
      if (await receivedFolder.exists()) {
        return receivedFolder.listSync().whereType<File>().toList()..sort(
          (a, b) => b.lastModifiedSync().compareTo(a.lastModifiedSync()),
        );
      }
      return [];
    } catch (e) {
      print("❌ Error getting received files: $e");
      return [];
    }
  }

  /// Delete a file
  static Future<bool> deleteFile(String filePath) async {
    try {
      final file = File(filePath);
      if (await file.exists()) {
        await file.delete();
        print("✅ File deleted: $filePath");
        print("File Deleted: File removed successfully");
        return true;
      }
      return false;
    } catch (e) {
      print("❌ Error deleting file: $e");
      return false;
    }
  }

  /// Clear all files from Send folder
  static Future<void> clearSendFolder() async {
    try {
      final files = await getSentFiles();
      for (final file in files) {
        await file.delete();
      }
      print("✅ Send folder cleared: ${files.length} files deleted");
    } catch (e) {
      print("❌ Error clearing Send folder: $e");
    }
  }

  /// Clear all files from Received folder
  static Future<void> clearReceivedFolder() async {
    try {
      final files = await getReceivedFiles();
      for (final file in files) {
        await file.delete();
      }
      print("✅ Received folder cleared: ${files.length} files deleted");
    } catch (e) {
      print("❌ Error clearing Received folder: $e");
    }
  }

  /// Get file size in human-readable format
  static Future<String> getFileSize(File file) async {
    try {
      final bytes = await file.length();
      if (bytes < 1024) return '$bytes B';
      if (bytes < 1024 * 1024) {
        return '${(bytes / 1024).toStringAsFixed(2)} KB';
      }
      if (bytes < 1024 * 1024 * 1024) {
        return '${(bytes / (1024 * 1024)).toStringAsFixed(2)} MB';
      }
      return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB';
    } catch (e) {
      return 'Unknown';
    }
  }

  /// Get file extension
  static String getFileExtension(String path) {
    return path.split('.').last.toLowerCase();
  }

  /// Check if file is image
  static bool isImageFile(String path) {
    final ext = getFileExtension(path);
    return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'].contains(ext);
  }

  /// Check if file is document
  static bool isDocumentFile(String path) {
    final ext = getFileExtension(path);
    return [
      'pdf',
      'doc',
      'docx',
      'xls',
      'xlsx',
      'txt',
      'ppt',
      'pptx',
      'rtf',
      'odt',
    ].contains(ext);
  }

  /// Check if file is video
  static bool isVideoFile(String path) {
    final ext = getFileExtension(path);
    return ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'webm'].contains(ext);
  }

  /// Check if file is audio
  static bool isAudioFile(String path) {
    final ext = getFileExtension(path);
    return ['mp3', 'wav', 'aac', 'flac', 'ogg', 'm4a', 'wma'].contains(ext);
  }

  /// Get file icon based on type
  static String getFileIcon(String path) {
    if (isImageFile(path)) return '🖼️';
    if (isVideoFile(path)) return '🎥';
    if (isAudioFile(path)) return '🎵';
    if (isDocumentFile(path)) {
      final ext = getFileExtension(path);
      if (ext == 'pdf') return '📄';
      if (['doc', 'docx'].contains(ext)) return '📝';
      if (['xls', 'xlsx'].contains(ext)) return '📊';
      if (['ppt', 'pptx'].contains(ext)) return '📽️';
    }
    return '📎';
  }

  /// Get storage info
  static Future<Map<String, String>> getStorageInfo() async {
    try {
      final taxGlideFolder = await getTaxGlideFolder();
      final sentFiles = await getSentFiles();
      final receivedFiles = await getReceivedFiles();

      int totalSentSize = 0;
      int totalReceivedSize = 0;

      for (final file in sentFiles) {
        totalSentSize += await file.length();
      }

      for (final file in receivedFiles) {
        totalReceivedSize += await file.length();
      }

      return {
        'taxGlidePath': taxGlideFolder.path,
        'sentFiles': sentFiles.length.toString(),
        'receivedFiles': receivedFiles.length.toString(),
        'sentSize': _formatBytes(totalSentSize),
        'receivedSize': _formatBytes(totalReceivedSize),
        'totalSize': _formatBytes(totalSentSize + totalReceivedSize),
      };
    } catch (e) {
      print("❌ Error getting storage info: $e");
      return {};
    }
  }

  static String _formatBytes(int bytes) {
    if (bytes < 1024) return '$bytes B';
    if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(2)} KB';
    if (bytes < 1024 * 1024 * 1024) {
      return '${(bytes / (1024 * 1024)).toStringAsFixed(2)} MB';
    }
    return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB';
  }
}
