import type { QuoteItem } from "@/modules/providers/quote-provider";
import {
  normalizeMotherShipRateOption,
  normalizeMotherShipServiceLevel,
} from "@/lib/constants/mothership-ui-tiers";
import { isAxelQuoteResponseUrl } from "@/workers/rpa/quote-capture/axel-contract";
import { satisfiesQuoteContract } from "@/workers/rpa/quote-capture/quote-contract-guard";
import { normalizeQuote } from "@/workers/rpa/quote-capture/quote-normalize";
import type { QuoteCaptureSignals, QuoteDecodeResult } from "@/workers/rpa/quote-capture/types";

type PartialTier = {
  serviceLevel: QuoteItem["serviceLevel"];
  rateOption: QuoteItem["rateOption"];
  rawFreight: number;
  surcharges: number;
  transitDays: string;
  transitDescription: string;
  carrier: string;
};

const MAX_WALK_DEPTH = 24;

const SERVICE_LEVEL_ALIASES: Record<string, string> = {
  standard: "standard",
  guaranteed: "guaranteed",
  guarantee: "guaranteed",
  shared: "standard",
  sharedtruck: "standard",
  dedicated: "dedicated",
  dedicatedtruck: "dedicated",
  truckload: "dedicated",
  fulltruckload: "dedicated",
  ftl: "dedicated",
  标准: "standard",
  保证送达: "guaranteed",
  专属卡车: "dedicated",
  专属货车: "dedicated",
};

const RATE_OPTION_ALIASES: Record<string, QuoteItem["rateOption"]> = {
  lowest: "lowest",
  cheapest: "lowest",
  economy: "lowest",
  fastest: "fastest",
  expedited: "fastest",
  express: "fastest",
  bestvalue: "bestValue",
  最低价格: "lowest",
  最快递送: "fastest",
  最优性价比: "bestValue",
};

const PRICE_FIELD_KEYS = [
  "price",
  "freight",
  "amount",
  "cost",
  "total",
  "rawfreight",
  "rawtotal",
  "rate",
  "value",
  "basequoteprice",
  "finalprice",
] as const;

const TRANSIT_FIELD_KEYS = [
  "transitdays",
  "transit_days",
  "estimatedtransitdays",
  "estimatedtransit",
  "deliverydays",
  "transit",
  "eta",
  "days",
] as const;

function normalizeKey(key: string): string {
  return key.replace(/[^a-z0-9]/gi, "").toLowerCase();
}

function keyToServiceLevel(key: string): string | null {
  const n = normalizeKey(key);
  const fromAlias = SERVICE_LEVEL_ALIASES[n];
  if (fromAlias) {
    return fromAlias;
  }
  return normalizeMotherShipServiceLevel(key);
}

function keyToRateOption(key: string): QuoteItem["rateOption"] | null {
  const n = normalizeKey(key);
  return RATE_OPTION_ALIASES[n] ?? null;
}

function mapSubKeyToRateOption(
  _serviceLevel: string,
  subKey: string,
): QuoteItem["rateOption"] | null {
  const ro = keyToRateOption(subKey) ?? normalizeMotherShipRateOption(subKey);
  if (ro) {
    return ro as QuoteItem["rateOption"];
  }
  if (normalizeKey(subKey) === "bestvalue") {
    return "bestValue";
  }
  return null;
}

function readStringField(obj: Record<string, unknown>, keys: readonly string[]): string | null {
  for (const key of keys) {
    const val = obj[key];
    if (typeof val === "string" && val.trim()) {
      return val.trim();
    }
    if (typeof val === "number" && Number.isFinite(val)) {
      return String(val);
    }
  }
  return null;
}

function readNumericFromKeys(
  obj: Record<string, unknown>,
  keys: readonly string[],
): number | null {
  for (const want of keys) {
    for (const key of Object.keys(obj)) {
      if (normalizeKey(key) !== normalizeKey(want)) {
        continue;
      }
      const val = obj[key];
      if (typeof val === "number" && val > 0) {
        return val;
      }
      if (typeof val === "string") {
        const m = val.replace(/,/g, "").match(/(\d+(?:\.\d+)?)/);
        if (m) {
          const n = Number(m[1]);
          if (n > 0) {
            return n;
          }
        }
      }
    }
  }
  return null;
}

function readPrice(obj: Record<string, unknown>): number | null {
  // 为何：MotherShip UI 展示 finalPrice；price 常为承运商标价与 UI 不一致
  return (
    readNumericFromKeys(obj, ["finalprice"]) ??
    readNumericFromKeys(obj, ["price"])
  );
}

