import { Prisma } from "@prisma/client";
import { isFlockRpaEnabled } from "@/lib/flock/env";
import { getFlockBatchExclusiveBusyMessage } from "@/lib/flock/exclusive-lock";
import { FLOCK_UI } from "@/lib/flock/ui-labels";
import { prisma } from "@/lib/prisma";
import { hashFlockInput } from "@/modules/flock/hash";
import { enqueueFlockQuoteJob } from "@/modules/flock/rpa-queue";
import { validateFlockQuoteInput } from "@/modules/flock/validation";
import {
  generateQuoteId,
  handleQuoteIdConflict,
  isQuoteIdUniqueConflict,
} from "@/modules/quote/quote-id";
import { markQuoteStarted, safeRecord } from "@/modules/metrics/collector";
import { buildFlockProgressPayload } from "@/lib/flock/rpa-progress";
import type { FlockQuoteInput } from "@/workers/rpa/flock/types";

export class FlockEnqueueError extends Error {
  readonly code = "QUOTE_UNAVAILABLE" as const;

  constructor(message: string) {
    super(message);
    this.name = "FlockEnqueueError";
  }
}

export type FlockSubmitResult = {
  quote_id: string;
  status: "processing";
};

function zipJson(
  zip: string,
  input: FlockQuoteInput,
  side: "pickup" | "delivery",
): Prisma.InputJsonValue {
  return {
    street: "",
    city: "",
    state: "",
    zip,
    place_id: "",
    formatted_address: zip,
    selected_from_suggestions: false,
    provider: "flock",
    ...(side === "pickup"
      ? {
          flock_pickup_date: input.pickupDate,
          flock_pallet_count: input.palletCount,
          flock_total_weight_lb: input.totalWeightLb,
        }
      : {}),
  };
}

/** Flock Freight 询价入队 */
export async function submitFlockQuote(body: unknown): Promise<FlockSubmitResult> {
  if (!isFlockRpaEnabled()) {
    throw new FlockEnqueueError(FLOCK_UI.disabledHint);
  }

  // 仅 batch 探针占锁时拒绝入队；Worker 查价中仍可排队（本机串行锁保证不互踩）
  const busy = getFlockBatchExclusiveBusyMessage();
  if (busy) {
    throw new FlockEnqueueError(busy);
  }

  const parsed = validateFlockQuoteInput(body);
  const { request_id, customer_id, ...input } = parsed;
  const cargoHash = hashFlockInput(input);
  let quoteId = await generateQuoteId();

  const baseRecord = {
    requestId: request_id,
    customerId: customer_id,
    cargoHash,
    status: "processing" as const,
    pickupJson: zipJson(input.pickupZip, input, "pickup"),
    deliveryJson: zipJson(input.deliveryZip, input, "delivery"),
    weightLb: input.totalWeightLb,
    dimLIn: input.lengthIn,
    dimWIn: input.widthIn,
    dimHIn: input.heightIn,
    palletCount: input.palletCount,
    cargoType: "general_freight",
    quotesJson: buildFlockProgressPayload(
      "queued",
    ) as unknown as Prisma.InputJsonValue,
  };

  try {
    await prisma.quoteRecord.create({
      data: { quoteId, ...baseRecord },
    });
  } catch (error) {
    if (!isQuoteIdUniqueConflict(error)) {
      throw error;
    }
    quoteId = await generateQuoteId();
    try {
      await prisma.quoteRecord.create({
        data: { quoteId, ...baseRecord },
      });
    } catch (retryError) {
      if (isQuoteIdUniqueConflict(retryError)) {
        await handleQuoteIdConflict(quoteId, customer_id);
      }
      throw retryError;
    }
  }

  try {
    await enqueueFlockQuoteJob({
      quoteId,
      requestId: request_id,
      customerId: customer_id,
      cargoHash,
      input,
    });
  } catch (error) {
    console.error("[flock] 入队失败:", error);
    await prisma.quoteRecord.update({
      where: { quoteId },
      data: {
        status: "failed",
        errorCode: "QUOTE_UNAVAILABLE",
        errorMessage: "Flock 报价队列暂不可用",
      },
    });
    throw new FlockEnqueueError("Flock 报价服务暂不可用，请稍后重试");
  }

  safeRecord(() => markQuoteStarted(quoteId));
  return { quote_id: quoteId, status: "processing" };
}
