"use client";

import { useCallback, useRef, useState } from "react";
import type {
  AddressInput,
  MothershipAddressCandidate,
  QuoteDetail,
  QuotePageStatus,
  QuoteRequestBody,
} from "@/lib/frontend/types";
import { SUBMIT_LOCK_MS } from "@/lib/frontend/constants";
import {
  hostCreateQuote,
  hostFetchMothershipCandidates,
  hostGetQuote,
  hostPreheatQuoteSession,
  hostReleaseQuoteSession,
} from "@/lib/frontend/api-client";
import { applyMothershipCandidate } from "@/lib/frontend/mothership-address";
import { pollQuoteUntilDone } from "@/hooks/use-quote-polling";
import { formatQuoteErrorMessage } from "@/modules/quote/quote-error-messages";
import { QuoteForm } from "@/components/quote/quote-form";
import { QuoteResultPanel } from "@/components/quote/quote-result-panel";
import { AddressDisambiguationModal } from "@/components/quote/address-disambiguation-modal";
import { PrimaryButton } from "@/components/ui/primary-button";
import { ErrorBanner } from "@/components/ui/error-banner";

export interface EmbeddedQuoteWidgetProps {
  serviceToken: string;
  customerId: string;
  apiBaseUrl?: string;
}

const FORM_ID = "embedded-quote-form";