function readTransit(obj: Record<string, unknown>): string {
  const daysVal = obj.days ?? obj.transitDays;
  if (typeof daysVal === "number") {
    if (daysVal > 0) {
      return `Est. ${daysVal} business days`;
    }
    if (daysVal === 0) {
      return "0 business days";
    }
  }
  const desc = readStringField(obj, [
    "serviceCommitmentDescription",
    "transitDescription",
    "description",
    "label",
  ]);
  if (desc) {
    return desc;
  }
  for (const key of Object.keys(obj)) {
    const nk = normalizeKey(key);
    if (!TRANSIT_FIELD_KEYS.some((t) => nk.includes(t.replace(/_/g, "")))) {
      continue;
    }
    const val = obj[key];
    if (typeof val === "string" && val.trim()) {
      return val.trim();
    }
    if (typeof val === "number" && val > 0) {
      return `${val} business days`;
    }
  }
  return "—";
}

function inferServiceLevel(obj: Record<string, unknown>): string | null {
  const fields = ["serviceLevel", "service_level", "serviceType", "service_type", "type", "name", "tier"];
  for (const key of fields) {
    const val = obj[key];
    if (typeof val !== "string") {
      continue;
    }
    const lower = val.toLowerCase();
    if (lower.includes("guarantee") || val.includes("保证")) {
      return "guaranteed";
    }
    if (
      lower.includes("dedicated") ||
      lower.includes("truckload") ||
      lower.includes("ftl") ||
      val.includes("专属")
    ) {
      return "dedicated";
    }
    if (lower.includes("standard") || val.includes("标准")) {
      return "standard";
    }
    const fromKey = keyToServiceLevel(val);
    if (fromKey) {
      return fromKey;
    }
  }
  return null;
}

function inferRateOption(obj: Record<string, unknown>): QuoteItem["rateOption"] | null {
  const fields = ["rateOption", "rate_option", "option", "speed", "name", "label", "serviceType", "service_type"];
  for (const key of fields) {
    const val = obj[key];
    if (typeof val !== "string") {
      continue;
    }
    const lower = val.toLowerCase();
    if (lower.includes("fast") || lower.includes("exped") || val.includes("最快")) {
      return "fastest";
    }
    if (lower.includes("low") || lower.includes("cheap") || val.includes("最低")) {
      return "lowest";
    }
    if (lower.includes("bestvalue") || lower.includes("best value") || val.includes("最优")) {
      return "bestValue";
    }
  }
  return null;
}

function readCarrierName(obj: Record<string, unknown>): string {
  const carrierInfo = obj.carrierInfo;
  if (
    carrierInfo != null &&
    typeof carrierInfo === "object" &&
    !Array.isArray(carrierInfo)
  ) {
    const name = readStringField(carrierInfo as Record<string, unknown>, [
      "name",
      "carrierName",
    ]);
    if (name) {
      return name;
    }
  }
  return (
    readStringField(obj, ["carrierName", "carrier", "providerName"]) ??
    "Mothership"
  );
}

function pushTier(
  acc: PartialTier[],
  serviceLevel: string,
  rateOption: QuoteItem["rateOption"],
  obj: Record<string, unknown>,
): void {
  const rawFreight = readPrice(obj);
  if (rawFreight === null || rawFreight <= 0) {
    return;
  }
  const surcharges =
    typeof obj.surcharges === "number" && obj.surcharges >= 0
      ? obj.surcharges
      : typeof obj.fees === "number" && obj.fees >= 0
        ? obj.fees
        : 0;
  const transit = readTransit(obj);
  acc.push({
    serviceLevel,
    rateOption,
    rawFreight,
    surcharges,
    transitDays: transit,
    transitDescription: transit,
    carrier: readCarrierName(obj),
  });
}

function walkNestedServiceRates(
  obj: Record<string, unknown>,
  acc: PartialTier[],
  depth: number,
): void {
  if (depth > MAX_WALK_DEPTH) {
    return;
  }

  for (const [key, value] of Object.entries(obj)) {
    const sl = keyToServiceLevel(key);
    if (!sl || typeof value !== "object" || value === null || Array.isArray(value)) {
      continue;
    }
    const nested = value as Record<string, unknown>;
    const directRo = keyToRateOption(key);
    if (directRo) {
      pushTier(acc, sl, directRo, nested);
      continue;
    }
    for (const [subKey, subVal] of Object.entries(nested)) {
      const ro = mapSubKeyToRateOption(sl, subKey);
      if (!ro || typeof subVal !== "object" || subVal === null || Array.isArray(subVal)) {
        continue;
      }
      pushTier(acc, sl, ro, subVal as Record<string, unknown>);
    }
  }
}

