import type { SkuConfig, SkuList } from '@/services/prod/prod-manager';

/**
 * @param str 需要转驼峰的下划线字符串
 * @returns 字符串驼峰
 */
export const underlineToHump = (str: string): string => {
  if (!str) return '';
  return str.replace(/-(\w)/g, (_, letter: string) => {
    return letter.toUpperCase();
  });
};

export const setCssVar = (
  prop: string,
  val: any,
  dom = document.documentElement,
) => {
  dom.style.setProperty(prop, val);
};

/**
 * @param str 需要转下划线的驼峰字符串
 * @returns 字符串下划线
 */
export const humpToUnderline = (str: string): string => {
  return str.replace(/([A-Z])/g, '-$1').toLowerCase();
};

// copy to vben-admin

const objectToString = Object.prototype.toString;

export const is = (val: unknown, type: string) => {
  return objectToString.call(val) === `[object ${type}]`;
};

export const isDef = <T = unknown>(val?: T): val is T => {
  return typeof val !== 'undefined';
};

export const isUnDef = <T = unknown>(val?: T): val is T => {
  return !isDef(val);
};

export const isObject = (val: any): val is Record<any, any> => {
  return val !== null && is(val, 'Object');
};

export const isEmpty = (val: any): boolean => {
  if (val === null || val === undefined || typeof val === 'undefined') {
    return true;
  }
  if (isArray(val) || isString(val)) {
    return val.length === 0;
  }

  if (val instanceof Map || val instanceof Set) {
    return val.size === 0;
  }

  if (isObject(val)) {
    return Object.keys(val).length === 0;
  }

  return false;
};

export const isDate = (val: unknown): val is Date => {
  return is(val, 'Date');
};

export const isNull = (val: unknown): val is null => {
  return val === null;
};

export const isNullAndUnDef = (val: unknown): val is null | undefined => {
  return isUnDef(val) && isNull(val);
};

export const isNullOrUnDef = (val: unknown): val is null | undefined => {
  return isUnDef(val) || isNull(val);
};

export const isNumber = (val: unknown): val is number => {
  return is(val, 'Number');
};

export const isPromise = <T = any>(val: unknown): val is Promise<T> => {
  return (
    is(val, 'Promise') &&
    isObject(val) &&
    isFunction(val.then) &&
    isFunction(val.catch)
  );
};

export const isString = (val: unknown): val is string => {
  return is(val, 'String');
};

export const isFunction = (val: unknown): val is (...args: any[]) => any => {
  return typeof val === 'function';
};

export const isBoolean = (val: unknown): val is boolean => {
  return is(val, 'Boolean');
};

export const isRegExp = (val: unknown): val is RegExp => {
  return is(val, 'RegExp');
};

export const isArray = (val: any): val is Array<any> => {
  return val && Array.isArray(val);
};

export const isWindow = (val: any): val is Window => {
  return typeof window !== 'undefined' && is(val, 'Window');
};

export const isElement = (val: unknown): val is Element => {
  return isObject(val) && !!val.tagName;
};

export const isMap = (val: unknown): val is Map<any, any> => {
  return is(val, 'Map');
};

export const isServer = typeof window === 'undefined';

export const isClient = !isServer;

