import {NativeModules, NativeEventEmitter} from 'react-native';

const {TorrentStreamModule} = NativeModules;
const emitter = TorrentStreamModule
  ? new NativeEventEmitter(TorrentStreamModule)
  : null;

// Common trackers for magnet URI
const TRACKERS = [
  'udp://open.demonii.com:1337/announce',
  'udp://tracker.openbittorrent.com:80',
  'udp://tracker.coppersurfer.tk:6969',
  'udp://glotorrents.pw:6969/announce',
  'udp://tracker.opentrackr.org:1337/announce',
  'udp://torrent.gresille.org:80/announce',
  'udp://p4p.arenabg.com:1337',
  'udp://tracker.leechers-paradise.org:6969',
]
  .map(t => `&tr=${encodeURIComponent(t)}`)
  .join('');

function buildMagnet(infoHash: string): string {
  return `magnet:?xt=urn:btih:${infoHash.toLowerCase()}${TRACKERS}`;
}

export interface TorrentProgress {
  progress: number;
  seeds: number;
  downloadSpeed: number;
  bufferProgress: number;
  status: 'resolving' | 'downloading';
}

export interface TorrentResult {
  url: string;
  path: string;
  name: string;
}

/**
 * Start streaming a torrent locally.
 * Returns a promise that resolves with the local file URL when ready to play.
 */
export function startTorrentStream(
  infoHash: string,
  onProgress?: (p: TorrentProgress) => void,
): Promise<TorrentResult> {
  if (!TorrentStreamModule) {
    return Promise.reject(new Error('TorrentStream native module not available'));
  }

  const magnet = buildMagnet(infoHash);

  let progressSub: {remove: () => void} | null = null;
  if (onProgress && emitter) {
    progressSub = emitter.addListener('torrentProgress', onProgress);
  }

  return TorrentStreamModule.start(magnet).then((result: TorrentResult) => {
    // Keep progress listener active during playback — caller is responsible for cleanup
    return result;
  }).catch((err: Error) => {
    progressSub?.remove();
    throw err;
  });
}

/**
 * Stop the current torrent stream.
 */
export function stopTorrentStream(): void {
  if (TorrentStreamModule) {
    TorrentStreamModule.stop();
  }
}

/**
 * Check if local torrent streaming is available (native module present).
 */
export function isTorrentStreamAvailable(): boolean {
  return !!TorrentStreamModule;
}

// ── Watch Later (preload) APIs ──

export interface PreloadProgress {
  infoHash: string;
  status: 'resolving' | 'downloading' | 'complete';
  progress: number;
  seeds: number;
  downloadSpeed: number;
}

export interface PreloadStatus {
  infoHash: string;
  progress: number;
  fileName: string;
  totalSize: number;
  ready: boolean;
}

/**
 * Start preloading a torrent in the background for Watch Later.
 */
export function preloadTorrent(
  infoHash: string,
  onProgress?: (p: PreloadProgress) => void,
): Promise<void> {
  if (!TorrentStreamModule) {
    return Promise.reject(new Error('TorrentStream native module not available'));
  }
  const magnet = buildMagnet(infoHash);

  let progressSub: {remove: () => void} | null = null;
  if (onProgress && emitter) {
    progressSub = emitter.addListener('preloadProgress', (p: PreloadProgress) => {
      if (p.infoHash === infoHash) {
        onProgress(p);
        // Clean up listener once download is complete
        if (p.status === 'complete') {
          progressSub?.remove();
          progressSub = null;
        }
      }
    });
  }

  return TorrentStreamModule.preload(magnet, infoHash).then(() => {
    // Listener stays active until 'complete' event or error
  }).catch((err: Error) => {
    progressSub?.remove();
    throw err;
  });
}

/**
 * Play a preloaded torrent — starts HTTP server and returns URL.
 */
export function playPreloadedTorrent(infoHash: string): Promise<TorrentResult> {
  if (!TorrentStreamModule) {
    return Promise.reject(new Error('TorrentStream native module not available'));
  }
  return TorrentStreamModule.playPreloaded(infoHash);
}

/**
 * Cancel a preloading torrent.
 */
export function cancelPreload(infoHash: string): void {
  if (TorrentStreamModule) {
    TorrentStreamModule.cancelPreload(infoHash);
  }
}

/**
 * Get status of all preloading torrents.
 */
export function getPreloadStatus(): Promise<PreloadStatus[]> {
  if (!TorrentStreamModule) return Promise.resolve([]);
  return TorrentStreamModule.getPreloadStatus();
}
