use crate::Result;
use std::{fs, path::Path};

cfg_fs_ext! {
  /// 额外接口
  pub mod options;
  pub use options::*;
}
#[cfg(feature = "encode")]
use encoding::{all::GBK, DecoderTrap, Encoding};

/// 主要针对兼容中文
#[cfg(feature = "encode")]
pub fn auto_read_gpk<P>(path: P) -> Result<String>
where
  P: AsRef<Path>,
{
  let _res = String::from_utf8(fs::read(&path)?);
  let res = _res.unwrap_or(
    GBK
      .decode(&fs::read(path)?, DecoderTrap::Strict)
      .map_err(|e| {
        std::io::Error::new(std::io::ErrorKind::InvalidData, format!("GPK解码失败{}", e))
      })?,
  );
  Ok(res)
}

/// 树形目录，返回完整路径的字符串数组
pub fn tree_folder<P>(dir_path: P) -> Result<Vec<String>>
where
  P: AsRef<Path>,
{
  let mut result = Vec::new();
  if dir_path.as_ref().is_dir() {
    // 递归处理目录
    let entries = fs::read_dir(dir_path)?;
    for entry in entries {
      if let Ok(entry) = entry {
        // 获取完整路径
        let file_path = entry.path();
        // 判断是文件还是目录
        if file_path.is_dir() {
          // 如果是目录，递归调用，并将结果合并到当前结果中
          let sub_directory_files = tree_folder(&file_path)?;
          result.extend(sub_directory_files);
        } else {
          // 如果是文件，将完整路径添加到结果中
          if let Some(file_name) = file_path.to_str() {
            result.push(file_name.to_string());
          }
        }
      }
    }
  } else {
    result.push(dir_path.as_ref().display().to_string())
  }
  Ok(result)
}

/// 重命名
pub fn rename_file<P, P2>(src: P, dst: P2) -> Result<()>
where
  P: AsRef<Path>,
  P2: AsRef<Path>,
{
  let src = src.as_ref();
  let dst = dst.as_ref();
  if src.exists() && src.is_file() {
    if dst.exists() && !dst.is_file() {
      Err(format!("目标已存在，并非文件格式 {}", dst.display()).into())
    } else {
      fs::rename(src, dst)?;
      if dst.exists() && dst.is_file() {
        Ok(())
      } else {
        Err(format!("源{} 目标移动失败 {}", src.display(), dst.display()).into())
      }
    }
  } else {
    Err(format!("原始缓存文件不存在 {}", src.display()).into())
  }
}
/// 自动化转换路径
pub fn convert_path(path_str: &str) -> String {
  if cfg!(target_os = "windows") {
    path_str.replace('/', "\\")
  } else {
    String::from(path_str)
  }
}

/// 打开文件夹
#[cfg(feature = "cmd")]
pub fn open_file(path: std::path::PathBuf) -> Result<()> {
  use crate::parse::ParseResult as _;
  let pathname = convert_path(path.to_str().res()?);
  #[cfg(target_os = "macos")]
  crate::system::cmd_spawn("open", ["-R", &pathname], None, false)?;
  #[cfg(target_os = "windows")]
  crate::system::cmd_spawn("explorer.exe", ["/select,", &pathname], None, false)?;
  // https://askubuntu.com/a/31071
  #[cfg(target_os = "linux")]
  crate::system::cmd_spawn("xdg-open", [&pathname], None, false)?;
  Ok(())
}
