package com.volcengine.reactnative.veplayer;

import android.content.Context;
import android.os.Environment;
import android.util.Log;

import androidx.annotation.Nullable;

import java.io.File;
import java.util.List;

import com.ss.ttvideoengine.Resolution;
import com.ss.ttvideoengine.TTVideoEngine;
import com.ss.ttvideoengine.download.Downloader;
import com.ss.ttvideoengine.download.DownloadTask;
import com.ss.ttvideoengine.download.IDownloaderListener;
import com.ss.ttvideoengine.utils.Error;
import static com.ss.ttvideoengine.DataLoaderHelper.DATALOADER_KEY_STRING_DOWNLOAD_DIR;

/**
 * 下载任务辅助类
 * 提供下载任务相关的功能
 */
public class DownloadHelper {
  private static final String TAG = "DownloadHelper";
  
  // 回调接口，用于返回任务列表
  public interface LoadAllTaskCallback {
    void onResult(List<DownloadTask> tasks);
  }
  
  // 临时保存的回调函数
  private static LoadAllTaskCallback sLoadAllTaskCallback;
  // 外部设置的下载监听器
  private static @Nullable IDownloaderListener sExternalListener;
  
  // 静态的下载监听器实例
  private static final IDownloaderListener sCommonListener = new IDownloaderListener() {
    @Override
    public void downloaderDidComplete(Downloader downloader, DownloadTask task, Error error) {
      Log.d(TAG, "downloaderDidComplete: " + task.getVideoId() + " " + error);
      if (sExternalListener != null) {
        sExternalListener.downloaderDidComplete(downloader, task, error);
      }
    }

    @Override
    public void downloaderWriteData(Downloader downloader, DownloadTask task, long bytesWritten, long timeMS) {
      if (sExternalListener != null) {
        sExternalListener.downloaderWriteData(downloader, task, bytesWritten, timeMS);
      }
    }

    @Override
    public void downloaderOnProgress(Downloader downloader, DownloadTask task, long receivedSize, long totalSize) {
      Log.d(TAG, "downloaderOnProgress: " + task.getVideoId() + " " + receivedSize + " " + totalSize);
      if (sExternalListener != null) {
        sExternalListener.downloaderOnProgress(downloader, task, receivedSize, totalSize);
      }
    }

    @Override
    public void downloaderDidResume(Downloader downloader, DownloadTask task, long fileOffset, long expectedTotalBytes) {
      Log.d(TAG, "downloaderDidResume: " + task.getVideoId() + " " + fileOffset + " " + expectedTotalBytes);
      if (sExternalListener != null) {
        sExternalListener.downloaderDidResume(downloader, task, fileOffset, expectedTotalBytes);
      }
    }

    @Override
    public void downloaderDidLoadAllTask(Downloader downloader, @Nullable List<DownloadTask> tasks, @Nullable Error error) {
      Log.d(TAG, "downloaderDidLoadAllTask: " + tasks + " " + error);
      // 先处理 loadAllTask 的一次性回调
      if (sLoadAllTaskCallback != null) {
        sLoadAllTaskCallback.onResult(tasks);
        sLoadAllTaskCallback = null; // 清除回调，避免内存泄漏
      }
      // 再转发给外部监听器
      if (sExternalListener != null) {
        sExternalListener.downloaderDidLoadAllTask(downloader, tasks, error);
      }
    }

    @Override
    public void downloaderStateChanged(Downloader downloader, DownloadTask task, int state) {
      Log.d(TAG, "downloaderStateChanged: " + task.getVideoId() + " " + state);
      if (sExternalListener != null) {
        sExternalListener.downloaderStateChanged(downloader, task, state);
      }
    }
  };

  /**
   * 设置外部监听器。内部会将 Downloader 的监听器统一设置为公共的 sCommonListener，
   * 并在公共监听器内将事件转发到外部监听器。
   */
  public static void setListener(@Nullable IDownloaderListener listener) {
    sExternalListener = listener;
    try {
      Downloader downloader = Downloader.getInstance();
      Log.d(TAG, "setListener for downloader");
      downloader.setListener(sCommonListener);
    } catch (Throwable t) {
      Log.w(TAG, "setListener failed: " + (t != null ? t.getMessage() : "unknown"));
    }
  }