function walkJson(node: unknown, acc: PartialTier[], depth = 0): void {
  if (depth > MAX_WALK_DEPTH || node == null) {
    return;
  }

  if (Array.isArray(node)) {
    for (const item of node) {
      walkJson(item, acc, depth + 1);
    }
    return;
  }

  if (typeof node !== "object") {
    return;
  }

  const obj = node as Record<string, unknown>;
  walkNestedServiceRates(obj, acc, depth);

  const sl = inferServiceLevel(obj);
  const ro = inferRateOption(obj);
  if (sl) {
    pushTier(acc, sl, ro ?? "lowest", obj);
  }

  for (const value of Object.values(obj)) {
    walkJson(value, acc, depth + 1);
  }
}

function dedupePartials(partials: PartialTier[]): PartialTier[] {
  const map = new Map<string, PartialTier>();
  for (const tier of partials) {
    const key = `${tier.serviceLevel}/${tier.rateOption}`;
    if (!map.has(key)) {
      map.set(key, tier);
    }
  }
  return [...map.values()];
}

function partialsToQuoteItems(partials: PartialTier[]): QuoteItem[] {
  return dedupePartials(partials).map((tier) => ({
    serviceLevel: tier.serviceLevel,
    rateOption: tier.rateOption,
    carrier: tier.carrier,
    transitDays: tier.transitDays,
    transitDescription: tier.transitDescription,
    rawFreight: tier.rawFreight,
    surcharges: tier.surcharges,
    rawTotal: tier.rawFreight + tier.surcharges,
  }));
}

/** UI 档位：叶节点 finalPrice/price；或经 id 关联 availableRates 解析完整对象 */
function resolveUiTierLeaf(tier: unknown): Record<string, unknown> | null {
  if (tier == null || typeof tier !== "object" || Array.isArray(tier)) {
    return null;
  }
  const obj = tier as Record<string, unknown>;
  if (readNumericFromKeys(obj, ["finalprice", "price"]) != null) {
    return obj;
  }
  return null;
}

function resolveTierFromRatesSlot(
  slotVal: unknown,
  availableRates: Record<string, unknown> | null,
): Record<string, unknown> | null {
  const leaf = resolveUiTierLeaf(slotVal);
  if (leaf) {
    return leaf;
  }
  if (availableRates == null) {
    return null;
  }
  let rateId: string | null = null;
  if (typeof slotVal === "string" && slotVal.trim()) {
    rateId = slotVal.trim();
  } else if (slotVal != null && typeof slotVal === "object" && !Array.isArray(slotVal)) {
    const id = (slotVal as Record<string, unknown>).id;
    if (typeof id === "string" && id.trim()) {
      rateId = id.trim();
    }
  }
  if (!rateId) {
    return null;
  }
  const ref = availableRates[rateId];
  if (ref == null || typeof ref !== "object" || Array.isArray(ref)) {
    return null;
  }
  return resolveUiTierLeaf(ref) ? (ref as Record<string, unknown>) : null;
}

/** MotherShip 返回什么就解析什么：至少 1 条有效运价即可 */
function hasMinimumTiers(items: QuoteItem[]): boolean {
  return items.some((i) => i.rawFreight > 0);
}

/** 解码 sign-up-quote?quote-details=（URL 编码 JSON，可能多层） */
export function decodeQuoteDetailsParam(raw: string): unknown | null {
  let current = raw.trim();
  for (let attempt = 0; attempt < 4; attempt += 1) {
    if (current.startsWith("{") || current.startsWith("[")) {
      try {
        return JSON.parse(current) as unknown;
      } catch {
        return null;
      }
    }

    let progressed = false;

    try {
      const urlDecoded = decodeURIComponent(current);
      if (urlDecoded !== current) {
        current = urlDecoded;
        progressed = true;
      }
    } catch {
      /* 非 URL 编码 */
    }

    if (!progressed) {
      try {
        const fromB64 = Buffer.from(current, "base64").toString("utf8");
        if (fromB64 && fromB64 !== current) {
          current = fromB64;
          progressed = true;
        }
      } catch {
        /* 非 base64 */
      }
    }

    if (!progressed) {
      break;
    }
  }

  if (current.startsWith("{") || current.startsWith("[")) {
    try {
      return JSON.parse(current) as unknown;
    } catch {
      return null;
    }
  }
  return null;
}

