import { AegisReportInPixui } from 'pixui-runtime';
import { safeJsonParse } from 't-comm/es/json/json-parse';
import { GameletAPI } from 'gamelet-pixui-frame';

import { checkI18n } from '../i18n/check';

/**
 * 最小安全边距（单位：px）
 * 当从客户端获取的边距小于此值时，使用此值作为最小保证
 */
const ORIGIN_PADDING = 44;

/**
 * px 转 rem 的转换比例
 * 计算公式：rem = px * PX_TO_REM_RATIO
 */
const PX_TO_REM_RATIO = 2 / 100;

const originData = {
  left: 0,
  top: 0,
  right: 0,
  bottom: 0,
};

const safeDistance = {
  data: originData,
  isReady: false, // 标记数据是否已经获取完成
  readyPromise: null as Promise<void> | null, // 用于等待数据准备完成
  resolveReady: null as (() => void) | null, // resolve 函数
  listeners: [] as Array<() => void>, // 数据变化监听器列表
  get() {
    return this.data;
  },
  set(data) {
    this.data = data;
    this.isReady = true;
    if (this.resolveReady) {
      this.resolveReady();
    }
    // 通知所有监听器数据已更新
    this.listeners.forEach(listener => listener());
  },
  // 订阅数据变化
  subscribe(listener: () => void) {
    this.listeners.push(listener);
    // 返回取消订阅函数
    return () => {
      const index = this.listeners.indexOf(listener);
      if (index > -1) {
        this.listeners.splice(index, 1);
      }
    };
  },
};


export async function tryGetSafeAreaInfo() {
  // 如果已经初始化过，直接返回
  if (safeDistance.isReady) {
    return;
  }

  // 创建一个 Promise 用于等待数据返回
  if (!safeDistance.readyPromise) {
    safeDistance.readyPromise = new Promise((resolve) => {
      safeDistance.resolveReady = resolve;
    });
  }

  GameletAPI.addOnGameCommandListener((msg) => {
    setTimeout(() => {
      AegisReportInPixui.report({
        msg: 'GAME_COMMAND_0',
        params: {
          msg,
        },
      });
    }, 3000);

    const ret = safeJsonParse(msg);
    setTimeout(() => {
      AegisReportInPixui.report({
        msg: 'GAME_COMMAND_1',
        params: {
          msg,
          ret,
        },
      });
    }, 3000);

    if (ret && ret.type === 'GetMarginRtn') {
      const margin = (ret.content || '').split(',').map(val => parseInt(val, 10));

      setTimeout(() => {
        AegisReportInPixui.report({
          msg: 'GAME_COMMAND_SAFE_AREA_INFO',
          params: {
            msg,
            ret,
            margin,
          },
        });
      }, 3000);

      safeDistance.set({
        left: margin[0],
        top: margin[1],
        right: margin[2],
        bottom: margin[3],
      });
    }
  });

  GameletAPI.callGame(JSON.stringify({
    type: 'GetMargin',
    appid: GameletAPI.getAppID(),
    appId: GameletAPI.getAppID(),
    appName: GameletAPI.getAppName(),
  }));

  // 等待数据返回，最多等待 3 秒
  await Promise.race([
    safeDistance.readyPromise,
    new Promise(resolve => setTimeout(resolve, 3000)),
  ]);
}

// 模块加载时自动初始化 Safe Area 数据
// 这样所有页面导入时，数据获取就已经在后台进行了
tryGetSafeAreaInfo().catch((err) => {
  console.error('Failed to initialize Safe Area:', err);
});

/**
 * 订阅 Safe Area 数据变化
 * 当数据更新时会调用回调函数
 *
 * @param callback - 数据变化时的回调函数
 * @returns 取消订阅的函数
 *
 * @example
 * const unsubscribe = subscribeSafeAreaChange(() => {
 *   console.log('Safe Area data updated');
 * });
 * // 取消订阅
 * unsubscribe();
 */
