import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
import '../core/database.dart';
import '../core/preferences.dart';
import '../models/trip.dart';
import '../models/photo.dart';

class MediaScanner {
  static const _channel = MethodChannel('cz.coolcode.live_vacation_memories/media');


  /// Request permissions for storage/photos and media location

  static Future<bool> requestPermissions() async {
    // On Android 13+, Permission.photos is required. On Android 12-, Permission.storage is required.
    final photoStatus = await Permission.photos.request();
    final storageStatus = await Permission.storage.request();
    
    // accessMediaLocation is optional/best-effort to read EXIF GPS
    try {
      await Permission.accessMediaLocation.request();
    } catch (e) {
      // Ignore location request failures
    }

    final hasPhotoAccess = photoStatus.isGranted || photoStatus.isLimited;
    final hasStorageAccess = storageStatus.isGranted || storageStatus.isLimited;

    return hasPhotoAccess || hasStorageAccess;
  }

  /// Scan media store for a given trip
  static Future<List<Photo>> scanPhotosForTrip(Trip trip) async {
    // 1. Ensure times are set
    final start = trip.startTimeUtc;
    final finish = trip.finishTimeUtc ?? DateTime.now().millisecondsSinceEpoch;
    
    if (start == null) return [];

    // 2. Request permissions
    final hasPermission = await requestPermissions();
    if (!hasPermission) {
      throw Exception('Nedostatečná oprávnění pro přístup k fotografiím a GPS údajům.');
    }

    // 3. Invoke Native MethodChannel
    final List<dynamic>? rawPhotos = await _channel.invokeMethod<List<dynamic>>(
      'scanPhotos',
      {
        'startUtc': start,
        'finishUtc': finish,
      },
    );

    if (rawPhotos == null) return [];

    final List<Photo> likelyPhotos = [];

    for (final raw in rawPhotos) {
      if (raw is! Map) continue;

      final map = Map<String, dynamic>.from(raw);


      // Extract values
      final id = map['id']?.toString() ?? '';
      final uri = map['uri']?.toString() ?? '';
      final displayName = map['displayName']?.toString() ?? 'foto_$id.jpg';
      final mimeType = map['mimeType']?.toString() ?? 'image/jpeg';
      final size = map['size'] as int? ?? 0;
      final relativePath = map['relativePath']?.toString();
      final ownerPackageName = map['ownerPackageName']?.toString();

      // Prioritize dates: EXIF DateTaken -> MediaStore DateTaken -> MediaStore DateAdded
      final exifDateTaken = map['exifDateTaken'] as int?;
      final mediaDateTaken = map['dateTaken'] as int?;
      final mediaDateAdded = map['dateAdded'] as int?;
      final dateTaken = exifDateTaken ?? mediaDateTaken ?? mediaDateAdded;

      final latitude = map['exifLatitude'] as double?;
      final longitude = map['exifLongitude'] as double?;
      final altitude = map['exifAltitude'] as double?;
      final make = map['exifMake']?.toString();
      final model = map['exifModel']?.toString();
      final orientation = map['exifOrientation'] as int?;

      // Calculate hash on-demand later or trigger immediately
      // For now, let's leave sha256 empty, it will be populated by HashWorker/service
      final photo = Photo(
        id: id,
        tripId: trip.id,
        authorParticipantId: AppPreferences.participantId,
        contentUri: uri,
        displayName: displayName,
        mimeType: mimeType,
        sizeBytes: size,
        dateTakenUtc: dateTaken,
        dateAddedUtc: mediaDateAdded,
        latitude: latitude,
        longitude: longitude,
        altitude: altitude,
        width: null,
        height: null,
        orientation: orientation,
        cameraMake: make,
        cameraModel: model,
        relativePath: relativePath,
        ownerPackageName: ownerPackageName,
        sha256: null,
        perceptualHash: null,
        isLocalOriginal: true,
        sourceDeviceId: AppPreferences.deviceId,
        importState: 'imported',
        shareState: 'pending',
      );

      // Save to database
      await DatabaseHelper.instance.insertPhoto(photo);
      likelyPhotos.add(photo);
    }

    return likelyPhotos;
  }

  /// Calculate SHA-256 for a given content URI using native platform channel
  static Future<String> calculateSha256(String uri) async {
    final String? hash = await _channel.invokeMethod<String>(
      'calculateSha256',
      {'uri': uri},
    );
    return hash ?? '';
  }


  /// Get thumbnail bytes for a photo Content URI
  static Future<Uint8List> getThumbnail(String uri, {int width = 200, int height = 200}) async {
    final Uint8List? bytes = await _channel.invokeMethod<Uint8List>(
      'getThumbnail',
      {
        'uri': uri,
        'width': width,
        'height': height,
      },
    );
    if (bytes == null) {
      throw Exception('Chyba při načítání náhledu.');
    }
    return bytes;
  }

  /// Get full photo bytes for a Content URI
  static Future<Uint8List> getPhotoBytes(String uri) async {
    final Uint8List? bytes = await _channel.invokeMethod<Uint8List>(
      'getPhotoBytes',
      {'uri': uri},
    );
    if (bytes == null) {
      throw Exception('Chyba při načítání fotografie.');
    }
    return bytes;
  }
}