function extractTiersFromServiceBlock(
  partials: PartialTier[],
  serviceLevel: string,
  block: Record<string, unknown>,
  availableRates: Record<string, unknown> | null,
): void {
  for (const [subKey, subVal] of Object.entries(block)) {
    const ro = mapSubKeyToRateOption(serviceLevel, subKey);
    if (!ro) {
      continue;
    }
    const tier = resolveTierFromRatesSlot(subVal, availableRates);
    if (tier) {
      pushTier(partials, serviceLevel, ro, tier);
    }
  }
}

function extractTiersFromRates(
  rates: Record<string, unknown>,
  availableRates: Record<string, unknown> | null,
): PartialTier[] {
  const partials: PartialTier[] = [];
  const skipTopLevel = new Set(["fastest"]);

  for (const [key, block] of Object.entries(rates)) {
    if (skipTopLevel.has(key)) {
      continue;
    }
    const serviceLevel = keyToServiceLevel(key);
    if (
      !serviceLevel ||
      block == null ||
      typeof block !== "object" ||
      Array.isArray(block)
    ) {
      continue;
    }
    extractTiersFromServiceBlock(
      partials,
      serviceLevel,
      block as Record<string, unknown>,
      availableRates,
    );
  }

  const fastestTop = resolveTierFromRatesSlot(rates.fastest, availableRates);
  if (
    fastestTop &&
    !partials.some(
      (p) => p.serviceLevel === "standard" && p.rateOption === "fastest",
    )
  ) {
    pushTier(partials, "standard", "fastest", fastestTop);
  }

  return partials;
}

function readAvailableRates(body: unknown): Record<string, unknown> | null {
  if (body == null || typeof body !== "object" || Array.isArray(body)) {
    return null;
  }
  const data = (body as Record<string, unknown>).data;
  if (data == null || typeof data !== "object" || Array.isArray(data)) {
    return null;
  }
  const availableRates = (data as Record<string, unknown>).availableRates;
  if (
    availableRates == null ||
    typeof availableRates !== "object" ||
    Array.isArray(availableRates)
  ) {
    return null;
  }
  return availableRates as Record<string, unknown>;
}

/** MotherShip UI 档位名仅以 rates.{standard|guaranteed} 下出现的子键为准 */
function listUiRateOptionsFromRatesBlock(
  rates: Record<string, unknown> | undefined,
  serviceLevel: string,
): Set<QuoteItem["rateOption"]> | null {
  const block = rates?.[serviceLevel];
  if (block == null || typeof block !== "object" || Array.isArray(block)) {
    return null;
  }
  const allowed = new Set<QuoteItem["rateOption"]>();
  for (const subKey of Object.keys(block as Record<string, unknown>)) {
    const ro = mapSubKeyToRateOption(serviceLevel, subKey);
    if (ro) {
      allowed.add(ro);
    }
  }
  return allowed.size > 0 ? allowed : null;
}

/** 仅 rates.{serviceLevel} 下声明的子键允许从 availableRates 补全（与官网 Tab 一致） */
function listAllowedRateOptionsForSupplement(
  rates: Record<string, unknown> | undefined,
  serviceLevel: string,
): Set<QuoteItem["rateOption"]> | null {
  if (!rates) {
    return null;
  }
  return listUiRateOptionsFromRatesBlock(rates, serviceLevel);
}

function isRateOptionAllowedForSupplement(
  rates: Record<string, unknown> | undefined,
  serviceLevel: string,
  rateOption: QuoteItem["rateOption"],
): boolean {
  const allowed = listAllowedRateOptionsForSupplement(rates, serviceLevel);
  if (allowed == null || allowed.size === 0) {
    return false;
  }
  return allowed.has(rateOption);
}

function hasPartialTier(
  partials: PartialTier[],
  serviceLevel: string,
  rateOption: QuoteItem["rateOption"],
): boolean {
  return partials.some(
    (p) => p.serviceLevel === serviceLevel && p.rateOption === rateOption,
  );
}

function mergePartials(target: PartialTier[], source: PartialTier[]): void {
  for (const tier of source) {
    if (!hasPartialTier(target, tier.serviceLevel, tier.rateOption)) {
      target.push(tier);
    }
  }
}

/**
 * data.availableRates 补全：仅填充 rates.* 已声明槽位（显式 serviceType 或 id 引用），禁止 customRate 推断
 */
