import { removeQs } from "./tools";
import { checkIsVideoUrl } from "./video";

// 图片展示类型
export const SQUARE = 'square';
export const LANDSCAPE = 'landscape';
export const PORTRAIT = 'portrait';
export const LONG = 'LONG';

// 从图片 URL 解析出图片尺寸
export function getSize(url) {
  const RE_PARSE = /\/[^\\/]*w_((?:\d|.)+)@h_(\d+)[^\\/]+$/;
  const re = url.match(RE_PARSE);

  if (re) {
    return {
      width: Number(re[1]),
      height: Number(re[2])
    };
  }

  return null;
}

export function getImageType(url) {
  const size = getSize(url);

  // 无法从 url 中解析出尺寸的，统一用正方形处理
  if (!size) {
    return SQUARE;
  }

  const { width, height } = size;

  if (width > height) {
    return LANDSCAPE;
  } else if (height > width) {
    if (height / width >= 3) {
      return LONG;
    }

    return PORTRAIT;
  }

  return SQUARE;
}

export enum OssImageResizeMode {
  lfit = 'lfit', // 等比缩放，限制在设定在指定w与h的矩形内的最大图片, 图片不会被裁剪
  mfit = 'mfit', // 等比缩放，延伸出指定w与h的矩形框外的最小图片，图片不会被裁剪
  fill = 'fill', // 将原图等比缩放为延伸出指定w与h的矩形框外的最小图片，之后将超出的部分进行居中裁剪。
  pad = 'pad', // 将原图缩放为指定w与h的矩形内的最大图片，之后使用指定颜色居中填充空白部分。
  fixed = 'fixed', // 固定宽高，强制缩放
  none = 'none' // 不缩放
}

enum ImageResizeLimit {
  notLimit = 0, // 不限制，按指定参数进行缩放。
  limit = 1 // 限制，当目标图片分辨率大于原图分辨率时，返回按照原图分辨率转换的图片（可能和原图的体积不一样）。
}

export interface Params {
  m?: OssImageResizeMode; // 缩放模式
  w?: number; // 宽度
  h?: number; // 高度
  limit?: ImageResizeLimit; // 当目标图片分辨率大于原图分辨率时，是否进行缩放，默认不缩放，保持原有大小
  q?: number;
  f?: string;
  crop?: boolean; // 是否裁剪, 如果传 true 并且 w h 都有值，则会裁剪
  interlace?: boolean; // 是否渐进显示，只在 f 为 jpg 时有效
  bright?: number; // 亮度, -100 ~ 100, <0 变暗, >0 变亮
}

/**
 * 检查图片链接是否有签名，有签名的图片链接不能进行修改，例如私有图片就需要签名访问
 * @param url 图片链接
 * @returns
 */
export function checkHasSignature(url: string): boolean {
  if (typeof url !== 'string') return false;
  return url.includes('Signature=') || url.includes('signature=');
}

/***************************************************
 * 从 url 中获取图片的宽高
 ***************************************************/
interface ImgSize {
  width: number;
  height: number;
}

/**
 * 从 url 中获取图片的宽高，注意有可能获取不成功
 */
export function getMediaSizeFromUrl(
  url: string,
  defaultSize: ImgSize = {
    width: 300,
    height: 300
  }
): ImgSize & { success: boolean } {
  const size = { ...defaultSize, success: false };
  if (!url) return size;
  try {
    const reg = /_w_(\d+)@h_(\d+)/;
    const matches = url.match(reg);
    if (matches && matches.length === 3) {
      size.width = parseInt(matches[1]);
      size.height = parseInt(matches[2]);
      size.success = true;
    }
  } catch (error) {
    console.error('getMediaSizeFromUrl error-->:', url, error);
  }
  return size;
}

/**
 * 检查是否是 gif 图片
 * @param url
 * @returns
 */
export const checkIsGif = (url: string) => {
  if (!url) return false;
  const reg = /\.(gif)$/i;
  return reg.test(removeQs(url));
};

/**
 * 检查是否是 webp 图片
 * @param url
 * @returns
 */
export const checkIsWebp = (url: string) => {
  if (!url) return false;
  const reg = /\.(webp)$/i;
  return reg.test(removeQs(url));
};




