import {
  APP_NAME,
  APP_VERSION,
  APP_NAME_TEXT,
  ENABLE_UPGRADE_VIP,
} from "@/config/index";
import {LOGIN_ID_STORAGE_KEY } from '@/xiaolanbenlib/constant'

import Taro, { FileSystemManager } from "@tarojs/taro";
import { error } from "console";
import { useRef, useCallback, useEffect } from "react";

const appTokenKey = `${APP_NAME}+${APP_VERSION}token`;



export const getToken = () => {
  return Taro.getStorageSync(appTokenKey);
};
export const setToken = (value: string) => {
  Taro.setStorageSync(appTokenKey, value);
};
export const removeToken = () => {
  Taro.setStorageSync(appTokenKey, "");
};

export const getSuffix = (filePath: string) => {
  const suffix = filePath.split(".").pop() ?? "";
  return suffix;
};

const chars =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// Use a lookup table to find the index.
const lookup = typeof Uint8Array === "undefined" ? [] : new Uint8Array(256);
for (let i = 0; i < chars.length; i++) {
  lookup[chars.charCodeAt(i)] = i;
}

export const encode = (arraybuffer: ArrayBuffer): string => {
  let bytes = new Uint8Array(arraybuffer),
    i,
    len = bytes.length,
    base64 = "";

  for (i = 0; i < len; i += 3) {
    base64 += chars[bytes[i] >> 2];
    base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
    base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
    base64 += chars[bytes[i + 2] & 63];
  }

  if (len % 3 === 2) {
    base64 = base64.substring(0, base64.length - 1) + "=";
  } else if (len % 3 === 1) {
    base64 = base64.substring(0, base64.length - 2) + "==";
  }

  return base64;
};

export const decode = (base64: string): ArrayBuffer => {
  let bufferLength = base64.length * 0.75,
    len = base64.length,
    i,
    p = 0,
    encoded1,
    encoded2,
    encoded3,
    encoded4;

  if (base64[base64.length - 1] === "=") {
    bufferLength--;
    if (base64[base64.length - 2] === "=") {
      bufferLength--;
    }
  }

  const arraybuffer = new ArrayBuffer(bufferLength),
    bytes = new Uint8Array(arraybuffer);

  for (i = 0; i < len; i += 4) {
    encoded1 = lookup[base64.charCodeAt(i)];
    encoded2 = lookup[base64.charCodeAt(i + 1)];
    encoded3 = lookup[base64.charCodeAt(i + 2)];
    encoded4 = lookup[base64.charCodeAt(i + 3)];

    bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
    bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
    bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
  }

  return arraybuffer;
};

export function throttle(func: Function, delay: number): Function {
  let timer: NodeJS.Timeout | null = null;
  return function (...args: any[]) {
    if (!timer) {
      func.apply(this, args);
      timer = setTimeout(() => {
        timer = null;
      }, delay);
    }
  };
}

export function debounce(func: Function, delay: number): Function {
  let timer: NodeJS.Timeout | null = null;
  return function (...args: any[]) {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      func.apply(this, args);
      timer = null;
    }, delay);
  };
}

/**
 * 自定义Hook实现debounce功能
 * @param value 要延迟的值
 * @param delay 延迟时间（毫秒）
 * @returns 经过debounce处理后的值
 */
export function useDebounce(fn: () => void, delay: number) {
  const timer = useRef<null | ReturnType<typeof setTimeout>>(null);
  return () => {
    timer.current && clearTimeout(timer.current);
    timer.current = setTimeout(fn, delay);
  };
}

// 修改 useDebounce 使其支持任意参数
export function useDebounceWithParams<T extends (...args: any[]) => any>(
  fn: T,
  delay: number
): T {
  const timerRef = useRef<NodeJS.Timeout | null>(null);

  return useCallback(
    (...args: Parameters<T>) => {
      if (timerRef.current) {
        clearTimeout(timerRef.current);
      }

      timerRef.current = setTimeout(() => {
        fn(...args);
      }, delay);
    },
    [fn, delay]
  ) as T;
}



export const formatDate = (date: Date): string => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
};

export const formatDateFull = (date: Date): string => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0"); // 月份从 0 开始，所以加 1
  const day = String(date.getDate()).padStart(2, "0");
  const hours = String(date.getHours()).padStart(2, "0");
  const minutes = String(date.getMinutes()).padStart(2, "0");

  return `${year}-${month}-${day} ${hours}:${minutes}`;
};

export const formatSeconds = (seconds: number): string => {
  // 计算分钟数
  const minutes = Math.floor(seconds / 60);
  // 计算剩余的秒数
  const remainingSeconds = seconds % 60;

  // 确保分钟和秒都以两位数的形式显示
  const formattedMinutes = String(minutes).padStart(2, "0");
  const formattedSeconds = String(remainingSeconds).padStart(2, "0");

  // 返回格式化的字符串
  return `${formattedMinutes}:${formattedSeconds}`;
};