  /**
   * 加载所有下载任务
   * @param callback 回调函数，直接返回任务对象列表（List<DownloadTask>），不进行序列化
   * @param context Android Application Context
   */
  public static void loadAllTasks(LoadAllTaskCallback callback, Context context) {
    if (callback == null || context == null) {
      return;
    }
    
    // 获取 Downloader 实例
    Downloader downloader = Downloader.getInstance();
    
    // 保存回调函数
    sLoadAllTaskCallback = callback;
    
    // 统一设置为公共监听器，以便中转外部监听器与 loadAllTask 的回调（强制覆盖）
    downloader.setListener(sCommonListener);
    
    Log.d(TAG, "loadAllTasks: " + downloader);
    // 加载所有任务
    downloader.loadAllTasks(context);
  }

  /**
   * 设置下载目录（带子目录）
   * @param subdir 子目录名称，如果为 null 或空字符串，则使用默认下载目录
   */
  public static void setDownloadDirectoryWithSubdir(String subdir) {
    Context appContext = VeplayerModule.reactApplicationContext != null
        ? VeplayerModule.reactApplicationContext.getApplicationContext()
        : null;
    if (appContext == null) {
      Log.w(TAG, "Application context is null, cannot set download directory");
      return;
    }
    File baseDir = appContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
    if (baseDir == null) {
      Log.w(TAG, "External files dir (Downloads) is null");
      return;
    }
    File finalDir = baseDir;
    if (subdir != null && !subdir.isEmpty()) {
      finalDir = new File(baseDir, subdir);
    }
    try {
      // Ensure directory exists
      if (!finalDir.exists()) {
        boolean ok = finalDir.mkdirs();
        if (!ok) {
          Log.w(TAG, "Failed to create download subdir: " + finalDir.getAbsolutePath());
        }
      }
      // Set download directory for data loader
      TTVideoEngine.setStringValueSync(DATALOADER_KEY_STRING_DOWNLOAD_DIR, finalDir.getAbsolutePath());
    } catch (Throwable t) {
      Log.e(TAG, "Error setting download directory: " + t.getMessage());
    }
  }

  /**
   * 安全地获取任务的 videoId
   * @param task 下载任务
   * @return videoId，如果任务没有 videoId 或获取失败则返回 null
   */
  @Nullable
  public static String getVideoIdFromTask(@Nullable DownloadTask task) {
    if (task == null) {
      Log.w(TAG, "getVideoIdFromTask: task is null");
      return null;
    }

    try {
      String videoId = task.getVideoId();
      if (videoId != null) {
        Log.d(TAG, "getVideoIdFromTask: success, videoId=" + videoId);
        return videoId;
      } else {
        Log.d(TAG, "getVideoIdFromTask: videoId is null");
        return null;
      }
    } catch (Exception e) {
      Log.w(TAG, "getVideoIdFromTask: exception=" + e.getMessage());
      return null;
    }
  }

  /**
   * 安全地获取任务的 key（cache key）
   * 只有 DownloadURLTask 才有 key 属性
   * @param task 下载任务
   * @return key，如果任务不是 DownloadURLTask 或没有 key 则返回 null
   */
  @Nullable
  public static String getKeyFromTask(@Nullable DownloadTask task) {
    if (task == null) {
      Log.w(TAG, "getKeyFromTask: task is null");
      return null;
    }

    // 只有 DownloadURLTask 才有 getKey() 方法
    if (!(task instanceof com.ss.ttvideoengine.download.DownloadURLTask)) {
      Log.d(TAG, "getKeyFromTask: task is not DownloadURLTask");
      return null;
    }

    try {
      com.ss.ttvideoengine.download.DownloadURLTask urlTask = (com.ss.ttvideoengine.download.DownloadURLTask) task;
      String key = urlTask.getKey();
      if (key != null) {
        Log.d(TAG, "getKeyFromTask: success, key=" + key);
        return key;
      } else {
        Log.d(TAG, "getKeyFromTask: key is null");
        return null;
      }
    } catch (Exception e) {
      Log.w(TAG, "getKeyFromTask: exception=" + e.getMessage());
      return null;
    }
  }

