import { createHttpError } from "../../../utils/http.js";
import { normalizeProductName } from "../../order/product-match-service.js";
import {
  appointCloudtentaclesVirtualNumber,
  backCloudtentaclesVirtualNumber,
  fetchCloudtentaclesVirtualNumberCode,
  generateCloudtentaclesLoginCode,
  getCloudtentaclesBindUrl,
  verifyCloudtentaclesLoginCode,
} from "../../platforms/cloudtentacles/virtual-number-service.js";
import { KUAISHOU_CLOUD_FIXED_VN_KEY, type JsonObject } from "./domain.js";

export function resolveKuaishouCloudBindingResources(
  flow,
  { skuItems = [], knapsackItems = [] } = {}
) {
  const normalizedSkuItems = Array.isArray(skuItems)
    ? skuItems.filter(isCloudSkuLikeItem)
    : [];
  const normalizedKnapsackItems = Array.isArray(knapsackItems)
    ? knapsackItems.filter(isCloudSkuLikeItem)
    : [];
  const currentSkuId = Number(flow?.binding?.skuId || 0) || 0;
  const currentSkuName = String(flow?.binding?.skuName || "").trim();
  const nameCandidates = collectKuaishouCloudNameCandidates(flow);

  const skuItemById =
    currentSkuId > 0
      ? normalizedSkuItems.find(
          (item) => Number(item.id || 0) === currentSkuId
        ) || null
      : null;
  const knapsackItemById =
    currentSkuId > 0
      ? normalizedKnapsackItems.find(
          (item) => Number(item.id || 0) === currentSkuId
        ) || null
      : null;

  if (skuItemById || knapsackItemById) {
    const matchedItem = skuItemById || knapsackItemById;
    return {
      skuId: Number(matchedItem?.id || 0) || 0,
      skuName: String(currentSkuName || matchedItem?.name || "").trim(),
      vnKey: KUAISHOU_CLOUD_FIXED_VN_KEY,
      skuItem: skuItemById,
      knapsackItem: knapsackItemById,
      resolvedByName: false,
    };
  }

  const matchedSkuItem = findCloudItemByNames(
    normalizedSkuItems,
    nameCandidates
  );
  const matchedKnapsackItem = findCloudItemByNames(
    normalizedKnapsackItems,
    nameCandidates,
    matchedSkuItem ? Number(matchedSkuItem.id || 0) : 0
  );
  const matchedItem = matchedSkuItem || matchedKnapsackItem;

  return {
    skuId: Number(matchedItem?.id || 0) || 0,
    skuName: String(currentSkuName || matchedItem?.name || "").trim(),
    vnKey: KUAISHOU_CLOUD_FIXED_VN_KEY,
    skuItem: matchedSkuItem,
    knapsackItem: matchedKnapsackItem,
    resolvedByName: Boolean(matchedItem),
  };
}

export function resolveKuaishouCloudVnKeyCandidates(_input = {}) {
  return [KUAISHOU_CLOUD_FIXED_VN_KEY];
}

export async function prepareKuaishouCloudBindResourceWithFallback(input: JsonObject = {}) {
  const { cloudContext = {}, vnKeyCandidates = [] } = input;
  const candidates = Array.isArray(vnKeyCandidates) ? vnKeyCandidates : [];
  let lastError = null;

  for (const vnKey of candidates) {
    let vnId = 0;
    let vnPhone = "";

    try {
      const appointed = await appointCloudtentaclesVirtualNumber({
        ...cloudContext,
        key: vnKey,
      });
      vnId = Number(appointed.item?.id || 0);
      vnPhone = String(appointed.item?.phone || "").trim();

      if (!vnId || !vnPhone) {
        throw createHttpError("申请虚拟号成功但返回数据不完整", {
          statusCode: 502,
          errorCode: "kuaishou_cloud_invalid_vn",
        });
      }

      await generateCloudtentaclesLoginCode({
        ...cloudContext,
        key: vnKey,
        id: vnId,
      });

      const fetchedCode = await fetchCloudtentaclesVirtualNumberCode({
        ...cloudContext,
        key: vnKey,
        phone: vnPhone,
      });

      await verifyCloudtentaclesLoginCode({
        ...cloudContext,
        key: vnKey,
        id: vnId,
        code: fetchedCode.code,
      });

      const bindUrlResult = await getCloudtentaclesBindUrl({
        ...cloudContext,
        key: vnKey,
        id: vnId,
      });

      return {
        vnKey,
        vnId,
        vnPhone,
        bindUrl: String(bindUrlResult.bindUrl || "").trim(),
      };
    } catch (error) {
      lastError = error;

      if (vnId > 0) {
        try {
          await backCloudtentaclesVirtualNumber({
            ...cloudContext,
            key: vnKey,
            id: vnId,
          });
        } catch {
          // 退号失败保留主错误
        }
      }

      if (!isRecoverableKuaishouCloudVnKeyError(error)) {
        throw error;
      }
    }
  }

  throw (
    lastError ||
    createHttpError("没有找到可用的 VN Key", {
      statusCode: 409,
      errorCode: "kuaishou_cloud_missing_binding_config",
    })
  );
}

function collectKuaishouCloudNameCandidates(flow) {
  return Array.from(
    new Set(
      [
        String(flow?.binding?.skuName || "").trim(),
        String(flow?.internalSkuName || "").trim(),
        String(flow?.internalSkuCode || "").trim(),
      ].filter(Boolean)
    )
  );
}

function findCloudItemByNames(items, nameCandidates, preferredId = 0) {
  const normalizedItems = Array.isArray(items) ? items : [];
  const normalizedNames = nameCandidates
    .map((item) => ({
      raw: String(item || "").trim(),
      normalized: normalizeProductName(item),
    }))
    .filter((item) => item.raw && item.normalized);

  if (normalizedNames.length === 0 || normalizedItems.length === 0) {
    return preferredId > 0
      ? normalizedItems.find((item) => Number(item.id || 0) === preferredId) ||
          null
      : null;
  }

  if (preferredId > 0) {
    const preferred =
      normalizedItems.find((item) => Number(item.id || 0) === preferredId) ||
      null;
    if (preferred) {
      return preferred;
    }
  }

  const exactMatches = normalizedItems.filter((item) => {
    const itemName = normalizeProductName(item.name);
    return normalizedNames.some(
      (candidate) => candidate.normalized === itemName
    );
  });
  if (exactMatches.length > 0) {
    return exactMatches[0];
  }

  const partialMatches = normalizedItems.filter((item) => {
    const itemName = normalizeProductName(item.name);
    return normalizedNames.some(
      (candidate) =>
        itemName.includes(candidate.normalized) ||
        candidate.normalized.includes(itemName)
    );
  });
  if (partialMatches.length > 0) {
    return partialMatches.sort(
      (left, right) =>
        String(left.name || "").length - String(right.name || "").length
    )[0];
  }

  return null;
}

function isCloudSkuLikeItem(item) {
  return Boolean(item) && typeof item === "object" && Number(item.id || 0) > 0;
}

function isRecoverableKuaishouCloudVnKeyError(error) {
  const errorCode = String(error?.errorCode || error?.code || "").trim();
  const errorMessage = String(error?.message || "").trim();
  return (
    errorCode === "cloudtentacles_vn_bind_url_failed" &&
    errorMessage.includes("不支持的游戏类型")
  );
}