export function subscribeSafeAreaChange(callback: () => void) {
  return safeDistance.subscribe(callback);
}

/**
 * 检查 Safe Area 数据是否已准备好
 *
 * @returns 数据是否已准备好
 */
export function isSafeAreaReady() {
  return safeDistance.isReady;
}

/**
 * px 转 rem
 * @param px - 像素值
 * @returns rem 字符串（如 "1rem"）
 */
function pxToRem(px: number): string {
  return `${(px * PX_TO_REM_RATIO).toFixed(2)}rem`;
}

/**
 * 计算实际的 padding 值（确保不小于最小安全边距）
 * @param left - 左边距原始值
 * @param right - 右边距原始值
 * @returns 计算后的左右 padding 值
 */
function calculatePadding(left: number, right: number) {
  return {
    paddingLeft: Math.max(left, ORIGIN_PADDING),
    paddingRight: Math.max(right, ORIGIN_PADDING),
  };
}

/**
 * 检查当前语言是否为 RTL（从右到左）
 */
export function isRTLLanguage(): boolean {
  const { lang } = checkI18n();
  return lang === 'ur' || lang === 'ar';
}

/**
 * 获取 safe area 左右 padding 样式，返回可直接用于 style 属性的对象
 * import { getSafeAreaStyle } from 'src/local-logic/utils/safe-area';
 *
 * @param options - 可选配置
 * @param options.left - 是否包含 paddingLeft，默认 true
 * @param options.right - 是否包含 paddingRight，默认 true
 * @param options.position - 定位方式，'left' 或 'right'
 *
 * @example
 * // 直接用于 style 属性（左右都设置）
 * <div style={getSafeAreaStyle()}>...</div>
 *
 * // 只设置左边距
 * <div style={getSafeAreaStyle({ right: false })}>...</div>
 *
 * // 只设置右边距
 * <div style={getSafeAreaStyle({ left: false })}>...</div>
 *
 * // 设置定位 left
 * <div style={getSafeAreaStyle({ position: 'left' })}>...</div>
 *
 * // 设置定位 right
 * <div style={getSafeAreaStyle({ position: 'right' })}>...</div>
 *
 * // 或者与其他样式合并
 * <div style={{ ...getSafeAreaStyle(), backgroundColor: 'red' }}>...</div>
 */
export function getSafeAreaStyle(options?: { left?: boolean; right?: boolean; position?: 'left' | 'right' }) {
  const { left, right } = safeDistance.data;
  const { paddingLeft, paddingRight } = calculatePadding(left, right);

  let result: Record<string, string> = {};

  // 转换为 rem
  const leftRem = pxToRem(paddingLeft);
  const rightRem = pxToRem(paddingRight);

  // 如果指定了 position，只返回对应方位的定位值
  if (options?.position === 'left') {
    result = { left: leftRem };
  } else if (options?.position === 'right') {
    result = { right: rightRem };
  } else {
    // 没有指定 position，按照 left/right 选项设置 padding
    const includeLeft = options?.left !== false;
    const includeRight = options?.right !== false;

    if (includeLeft) {
      result = { ...result, paddingLeft: leftRem };
    }
    if (includeRight) {
      result = { ...result, paddingRight: rightRem };
    }
  }

  return result;
}

/**
 * 获取 safe area 原始数据和处理后的 padding 值
 * import { getSafeAreaInfo } from 'src/local-logic/utils/safe-area';
 *
 * @example
 * const safeArea = getSafeAreaInfo();
 * // 返回值包含：
 * // { left, top, right, bottom, paddingLeft, paddingTop, paddingRight, paddingBottom }
 */
export function getSafeAreaInfo() {
  const { left, top, right, bottom } = safeDistance.data;

  const { paddingLeft, paddingRight } = calculatePadding(left, right);

  return {
    left,
    top,
    right,
    bottom,
    paddingLeft,
    paddingTop: top,
    paddingRight,
    paddingBottom: bottom,
  };
}