  /**
   * 安全地获取任务的 URLs
   * 只有 DownloadURLTask 才有 urls 属性
   * @param task 下载任务
   * @return URLs 列表，如果任务不是 DownloadURLTask 或没有 URLs 则返回 null
   */
  @Nullable
  public static List<String> getUrlsFromTask(@Nullable DownloadTask task) {
    if (task == null) {
      Log.w(TAG, "getUrlsFromTask: task is null");
      return null;
    }

    // 只有 DownloadURLTask 才有 getUrls() 方法
    if (!(task instanceof com.ss.ttvideoengine.download.DownloadURLTask)) {
      Log.d(TAG, "getUrlsFromTask: task is not DownloadURLTask");
      return null;
    }

    try {
      com.ss.ttvideoengine.download.DownloadURLTask urlTask = (com.ss.ttvideoengine.download.DownloadURLTask) task;
      List<String> urls = urlTask.getUrls();
      if (urls != null && !urls.isEmpty()) {
        Log.d(TAG, "getUrlsFromTask: success, urls.count=" + urls.size());
        return urls;
      } else {
        Log.d(TAG, "getUrlsFromTask: urls is null or empty");
        return null;
      }
    } catch (Exception e) {
      Log.w(TAG, "getUrlsFromTask: exception=" + e.getMessage());
      return null;
    }
  }

  /**
   * 安全地获取任务的 resolution
   * 只有 DownloadVidTask 才有 resolution 属性
   * @param task 下载任务
   * @return resolution，如果任务不是 DownloadVidTask 或没有 resolution 则返回 null
   */
  @Nullable
  public static Resolution getResolutionFromTask(@Nullable DownloadTask task) {
    if (task == null) {
      Log.w(TAG, "getResolutionFromTask: task is null");
      return null;
    }

    // 只有 DownloadVidTask 才有 getCurrentResolution() 方法
    if (!(task instanceof com.ss.ttvideoengine.download.DownloadVidTask)) {
      Log.d(TAG, "getResolutionFromTask: task is not DownloadVidTask");
      return null;
    }

    try {
      com.ss.ttvideoengine.download.DownloadVidTask vidTask = (com.ss.ttvideoengine.download.DownloadVidTask) task;
      Resolution resolution = vidTask.getCurrentResolution();
      Log.d(TAG, "getResolutionFromTask: success, resolution=" + resolution);
      return resolution;
    } catch (Exception e) {
      Log.w(TAG, "getResolutionFromTask: exception=" + e.getMessage());
      return null;
    }
  }

  /**
   * 安全地获取任务的 codecType（H.265 或 H.264）
   * 只有 DownloadVidTask 才有 codecType 属性
   * @param task 下载任务
   * @return codecType，1=H264, 2=H265，如果任务不是 DownloadVidTask 或获取失败则返回 null
   */
  @Nullable
  public static Integer getCodecTypeFromTask(@Nullable DownloadTask task) {
    if (task == null) {
      Log.w(TAG, "getCodecTypeFromTask: task is null");
      return null;
    }

    // 只有 DownloadVidTask 才有 ish265Enable() 方法
    if (!(task instanceof com.ss.ttvideoengine.download.DownloadVidTask)) {
      Log.d(TAG, "getCodecTypeFromTask: task is not DownloadVidTask");
      return null;
    }

    try {
      com.ss.ttvideoengine.download.DownloadVidTask vidTask = (com.ss.ttvideoengine.download.DownloadVidTask) task;
      boolean isH265 = vidTask.ish265Enable();
      int codecType = isH265 ? 2 : 1; // 1=H264, 2=H265
      Log.d(TAG, "getCodecTypeFromTask: success, codecType=" + codecType + " (H" + (isH265 ? "265" : "264") + ")");
      return codecType;
    } catch (Exception e) {
      Log.w(TAG, "getCodecTypeFromTask: exception=" + e.getMessage());
      return null;
    }
  }

}