// 是否是中文字符
export function isChineseChatacter(str: string): boolean {
  const code = str.charCodeAt(0);
  if (
    (code >= 0x4e00 && code <= 0x9fff) ||
    (code >= 0x3400 && code <= 0x4dbf) ||
    (code >= 0x20000 && code <= 0x2a6df) ||
    (code >= 0x2a700 && code <= 0x2b73f) ||
    (code >= 0x2b740 && code <= 0x2b81f) ||
    (code >= 0x2b820 && code <= 0x2ceaf) ||
    (code >= 0xf900 && code <= 0xfaff) ||
    (code >= 0x2f800 && code <= 0x2fa1f)
  ) {
    return true;
  }

  return false;
}

export function countCharacters(str: string): number {
  let count = 0;
  const arr = Array.from(str);
  for (let i = 0, j = arr.length; i < j; i++) {
    // 判断是否为中文字符
    if (isChineseChatacter(arr[i])) {
      count += 1;
    } else {
      // 英文字符每两个算一个
      count += 0.5;
    }
  }

  return Math.ceil(count);
}

export const getStrByMaxLength = (str: string, length: number) => {
  const arr = Array.from(str);
  let result = "";
  let l = 0;
  for (let i = 0, j = arr.length; i < j; i++) {
    const s = arr[i];
    if (isChineseChatacter(s)) {
      l += 1;
    } else {
      l += 0.5;
    }
    result += s;
    if (Math.ceil(l) >= length) {
      return result;
    }
  }
  return result;
};

export const navToWebView = (url: string) => {
  Taro.navigateTo({
    url: `/pages/webview/index?url=${encodeURIComponent(url)}`,
  });
};

export const getCanvasTempPath = (
  canvas: any,
  canvasId: string
): Promise<string> => {
  return new Promise((resolve, reject) => {
    Taro.canvasToTempFilePath(
      {
        x: 0,
        y: 0,
        fileType: "jpg",
        quality: 0.8,
        canvas: canvas,
        canvasId: canvasId,
        success: (res) => {
          console.log(res, res.tempFilePath);
          resolve(res.tempFilePath);
          // wx.showToast({
          // 	title: 'canvas转图成功' + res.tempFilePath,
          // 	duration: 3000
          // })
        },
        fail: (res) => {
          console.log(res);
          Taro.showToast({
            title: "canvas转图片失败" + JSON.stringify(res),
            icon: "none",
            duration: 3000,
          });
          reject("");
        },
      },
      this
    );
  });
};

export const saveMediaFile = async (tmpPath: string, isVideo: boolean = false): Promise<boolean> => {
  return new Promise((resove) => {
    const params = {
      filePath: tmpPath,
      success() {
        console.log("save success");
        resove(true);
      },
      fail(error: any) {
        console.log("save fail", error);
        resove(false);
      },
    };
    isVideo ? Taro.saveVideoToPhotosAlbum(params) : Taro.saveImageToPhotosAlbum(params);
  });
};

export const getCloneVoiceIdentifier = (number: number): string => {
  const formattedNumber = number.toString().padStart(2, "0");

  return `克隆声音${formattedNumber}`;
};

export const navToVip = () => {
  if (ENABLE_UPGRADE_VIP) {
    Taro.navigateTo({ url: "/pages/vip/index" });
    return;
  }
  Taro.showModal({
    content: "此功能暂不可用",
    showCancel: false,
  });
};

export const getTempFileContent = <T>(
  tmpPath: string,
  encoding?: keyof FileSystemManager.Encoding
): Promise<T> => {
  return new Promise((resolve, reject) => {
    const fs = Taro.getFileSystemManager();
    fs.readFile({
      filePath: tmpPath,
      encoding: encoding,
      success: (res) => {
        const fileContent = res.data as T;
        // console.log(
        //   "%c [ fileContent ]: ",
        //   "color: #bf2c9f; background: pink; font-size: 13px;",
        //   fileContent
        // );
        resolve(fileContent);
      },
      fail: (err) => {
        console.error("读取文件失败", err);
        reject(err);
      },
    });
  });
};


export const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

export function generateRandomId(): string {
  const timestamp = Date.now().toString(36); // 当前时间戳转换为 base-36 字符串
  const randomNum = Math.random().toString(36).substring(2, 8); // 生成随机数并转换为 base-36 字符串
  return `${timestamp}-${randomNum}`; // 组合时间戳和随机数
}


/**
 * 生成符合 RFC 4122 版本 4 的 UUID
 * @returns 格式为 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' 的 UUID 字符串
 */
export function generateUUID(): string {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0;
    const v = c === 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}



export const pickNonEmpty = <T extends object>(obj: T): Partial<T> => {
  return Object.fromEntries(
    Object.entries(obj).filter(([_, value]) =>
      value !== "" && value != null
    )
  ) as Partial<T>;
};

export const getLoginId = () => {
  return Taro.getStorageSync(LOGIN_ID_STORAGE_KEY) // 打开小程序时创建 login_uuid
}

export const isSuccess = (status: number)=> {
  return status >= 200 && status < 300
}

/**
 * 文件大小单位类型
 */
export type FileSizeUnit = 'bit' | 'B' | 'KB' | 'MB' | 'GB' | 'TB';