export function EmbeddedQuoteWidget({
  serviceToken,
  customerId,
  apiBaseUrl = "",
}: EmbeddedQuoteWidgetProps) {
  const [status, setStatus] = useState<QuotePageStatus>("idle");
  const [quote, setQuote] = useState<QuoteDetail | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [submitLocked, setSubmitLocked] = useState(false);
  const [disambiguationOpen, setDisambiguationOpen] = useState(false);
  const [confirmedPickup, setConfirmedPickup] = useState<AddressInput | null>(
    null,
  );
  const [confirmedDelivery, setConfirmedDelivery] =
    useState<AddressInput | null>(null);
  const [pickupCandidates, setPickupCandidates] = useState<
    MothershipAddressCandidate[]
  >([]);
  const [deliveryCandidates, setDeliveryCandidates] = useState<
    MothershipAddressCandidate[]
  >([]);
  const pendingBodyRef = useRef<QuoteRequestBody | null>(null);
  const pendingSessionRef = useRef<string | undefined>(undefined);

  const reset = useCallback(() => {
    setStatus("idle");
    setQuote(null);
    setError(null);
    setConfirmedPickup(null);
    setConfirmedDelivery(null);
  }, []);

  const finishQuote = useCallback((detail: QuoteDetail) => {
    setQuote(detail);
    if (detail.status === "failed") {
      setStatus("error");
      setError(
        detail.error_message ??
          formatQuoteErrorMessage(detail.error_code),
      );
      return;
    }
    if (detail.status === "expired") {
      setStatus("expired");
      return;
    }
    setStatus(detail.is_realtime === false ? "fallback" : "success");
    setError(null);
  }, []);

  const submitQuote = useCallback(
    async (body: QuoteRequestBody) => {
      setStatus("validating");
      setError(null);

      const created = await hostCreateQuote(apiBaseUrl, serviceToken, body);
      if (created.code !== 0) {
        setStatus("error");
        setError(created.message);
        return;
      }

      const { quote_id, status: createStatus } = created.data;
      setStatus("processing");

      if (createStatus === "done") {
        const detail = await hostGetQuote(
          apiBaseUrl,
          serviceToken,
          customerId,
          quote_id,
        );
        if (detail.code !== 0) {
          setStatus("error");
          setError(detail.message);
          return;
        }
        finishQuote(detail.data);
        return;
      }

      const pollResult = await pollQuoteUntilDone(async () => {
        try {
          const res = await hostGetQuote(
            apiBaseUrl,
            serviceToken,
            customerId,
            quote_id,
          );
          if (res.code !== 0) {
            return { ok: false, errorMessage: res.message };
          }
          return { ok: true, data: res.data };
        } catch {
          return { ok: false };
        }
      });

      if (pollResult.type === "done") {
        finishQuote(pollResult.quote);
        return;
      }
      setStatus("error");
      setError(
        pollResult.type === "timeout"
          ? formatQuoteErrorMessage("QUOTE_TIMEOUT")
          : pollResult.message,
      );
    },
    [apiBaseUrl, serviceToken, customerId, finishQuote],
  );

  const handleSubmit = useCallback(
    async (body: QuoteRequestBody) => {
      if (submitLocked) return;
      setSubmitLocked(true);
      setTimeout(() => setSubmitLocked(false), SUBMIT_LOCK_MS);

      setStatus("resolving_address");
      setError(null);

      let candidatesRes;
      try {
        candidatesRes = await hostFetchMothershipCandidates(
          apiBaseUrl,
          serviceToken,
          customerId,
          body.pickup_address,
          body.delivery_address,
        );
      } catch {
        setStatus("error");
        setError("地址联想请求失败，请稍后重试");
        return;
      }

      if (candidatesRes.code !== 0) {
        setStatus("error");
        setError(candidatesRes.message);
        return;
      }

      const {
        pickup_candidates,
        delivery_candidates,
        quote_session_id,
      } = candidatesRes.data;
      pendingSessionRef.current = quote_session_id;

      pendingBodyRef.current = body;
      setPickupCandidates(pickup_candidates);
      setDeliveryCandidates(delivery_candidates);
      setDisambiguationOpen(true);
      if (quote_session_id) {
        void hostPreheatQuoteSession(
          apiBaseUrl,
          serviceToken,
          customerId,
          quote_session_id,
        );
      }
      setStatus("idle");
    },
    [apiBaseUrl, serviceToken, customerId, submitLocked],
  );

  const handleDisambiguationConfirm = useCallback(
    async (
      pickup: MothershipAddressCandidate,
      delivery: MothershipAddressCandidate,
    ) => {
      const base = pendingBodyRef.current;
      if (!base) {
        return;
      }
      setDisambiguationOpen(false);
      pendingBodyRef.current = null;

      const confirmedBody: QuoteRequestBody = {
        ...base,
        quote_session_id: pendingSessionRef.current,
        pickup_address: applyMothershipCandidate(base.pickup_address, pickup),
        delivery_address: applyMothershipCandidate(
          base.delivery_address,
          delivery,
        ),
      };
      setConfirmedPickup(confirmedBody.pickup_address);
      setConfirmedDelivery(confirmedBody.delivery_address);
      pendingSessionRef.current = undefined;
      await submitQuote(confirmedBody);
    },
    [submitQuote],
  );

  const handleDisambiguationCancel = useCallback(() => {
    const sessionId = pendingSessionRef.current;
    setDisambiguationOpen(false);
    pendingBodyRef.current = null;
    pendingSessionRef.current = undefined;
    setStatus("idle");
    if (sessionId) {
      void hostReleaseQuoteSession(
        apiBaseUrl,
        serviceToken,
        customerId,
        sessionId,
      );
    }
  }, [apiBaseUrl, serviceToken, customerId]);

  const formDisabled =
    status === "resolving_address" ||
    status === "validating" ||
    status === "processing" ||
    submitLocked ||
    disambiguationOpen;

  return (
    <div className="rounded-lg border border-border bg-surface p-4 shadow-card md:p-6">
      <div className="mb-4">
        <h2 className="text-lg font-semibold text-text-primary">卡派查价</h2>
        <p className="text-sm text-text-secondary">
          填写货物信息，获取实时四档报价
        </p>
      </div>

      {error && status === "idle" && (
        <div className="mb-4">
          <ErrorBanner>{error}</ErrorBanner>
        </div>
      )}

      <div className="grid gap-6 lg:grid-cols-5">
        <div className="lg:col-span-3">
          <QuoteForm
            customerId={customerId}
            disabled={formDisabled}
            formId={FORM_ID}
            confirmedPickup={confirmedPickup}
            confirmedDelivery={confirmedDelivery}
            onAddressDraftChange={() => {
              setConfirmedPickup(null);
              setConfirmedDelivery(null);
            }}
            onValidSubmit={(body) => void handleSubmit(body)}
          />
          <div className="mt-6">
            <PrimaryButton
              type="submit"
              form={FORM_ID}
              loading={
                status === "resolving_address" ||
                status === "validating" ||
                status === "processing"
              }
              disabled={formDisabled}
              className="w-full sm:w-auto"
            >
              获取报价
            </PrimaryButton>
          </div>
        </div>
        <div className="lg:col-span-2">
          <QuoteResultPanel
            status={status}
            quote={quote}
            error={error}
            onRetry={reset}
            onExpire={() => setStatus("expired")}
            onExpiredConfirm={reset}
          />
        </div>
      </div>

      <AddressDisambiguationModal
        open={disambiguationOpen}
        pickupCandidates={pickupCandidates}
        deliveryCandidates={deliveryCandidates}
        onConfirm={(pickup, delivery) =>
          void handleDisambiguationConfirm(pickup, delivery)
        }
        onCancel={handleDisambiguationCancel}
      />
    </div>
  );
}