export function formatImageUrl(url: string, params: Params = {}): string {
  if (checkIsVideoUrl(url)) return url; // 不处理视频截帧
  if (checkHasSignature(url)) return url; // 有签名的图片链接不处理，一般是私有链接
  if (checkIsGif(url) || checkIsWebp(url)) return url; // gif 、webp 有可能是动图，不处理，webp 越压越大，gif 压了变静态图

  url = removeQs(url); // 标准化图片链接

  if (!url) {
    return url;
  }

  let {
    m = OssImageResizeMode.mfit,
    w = 750, // 图片质量不要设置得太高，测试过 1125 在安卓、ios 下都会卡顿
    q = 85,
    f = 'webp'
  } = params;
  const {
    h,
    limit = 1,
    crop = false,
    interlace = true,
    bright = 0 // 暗模式下默认降低亮度
  } = params;

  // 对没有裁切的超大图片的参数进行参数修正，避免阿里云转换失败或者超大图导致 app 崩溃
  const noResize = !m || m === OssImageResizeMode.none;
  if (noResize) {
    const imgSize = getMediaSizeFromUrl(url);
    const isHugeImage =
      imgSize.success && (imgSize.width >= 16383 || imgSize.height >= 16383); // 转成 webp 格式需要注意图片宽高不能超过 16383 像素,阿里云限制
    if (isHugeImage) {
      f = ''; // 超大图片不转成 webp, 防止转换失败
      m = OssImageResizeMode.mfit; // 超大图片要进行裁剪，不然容易导致 App 崩溃
      w = Math.min(imgSize.width, 2000); // 超大图片宽度限制为 2000
      q = Math.min(q, 85); // 超大图片质量限制为 85
    }
  }

  // 图片缩放
  let resizeStr = ''; // 例如 /resize,m_lfit,w_100,h_100,limit_0
  if (m && m !== OssImageResizeMode.none && (w || h)) {
    resizeStr = `/resize`;

    if (m) {
      resizeStr = `${resizeStr},m_${m}`;
    }

    if (w) {
      resizeStr = `${resizeStr},w_${w}`;
    }

    if (h) {
      resizeStr = `${resizeStr},h_${h}`;
    }

    if (typeof limit !== 'undefined') {
      resizeStr = `${resizeStr},limit_${limit}`;
    }
  }

  // 裁剪参数
  let cropStr = '';
  if (crop && w > 0 && h && h > 0) {
    cropStr = `/crop,w_${w},h_${h},g_center`;
  }

  // 图片格式，默认使用 webp, 例如 /format,jpg
  let fotmatStr = '';
  let interlaceStr = '';
  if (typeof f === 'string' && f) {
    fotmatStr = `/format,${f}`;
    if (f === 'jpg' && interlace) {
      interlaceStr = '/interlace,1';
    }
  }

  // 图片质量，默认 75，例如 /quality,q_75
  let qualityStr = '';
  if (q) {
    qualityStr = `/quality,Q_${q}`;
  }

  // 亮度
  let brightStr = '';
  if (
    typeof bright === 'number' &&
    bright !== 0 &&
    bright >= -100 &&
    bright <= 100
  ) {
    brightStr = `/bright,${bright}`;
  }

  const formatedUrl = `${url}?x-oss-process=image${resizeStr}${cropStr}${qualityStr}${brightStr}${fotmatStr}${interlaceStr}`; // fotmatStr 放在最后，因为有些格式不支持某些操作，所以图片转换放最后

  // console.log('formatedUrl-->:', formatedUrl);

  return formatedUrl;
}


/**
 * 阿里云视频截帧参数
 * t: 截图时间(ms)，默认0表示封面
 * w: 截图宽度，0则按高同比例缩放
 * h: 截图高度，0则按宽同比例缩放；w与h都为0则使用源视频尺寸
 * m: 截图模式: fast(取 <= t 的最近关键帧)；不传=精确到时间点
 * f: 输出格式: jpg | png
 * ar: 旋转: auto | h | w
 */
export interface VideoSnapshotParams {
  t?: number;          // 毫秒
  w?: number;          // 像素
  h?: number;          // 像素
  m?: 'fast';
  f?: 'jpg' | 'png';
  ar?: 'auto' | 'h' | 'w';
}

/**
 * 生成阿里云视频封面(截帧) URL
 * @param url 原始视频 URL
 * @param params 截图参数
 * @returns 拼接后的可访问图片 URL
 */
export function formatVideoSnapshotUrl(
  url: string,
  params: VideoSnapshotParams = {}
): string {
  if (!url) return url;

  // 保留原签名/已有处理
  if (checkHasSignature(url) || /[?&]x-oss-process=/.test(url)) {
    return url;
  }

  const clean = removeQs(url);

  let {
    t = 0,
    w = 0,
    h = 0,
    m,
    f = 'jpg',
    ar
  } = params;

  // 规范范围保护
  if (t < 0) t = 0;
  if (w < 0) w = 0;
  if (h < 0) h = 0;

  const segs: string[] = [];
  segs.push(`t_${t}`);
  segs.push(`f_${f}`);

  if (w !== 0) segs.push(`w_${w}`);
  if (h !== 0) segs.push(`h_${h}`);
  if (m) segs.push(`m_${m}`);
  if (ar) segs.push(`ar_${ar}`);

  return `${clean}?x-oss-process=video/snapshot,${segs.join(',')}`;
}




export default {
  getSize,
  getImageType,
  formatImageUrl,
  formatVideoSnapshotUrl,
  SQUARE,
  LANDSCAPE,
  PORTRAIT,
  LONG
};