/**
 * 文件大小转换配置
 */
export interface FileSizeOptions {
  /** 保留小数位数，默认2位 */
  precision?: number;
  /** 是否使用二进制单位（1024进制），默认为true */
  binary?: boolean;
  /** 强制转换为指定单位，不自动选择 */
  unit?: FileSizeUnit;
  /** 是否添加单位后缀，默认为true */
  withUnit?: boolean;
}

/**
 * 文件大小转换工具
 * @param size 文件大小（bit）
 * @param options 转换配置
 * @returns 转换后的文件大小字符串或数字
 */
export function convertFileSize(size: number, options: FileSizeOptions = {}): string | number {
  const {
    precision = 2,
    binary = true,
    unit,
    withUnit = true
  } = options;

  // 检查输入是否为有效数字
  if (isNaN(size) || !isFinite(size)) {
    return withUnit ? 'Invalid size' : NaN;
  }

  // 处理零值
  if (size === 0) {
    return withUnit ? `0${unit || 'B'}` : 0;
  }

  // 计算转换基数
  const base = binary ? 1024 : 1000;

  // 定义单位列表
  const units: FileSizeUnit[] = ['bit', 'B', 'KB', 'MB', 'GB', 'TB'];

  // 如果指定了单位，直接转换
  if (unit) {
    const targetIndex = units.indexOf(unit);

    // 特殊处理bit到B的转换（1字节=8比特）
    if (unit === 'B') {
      size = size / 8;
    } else if (unit === 'bit') {
      // 如果目标是bit，直接返回原始值
      return withUnit ? `${size} bit` : size;
    }

    // 计算从B到目标单位的转换
    if (targetIndex > 1) {
      size = size / 8 / Math.pow(base, targetIndex - 1);
    }

    const result = Number(size.toFixed(precision));
    return withUnit ? `${result} ${unit}` : result;
  }

  // 特殊处理bit和B
  if (size < 8) {
    return withUnit ? `${size} bit` : size;
  }

  if (size < base * 8) {
    const result = Number((size / 8).toFixed(precision));
    return withUnit ? `${result} B` : result;
  }

  // 自动选择合适的单位
  let unitIndex = 2; // 从KB开始
  let convertedSize = size / 8; // 先转换为字节

  while (convertedSize >= base && unitIndex < units.length - 1) {
    convertedSize /= base;
    unitIndex++;
  }

  const result = Number(convertedSize.toFixed(precision));
  return withUnit ? `${result} ${units[unitIndex]}` : result;
}
//
export const pxToRpx = (px: number) => {
  const systemInfo = Taro.getSystemInfoSync()
  return (750 / systemInfo.windowWidth) * px
}



/**
 * 为图片URL添加阿里云OSS处理参数
 * 如果URL中不包含?x-oss-process=，则添加?x-oss-process=image/quality,Q_60/format,jpg
 * 如果URL中已包含其他查询参数，则追加&x-oss-process=image/quality,Q_60/format,jpg
 * @param url 原始图片URL
 * @returns 处理后的图片URL
 */
export function addOssProcessLowQualityParam(url: string): string {
  // 检查URL是否有效
  if (!url || typeof url !== 'string') {
    return url;
  }

  // 检查是否已经包含OSS处理参数
  if (url.includes('x-oss-process=')) {
    return url;
  }

  // 分离URL和查询参数
  const [baseUrl, existingQuery] = url.split('?');

  // 构建新的查询参数
  const ossParam = 'x-oss-process=image/quality,Q_60/format,jpg';
  const newQuery = existingQuery
    ? `${existingQuery}&${ossParam}`  // 已有查询参数，追加OSS参数
    : ossParam;                       // 没有查询参数，直接使用OSS参数

  // 返回处理后的URL
  return `${baseUrl}?${newQuery}`;
}

// 使用示例
// const exampleUrl1 = "https://example.com/image.jpg";
// const exampleUrl2 = "https://example.com/image.png?width=200&height=200";
// const exampleUrl3 = "https://example.com/image.webp?x-oss-process=image/resize,w_300";

// console.log(addOssProcessParam(exampleUrl1));
// // 输出: https://example.com/image.jpg?x-oss-process=image/quality,Q_60/format,jpg

// console.log(addOssProcessParam(exampleUrl2));
// // 输出: https://example.com/image.png?width=200&height=200&x-oss-process=image/quality,Q_60/format,jpg

// console.log(addOssProcessParam(exampleUrl3));
// // 输出: https://example.com/image.webp?x-oss-process=image/resize,w_300 (保持不变，因为已包含OSS参数)


export function restrictedPage() {
  // 方式一：不定义分享相关函数，默认就是禁止分享
  // 方式二：显式返回不允许分享（两种分享方式都要处理）
  useEffect(() => {
    // 禁止单页分享
    Taro.showShareMenu({
      withShareTicket: false,
      menus: []  // 不提供任何分享菜单
    })

    // 禁止分享到朋友圈
    Taro.hideShareMenu({
      menus: ['shareAppMessage', 'shareTimeline']
    })
  }, [])
}
