import Link from "next/link";
import { ArrowLeft, Gavel, Info, MessageSquareText, TrendingUp, Truck } from "lucide-react";
import { sellerApi } from "@/lib/api/seller";
import { requireRole, requireServerToken } from "@/lib/auth/server";
import type { ApiLeaderboardMeta, ApiLeaderboardRow, ApiSellerQuotationDetail } from "@/lib/api/types";
import RequirementSpec, { variationTotal } from "@/components/rfq/RequirementSpec";
import Countdown from "@/components/rfq/Countdown";
import PriceOptionBadge from "@/components/rfq/PriceOptionBadge";
import { formatUnit } from "@/lib/utils";
import BidPanel from "./BidPanel";

type PageProps = {
  params: Promise<{ id: string }>;
};

/**
 * The RFQ and its leaderboard are two independent reads keyed only by the RFQ
 * id, so they go out together — the page waits for the slower of the two rather
 * than for their sum.
 *
 * Either can fail on its own without blanking the page: a missing detail is the
 * "not found" state, while a failed board just renders empty and the client
 * poller fills it in on the next tick.
 */
async function loadRfq(token: string, id: number) {
  const [detail, board] = await Promise.all([
    sellerApi.rfq(token, id).catch(() => null as ApiSellerQuotationDetail | null),
    sellerApi
      .rfqLeaderboard(token, id)
      .then((r) => ({ rows: r.data ?? [], meta: r.meta }))
      .catch(() => ({ rows: [] as ApiLeaderboardRow[], meta: null as ApiLeaderboardMeta | null })),
  ]);

  return { detail, board };
}

/**
 * The seller's side of one auction, in the order the seller works through it:
 * 1. the RFQ, 2. what exactly the buyer wants (sizes, quantities, message),
 * 3. their rate, 4. where that rate ranks. Steps 1 and 2 sit in the left
 * column and 3 and 4 in the right on wide screens; on a phone they stack in
 * that order.
 *
 * Both requests are issued during SSR off the cookie token, so the browser gets
 * a populated page; only the bid form and the live board hydrate.
 */
