import type { QuoteItem, QuoteRequest } from "@/modules/providers/quote-provider";
import { RpaError } from "@/modules/rpa/errors";
import { AxelHttpClient } from "@/lib/axel/client";
import { pickBestSearchCandidate } from "@/lib/axel/pick-candidate";
import {
  buildAxelShipmentPayload,
  type AxelPlaceLocation,
} from "@/lib/axel/shipment";
import { normalizeAxelPlaceId } from "@/workers/rpa/axel-selection-bridge";
import { decodeAxelQuoteBodyLenient } from "@/workers/rpa/quote-capture/payload-decode";
import { normalizeQuoteItems } from "@/workers/rpa/quote-capture/quote-schema-validator";

function buildAddressQuery(
  addr: QuoteRequest["pickup"],
): string {
  const fromFormatted = addr.formattedAddress?.trim();
  if (fromFormatted) {
    return fromFormatted;
  }
  return [addr.street, addr.city, addr.state, addr.zip]
    .map((part) => part?.trim())
    .filter(Boolean)
    .join(", ");
}

function resolvePlaceId(addr: QuoteRequest["pickup"]): string | null {
  const optionId = addr.mothershipOptionId?.trim();
  if (optionId && !optionId.startsWith("ms_")) {
    return optionId;
  }
  const placeId = addr.placeId?.trim();
  if (placeId && placeId.startsWith("ChIJ")) {
    return placeId;
  }
  return null;
}

/** embed-demo / RPA Worker：按用户确认的 placeId 直连 axel/quote */
export async function fetchAxelQuoteItems(req: QuoteRequest): Promise<QuoteItem[]> {
  const client = await AxelHttpClient.create();

  type ResolvedSide = {
    placeId: string;
    description: string;
    place?: AxelPlaceLocation;
  };

  async function resolveSide(
    addr: QuoteRequest["pickup"],
    sideLabel: string,
  ): Promise<ResolvedSide> {
    const knownPlaceId = resolvePlaceId(addr);
    const description =
      addr.mothershipDisplayLabel?.trim() ||
      addr.formattedAddress?.trim() ||
      buildAddressQuery(addr);

    if (knownPlaceId) {
      try {
        const place = await client.fetchPlace(knownPlaceId);
        return { placeId: knownPlaceId, description, place };
      } catch {
        throw new RpaError(
          "ADDRESS_NOT_CONFIRMED",
          `${sideLabel}地址在 MotherShip 无法定位，请重新选择候选`,
          { retryable: true },
        );
      }
    }

    const query = buildAddressQuery(addr);
    const candidates = await client.searchLocation(query);
    const picked = pickBestSearchCandidate(query, candidates);
    if (!picked?.placeId) {
      throw new RpaError(
        "ADDRESS_SUGGESTION_NOT_FOUND",
        `未找到${sideLabel}地址候选：${query}`,
        { retryable: true },
      );
    }
    const place = await client.fetchPlace(picked.placeId);
    return {
      placeId: picked.placeId,
      description: picked.description,
      place,
    };
  }

  const [pickupSide, deliverySide] = await Promise.all([
    resolveSide(req.pickup, "提货"),
    resolveSide(req.delivery, "派送"),
  ]);

  const pickup = pickupSide.place ?? await client.fetchPlace(pickupSide.placeId);
  const delivery =
    deliverySide.place ?? await client.fetchPlace(deliverySide.placeId);
  const shipment = buildAxelShipmentPayload({
    pickup,
    delivery,
    pickupDescription: pickupSide.description,
    deliveryDescription: deliverySide.description,
    cargo: {
      palletCount: req.palletCount,
      weightLb: req.weightLb,
      lengthIn: req.dimsIn.l,
      widthIn: req.dimsIn.w,
      heightIn: req.dimsIn.h,
    },
  });

  let body: unknown;
  try {
    body = await client.postQuote(shipment);
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    if (
      /unable to find any rates|no carriers available|no capacity/i.test(msg) ||
      /axel\/quote HTTP 400/.test(msg)
    ) {
      throw new RpaError(
        "CARRIER_NO_CAPACITY",
        "MotherShip 该线路暂无可用报价，请调整地址或货物后重试",
        { retryable: false },
      );
    }
    throw new RpaError("RPA_DATA_INVALID", msg, { retryable: true });
  }
  const decoded = decodeAxelQuoteBodyLenient(body);
  if (!decoded?.length) {
    throw new RpaError(
      "RPA_DATA_INVALID",
      "axel/quote 响应无法解析为报价档位",
      { retryable: true },
    );
  }

  console.log(
    `[rpa] direct axel quote: pickup=${normalizeAxelPlaceId(pickupSide.placeId)} delivery=${normalizeAxelPlaceId(deliverySide.placeId)} tiers=${decoded.length}`,
  );

  return normalizeQuoteItems(decoded);
}