function extractTiersFromAvailableRates(
  body: unknown,
  ratesFromBody?: Record<string, unknown>,
): PartialTier[] {
  const availableRates = readAvailableRates(body);
  if (!availableRates) {
    return [];
  }

  const partials: PartialTier[] = [];

  for (const entry of Object.values(availableRates)) {
    if (entry == null || typeof entry !== "object" || Array.isArray(entry)) {
      continue;
    }
    const obj = entry as Record<string, unknown>;
    if (!resolveUiTierLeaf(obj)) {
      continue;
    }

    const serviceLevel = inferServiceLevel(obj) ?? "standard";
    const serviceType = String(obj.serviceType ?? "").toLowerCase();
    if (!serviceType || serviceType === "customrate") {
      continue;
    }
    const rateOption =
      keyToRateOption(serviceType) ??
      mapSubKeyToRateOption(serviceLevel, serviceType);
    if (!rateOption) {
      continue;
    }
    if (
      isRateOptionAllowedForSupplement(ratesFromBody, serviceLevel, rateOption)
    ) {
      pushTier(partials, serviceLevel, rateOption, obj);
    }
  }

  return partials;
}

function mergeAvailableRatesSupplement(
  partials: PartialTier[],
  body: unknown,
  rates: Record<string, unknown> | undefined,
): void {
  mergePartials(partials, extractTiersFromAvailableRates(body, rates));
}

function extractFromContractBodies(
  bodies: unknown[],
): QuoteItem[] | null {
  const partials: PartialTier[] = [];
  for (const body of bodies) {
    const canonical = normalizeQuote(body);
    if (!canonical) {
      continue;
    }
    const availableRates = readAvailableRates(body);
    partials.push(...extractTiersFromRates(canonical.rates, availableRates));
    mergeAvailableRatesSupplement(partials, body, canonical.rates);
  }
  const items = partialsToQuoteItems(partials);
  return hasMinimumTiers(items) ? items : null;
}

/** 直连 axel/quote：仅 rates.* 声明槽位 + id/空槽 availableRates 补全，不推断 customRate */
export function decodeAxelQuoteBodyLenient(body: unknown): QuoteItem[] | null {
  const partials: PartialTier[] = [];
  const canonical = normalizeQuote(body);
  const rates = canonical?.rates;
  const availableRates = readAvailableRates(body);
  if (rates) {
    partials.push(...extractTiersFromRates(rates, availableRates));
  }

  mergeAvailableRatesSupplement(partials, body, rates);

  const items = partialsToQuoteItems(partials);
  return hasMinimumTiers(items) ? items : null;
}

function orderContractPayloads(
  payloads: QuoteCaptureSignals["contractPayloads"],
): QuoteCaptureSignals["contractPayloads"] {
  return [...payloads].sort((a, b) => {
    const rank = (url: string) => (isAxelQuoteResponseUrl(url) ? 0 : 1);
    return rank(a.url) - rank(b.url);
  });
}

function tryLenientAxelDecode(
  signals: QuoteCaptureSignals,
): QuoteDecodeResult | null {
  const onSignUpQuote = signals.resultUrl.includes("sign-up-quote");
  const candidates = [
    ...orderContractPayloads(signals.contractPayloads),
    ...signals.jsonPayloads,
  ];
  for (const payload of candidates) {
    if (!isAxelQuoteResponseUrl(payload.url) && !onSignUpQuote) {
      continue;
    }
    const items = decodeAxelQuoteBodyLenient(payload.body);
    if (items && hasMinimumTiers(items)) {
      console.log(
        `[rpa] quote-decode: lenient axel/quote url=${payload.url} tiers=${items.length}`,
      );
      return { items, source: "lenient" };
    }
  }
  return null;
}

/** 契约 JSON 响应 → 四档报价；sign-up-quote 页 axel/quote 结构不全时走 lenient */
export function decodeQuotePayloads(
  signals: QuoteCaptureSignals,
): QuoteDecodeResult | null {
  if (signals.contractPayloads.length === 0) {
    return tryLenientAxelDecode(signals);
  }

  const ordered = orderContractPayloads(signals.contractPayloads);
  const strictOk = ordered.every((p) => satisfiesQuoteContract(p.body));

  if (strictOk) {
    const bodies = ordered.map((p) => p.body);
    const items = extractFromContractBodies(bodies);
    if (items && hasMinimumTiers(items)) {
      return { items, source: "contract" };
    }
  }

  return tryLenientAxelDecode(signals);
}

/** @deprecated Network-First 架构禁止 DOM 内嵌 JSON 报价提取 */
export function decodeEmbeddedJsonBodies(
  _bodies: unknown[],
): QuoteDecodeResult | null {
  return null;
}