export default async function SellerQuotationDetailPage({ params }: PageProps) {
  const { id } = await params;
  const rfqId = Number(id);
  const path = `/seller/quotations/${id}`;

  const token = await requireServerToken(path);
  await requireRole(["seller"]);

  const { detail: rfq, board } = await loadRfq(token, rfqId);

  if (!rfq) {
    return (
      <div className="rounded-xl bg-white p-10 text-center text-gray-500 shadow-sm">
        RFQ not found, or it was not sent to you.
      </div>
    );
  }

  const isLive = rfq.bidding?.is_live ?? false;
  const unit = formatUnit(rfq.unit_label);
  // The invitation itself; it carries a rate only once the seller has bid.
  const reply = rfq.my_reply;
  const hasBid = reply?.for_price != null;
  // Older size-wise RFQs carry no total of their own; add up the rows.
  const quantity = rfq.quantity || variationTotal(rfq.variation) || null;

  return (
    <div className="space-y-4">
      <Link
        href="/seller/quotations"
        className="inline-flex items-center gap-1 text-sm text-gray-600 hover:text-[#CC1414]"
      >
        <ArrowLeft className="h-4 w-4" /> Back to RFQs
      </Link>

      <div className="grid grid-cols-1 items-start gap-4 lg:grid-cols-2">
        <div className="space-y-4">
          {/* 1. New RFQ Received ------------------------------------------- */}
          <div className="rounded-xl bg-white p-5 shadow-sm ring-1 ring-gray-100">
            <div className="mb-4 flex flex-wrap items-start justify-between gap-2">
              <h1 className="text-base font-semibold text-gray-900">
                1. {hasBid ? "RFQ Details" : "New RFQ Received"}
              </h1>
              {isLive ? (
                <span className="inline-flex items-center gap-1.5 rounded-full bg-amber-50 px-2.5 py-1 text-xs font-semibold text-amber-800 ring-1 ring-amber-200">
                  <span className="h-1.5 w-1.5 animate-pulse rounded-full bg-amber-600" /> LIVE
                </span>
              ) : (
                <span className="rounded-full bg-gray-100 px-2.5 py-1 text-xs font-semibold text-gray-600">
                  Closed
                </span>
              )}
            </div>

            <div className="mb-4 flex flex-wrap items-baseline justify-between gap-2">
              <p className="text-sm text-gray-500">
                RFQ ID: <span className="font-medium text-gray-900">{rfq.unique_id}</span>
              </p>
              {isLive && (
                <Countdown
                  endsAt={rfq.bidding.ends_at}
                  fallbackSeconds={rfq.bidding.seconds_left}
                  className="text-sm font-semibold text-[#CC1414]"
                />
              )}
            </div>

            <dl className="space-y-3 rounded-xl bg-gray-50 p-4 text-sm ring-1 ring-gray-100">
              <Field label="Product">
                {[rfq.product?.name, rfq.size_label].filter(Boolean).join(" ") || "—"}
                {rfq.brand?.name ? ` · ${rfq.brand.name}` : ""}
              </Field>
              <Field label="Quantity">
                {quantity ? `${quantity} ${unit}` : "—"}
              </Field>
              <Field label="Delivery City">{rfq.delivery_city ?? "—"}</Field>
              {rfq.price_option && (
                <Field label="Buyer's Price Option">
                  <PriceOptionBadge value={rfq.price_option} showHint className="mt-0.5" />
                </Field>
              )}
              {rfq.required_by && <Field label="Required By">{rfq.required_by}</Field>}
              {rfq.payment_mode && (
                <Field label="Payment">
                  {rfq.payment_mode}
                  {rfq.credit_day ? ` · ${rfq.credit_day} days` : ""}
                </Field>
              )}
            </dl>

            {/* The buyer's identity and full address are withheld until the order
                is confirmed — the API does not send them, and saying so here stops
                sellers hunting for a contact that is not there. */}
            <p className="mt-3 rounded-lg bg-emerald-50 p-3 text-xs text-emerald-800 ring-1 ring-emerald-100">
              Only the delivery city is visible. Full delivery details are shared after order confirmation.
            </p>
          </div>

          {/* 2. Requirement ------------------------------------------------- */}
          <section className="rounded-xl bg-white p-5 shadow-sm ring-1 ring-gray-100">
            <h2 className="mb-3 text-base font-semibold text-gray-900">2. Requirement</h2>
            <RequirementSpec
              bare
              hidePrices
              unit={unit}
              variation={rfq.variation}
              quality={rfq.quality}
              packaging={rfq.packaging_charge}
              empty={
                <p className="text-sm text-gray-700">
                  {quantity ? `${quantity} ${unit}` : "Quantity not given"}
                  {rfq.size_label ? ` of ${rfq.size_label}` : ""}. No size-wise breakdown.
                </p>
              }
            />

            <div className="mt-4 rounded-lg bg-amber-50/70 p-3 ring-1 ring-amber-100">
              <p className="flex items-center gap-1.5 text-xs font-semibold text-gray-700">
                <MessageSquareText className="h-3.5 w-3.5 text-amber-700" /> Message from the buyer
              </p>
              <p className={`mt-1 whitespace-pre-wrap text-sm ${rfq.description ? "text-gray-800" : "text-gray-400"}`}>
                {rfq.description || "The buyer did not add a message."}
              </p>
              {rfq.purpose && (
                <p className="mt-2 text-xs text-gray-500">
                  Purpose: <span className="font-medium text-gray-700">{rfq.purpose}</span>
                </p>
              )}
            </div>
          </section>

        </div>

        {/* 3 + 4: bid form and the live board. */}
        <div className="space-y-4">
          <BidPanel
            rfqId={rfq.id}
            unit={unit}
            pricing={rfq.pricing}
            quotedBasePrice={reply?.quoted_base_price ?? null}
            exWorksCity={reply?.ex_works_city ?? null}
            currentExWorks={reply?.ex_works_price ?? null}
            dispatchWithinDays={rfq.order_terms?.dispatch_within_days ?? null}
            creditDays={rfq.order_terms?.credit_days ?? null}
            commission={reply?.commission ?? null}
            commissionType={reply?.commission_type ?? null}
            isLive={isLive}
            endsAt={rfq.bidding?.ends_at ?? null}
            secondsLeft={rfq.bidding?.seconds_left ?? 0}
            initialRows={board.rows}
            initialMeta={board.meta}
          />

          <div className="rounded-xl bg-white shadow-sm ring-1 ring-gray-100">
            <p className="border-b border-gray-100 px-4 py-2.5 text-xs font-semibold uppercase tracking-wide text-gray-500">
              How it works
            </p>
            <ul className="space-y-2.5 p-4 text-xs text-gray-600">
              <HowItWorks icon={<Gavel className="h-3.5 w-3.5" />}>
                Enter your basic price — the gauge difference, your charges and GST are added to give the Ex price of each size.
              </HowItWorks>
              <HowItWorks icon={<Truck className="h-3.5 w-3.5" />}>
                Preference is given to the lowest price.
              </HowItWorks>
              <HowItWorks icon={<TrendingUp className="h-3.5 w-3.5" />}>
                Improve your price before the timer ends to stay competitive.
              </HowItWorks>
              <HowItWorks icon={<Info className="h-3.5 w-3.5" />}>
                Competing sellers stay anonymous — you only see their prices.
              </HowItWorks>
            </ul>
          </div>
        </div>
      </div>
    </div>
  );
}

function Field({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div>
      <dt className="text-xs text-gray-500">{label}</dt>
      <dd className="font-medium text-gray-900">{children}</dd>
    </div>
  );
}

function HowItWorks({ icon, children }: { icon: React.ReactNode; children: React.ReactNode }) {
  return (
    <li className="flex items-start gap-2">
      <span className="mt-0.5 text-[#CC1414]">{icon}</span>
      <span>{children}</span>
    </li>
  );
}
