#import "ReactNativeLocalDownload.h"
#import <UIKit/UIKit.h>
#import <React/RCTEventEmitter.h>

@implementation ReactNativeLocalDownload
RCT_EXPORT_MODULE()

- (NSArray<NSString *> *)supportedEvents {
  return @[@"copyFileSAFProgress", @"copyFileSAFComplete", @"copyFileSAFError"];
}

- (void)localDownload:(NSString *)uri
             resolve:(RCTPromiseResolveBlock)resolve
              reject:(RCTPromiseRejectBlock)reject
{
  dispatch_async(dispatch_get_main_queue(), ^{
    NSURL *fileURL = [NSURL fileURLWithPath:uri];
    if (![fileURL isFileURL] || ![[NSFileManager defaultManager] fileExistsAtPath:uri]) {
      reject(@"invalid_file", @"The file URI is not valid or the file does not exist", nil);
      return;
    }

    UIActivityViewController *controller = [[UIActivityViewController alloc]
        initWithActivityItems:@[fileURL]
        applicationActivities:nil];

    UIViewController *rootVC = UIApplication.sharedApplication.delegate.window.rootViewController;
    [rootVC presentViewController:controller animated:YES completion:nil];

    resolve(nil);
  });
}

#pragma mark - Android-only FD stubs (iOS)

- (void)getContentFd:(NSString *)uri
             resolve:(RCTPromiseResolveBlock)resolve
              reject:(RCTPromiseRejectBlock)reject
{
  reject(
    @"UNSUPPORTED_PLATFORM",
    @"getContentFd is not supported on iOS",
    nil
  );
}

- (void)closeFd:(NSString *)fdOrPath
        resolve:(RCTPromiseResolveBlock)resolve
         reject:(RCTPromiseRejectBlock)reject
{
  // No-op stub for iOS
  resolve(@(YES));
}

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
    (const facebook::react::ObjCTurboModule::InitParams &)params
{
    return std::make_shared<facebook::react::NativeReactNativeLocalDownloadSpecJSI>(params);
}

- (void)persistContentPermission:(NSString *)uri
                          resolve:(RCTPromiseResolveBlock)resolve
                           reject:(RCTPromiseRejectBlock)reject
{
  // iOS sandbox does not support persistable URI permissions
  resolve(@(YES));
}

- (void)copyFileSAF:(NSString *)sourceUri
            destPath:(NSString *)destPath
             resolve:(RCTPromiseResolveBlock)resolve
              reject:(RCTPromiseRejectBlock)reject
{
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    @try {
      NSURL *sourceURL = [NSURL URLWithString:sourceUri];
      NSURL *destURL = [NSURL fileURLWithPath:destPath];
      
      // Get source file
      NSInputStream *inputStream = [[NSInputStream alloc] initWithURL:sourceURL];
      if (!inputStream) {
        reject(@"SOURCE_OPEN_FAILED", @"Unable to open source for reading", nil);
        return;
      }
      
      [inputStream open];
      
      // Create output stream
      NSOutputStream *outputStream = [[NSOutputStream alloc] initWithURL:destURL append:NO];
      if (!outputStream) {
        [inputStream close];
        reject(@"DEST_OPEN_FAILED", @"Unable to open destination for writing", nil);
        return;
      }
      
      [outputStream open];
      
      // Get file size
      NSError *sizeError = nil;
      NSNumber *fileSizeNumber = nil;
      if ([sourceURL isFileURL]) {
        fileSizeNumber = [[NSFileManager defaultManager] attributesOfItemAtPath:[sourceURL path] error:&sizeError][NSFileSize];
      }
      long long totalBytes = [fileSizeNumber longLongValue];
      long long bytesCopied = 0;
      NSTimeInterval startTime = [[NSDate date] timeIntervalSince1970];
      
      // Copy data
      uint8_t buffer[262144];
      NSInteger bytesRead = 0;
      int lastPercentage = -1;
      while ((bytesRead = [inputStream read:buffer maxLength:sizeof(buffer)]) > 0) {
        [outputStream write:buffer maxLength:bytesRead];
        bytesCopied += bytesRead;
        
        // Calculate speed
        NSTimeInterval elapsedSeconds = [[NSDate date] timeIntervalSince1970] - startTime;
        double bytesPerSec = elapsedSeconds > 0 ? bytesCopied / elapsedSeconds : 0;
        double percentComplete = totalBytes > 0 ? (bytesCopied / (double)totalBytes * 100.0) : 0;
        int currentPercentage = (int)percentComplete;
        
        // Only emit progress event when percentage changes
        if (currentPercentage != lastPercentage) {
          lastPercentage = currentPercentage;
          NSDictionary *progress = @{
            @"bytesCopied": @(bytesCopied),
            @"totalBytes": @(totalBytes),
            @"percentComplete": @(percentComplete),
            @"bytesPerSec": @(bytesPerSec)
          };
          
          [self sendEventWithName:@"copyFileSAFProgress" body:progress];
        }
      }
      
      [inputStream close];
      [outputStream close];
      
      [self sendEventWithName:@"copyFileSAFComplete" body:nil];
      resolve(@YES);
    } @catch (NSException *exception) {
      NSDictionary *errorData = @{
        @"code": @"COPY_ERROR",
        @"message": exception.reason ?: @"Unknown error"
      };
      [self sendEventWithName:@"copyFileSAFError" body:errorData];
      reject(@"COPY_ERROR", exception.reason ?: @"Failed to copy file", nil);
    }
  });
}

@end