export const isUrl = (path: string): boolean => {
  // fix:修复hash路由无法跳转的问题
  const reg =
    /(((^https?:(?:\/\/)?)(?:[-:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%#/.\w-_]*)?\??(?:[-+=&%@.\w_]*)#?(?:[\w]*))?)$/;
  return reg.test(path);
};

export const isDark = (): boolean => {
  return window.matchMedia('(prefers-color-scheme: dark)').matches;
};

// 是否是图片链接
export const isImgPath = (path: string): boolean => {
  return /(https?:\/\/|data:image\/).*?\.(png|jpg|jpeg|gif|svg|webp|ico)/gi.test(
    path,
  );
};

export const isEmptyVal = (val: any): boolean => {
  return val === '' || val === null || val === undefined;
};
export const isExternal = (path: string): boolean => {
  return /https?/.test(path);
};

/**
 * 查找数组对象的某个下标
 * @param {Array} ary 查找的数组
 * @param {Functon} fn 判断的方法
 */
// eslint-disable-next-line
export const findIndex = <T = Recordable>(ary: Array<T>, fn: Fn): number => {
  if (ary.findIndex) {
    return ary.findIndex(fn);
  }
  let index = -1;
  ary.some((item: T, i: number, ary: Array<T>) => {
    const ret: T = fn(item, i, ary);
    if (ret) {
      index = i;
      return true;
    }
    return false;
  });
  return index;
};

// 笛卡尔积函数

function cartesianProduct<T>(...arrays: T[][]): T[][] {
  return arrays.reduce(
    (acc, curr) => {
      const result: T[][] = [];
      acc.forEach((a) => {
        curr.forEach((c) => {
          result.push([...a, c]);
        });
      });
      return result;
    },
    [[]] as T[][],
  );
}

export function generateSkuTableData(data: SkuConfig[]): SkuList[] {
  // 过滤掉prodPropValues为空的配置
  const validData = data.filter((config) => config.prodPropValues.length > 0);

  // 如果所有配置都被过滤掉了，返回空数组
  if (validData.length === 0) {
    return [];
  }

  const propValueArrays = validData.map((config) => config.prodPropValues);
  const combinations = cartesianProduct<{
    propValue: string;
    valueId?: number;
    state?: number;
    isExist?: number;
  }>(...propValueArrays);

  return combinations.map((combination, index) => {
    const skuItem: SkuList = {
      skuName: combination.map((item) => item.propValue).join(','),
      basePrice: 0,
      isSpecs: index === 0 ? 1 : 0,
      status: 1,
      stocks: 0,
      isShelf: 1,
      // propIds: combination.map((item) => item.valueId).join(",")
    };

    // 只添加有效配置的动态属性
    validData.forEach((config, configIndex) => {
      (skuItem as any)[config.propName] = combination[configIndex].propValue;
    });

    return skuItem;
  });
}

// 根据删除的SKU规格更新data状态
function updateDataByDeletedSku(
  data: SkuConfig[],
  deletedSkuName: string,
): SkuConfig[] {
  // 解析删除的SKU名称，获取各个属性值
  const deletedValues = deletedSkuName.split(',').map((v) => v.trim());

  // 深拷贝data以避免修改原数据
  const updatedData = JSON.parse(JSON.stringify(data)) as SkuConfig[];

  // 遍历每个属性配置
  updatedData.forEach((config, configIndex) => {
    if (configIndex < deletedValues.length) {
      const targetValue = deletedValues[configIndex];

      // 找到对应的属性值并设置为失效
      config.prodPropValues.forEach(
        (propValue: {
          propValue: string;
          state?: number;
          isExist?: number;
        }) => {
          if (propValue.propValue === targetValue) {
            propValue.state = 0; // 设置为失效
            propValue.isExist = 0; // 设置为不存在
          }
        },
      );
    }
  });

  return updatedData;
}

// 批量处理多个删除的SKU
function _updateDataByDeletedSkus(
  data: SkuConfig[],
  deletedSkuNames: string[],
): SkuConfig[] {
  let updatedData = JSON.parse(JSON.stringify(data)) as SkuConfig[];

  deletedSkuNames.forEach((skuName) => {
    updatedData = updateDataByDeletedSku(updatedData, skuName);
  });

  return updatedData;
}

// 根据属性名和属性值直接设置失效状态
function _updateDataByPropValue(
  data: SkuConfig[],
  propName: string,
  propValue: string,
  state: 0 | 1 = 0,
): SkuConfig[] {
  const updatedData = JSON.parse(JSON.stringify(data)) as SkuConfig[];

  const targetConfig = updatedData.find(
    (config) => config.propName === propName,
  );
  if (targetConfig) {
    const targetPropValue = targetConfig.prodPropValues.find(
      (pv: {
        propValue: string;
        state?: number;
        isExist?: number;
        isExpire?: number;
      }) => pv.propValue === propValue,
    );
    if (targetPropValue) {
      targetPropValue.state = state;
      targetPropValue.isExist = state;
    }
  }

  return updatedData;
}

// 重新生成有效的SKU列表（过滤掉失效的属性值）
export function generateValidSkuTableData(data: SkuConfig[]): SkuList[] {
  console.log(data);
  // 过滤出有效的属性值
  const validData = data
    .map((config) => ({
      ...config,
      prodPropValues: config.prodPropValues.filter(
        (pv: { isExpire: number }) => pv.isExpire === 0,
      ),
    }))
    .filter((config) => config.prodPropValues.length > 0);
  if (validData.length === 0) {
    return [];
  }

  const propValueArrays = validData.map((config) => config.prodPropValues);
  const combinations = cartesianProduct<{
    propValue: string;
    valueId?: number;
    state?: number;
    isExist?: number;
    isExpire?: number;
  }>(...propValueArrays);

  return combinations.map((combination) => {
    const skuItem: SkuList = {
      skuName: combination.map((item) => item.propValue).join(','),
      properties: combination.map((item) => item.propValue).join(','),
      basePrice: 0,
      isSpecs: 0,
      status: 1,
      stocks: 0,
      stocksFlg: 1,
      isShelf: 1,
      isExist: combination.some((item) => item.isExist) ? 1 : 0,
    };

    validData.forEach((config, configIndex) => {
      (skuItem as any)[config.propName] = combination[configIndex].propValue;
    });

    return skuItem;
  });
}

export const generateUUID = () => {
  if (typeof crypto === 'object') {
    if (typeof crypto.randomUUID === 'function') {
      return crypto.randomUUID();
    }
    if (
      typeof crypto.getRandomValues === 'function' &&
      typeof Uint8Array === 'function'
    ) {
      const callback = (c: any) => {
        const num = Number(c);
        return (
          num ^
          (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))
        ).toString(16);
      };
      return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback);
    }
  }
  let timestamp = Date.now();
  let performanceNow =
    (typeof performance !== 'undefined' &&
      performance.now &&
      performance.now() * 1000) ||
    0;
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    let random = Math.random() * 16;
    if (timestamp > 0) {
      random = ((timestamp + random) % 16) | 0;
      timestamp = Math.floor(timestamp / 16);
    } else {
      random = ((performanceNow + random) % 16) | 0;
      performanceNow = Math.floor(performanceNow / 16);
    }
    return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16);
  });
};
