"use client";

import { Banknote, HandCoins, TriangleAlert } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { useI18n, useT } from "@/i18n";
import { formatCurrency, formatDateTime } from "@/lib/format";
import type { Order } from "@/types/order";

/**
 * The money on one order: what it cost, what it yielded, and every movement behind those figures.
 *
 * **Expected and actual are shown side by side, never one in place of the other.** A captain pays
 * what the supplier asks and takes what the customer hands over, and neither has to match what the
 * order said — a short collection is a real event that somebody has to see, and replacing the
 * expected figure with the actual one hides exactly the case worth looking at.
 *
 * The rows name their captain because the captain who paid and the captain who collected need not
 * be the same person: after a handover, one captain is owed for the goods while another is holding
 * the customer's cash.
 */
export function OrderMoney({ order }: { order: Order }) {
  const t = useT();
  const { locale } = useI18n();

  const settlement = order.settlement ?? null;
  const currency = order.currency;

  // Read from the settlement block when the detail carried it, and from the order otherwise, so
  // the card still says what it knows on an order whose ledger was never loaded.
  const expected = settlement?.expected_goods_cost ?? null;
  const paid = settlement?.amount_paid ?? order.amount_paid ?? null;
  const toCollect = settlement?.amount_to_collect ?? order.amount_to_collect ?? null;
  const collected = settlement?.amount_collected ?? order.amount_collected ?? null;
  const entries = settlement?.entries ?? [];

  /*
   * The order's own cash flow, preferring the across-legs figures wherever they are sent.
   *
   * They are only ever present on the delivery leg of a wrapped order, and there they are the
   * only honest answer: that row buys nothing, so on its own it reads as pure profit for an
   * order whose goods were paid for on the leg next to it.
   */
  const acrossLegs = settlement?.cash_flow?.across_legs ?? null;
  const cashFlow = acrossLegs ?? settlement?.cash_flow ?? null;

  // The order's own total. The server decides it — the fee is part of `amount_to_collect`, not an
  // extra on top — so nothing is added up here; falling back to the order's own fields only keeps
  // the line alive on a read that never loaded the ledger.
  const goodsValue = settlement?.goods_value ?? null;
  const fee = settlement?.delivery_fee ?? order.fee ?? null;
  const total = settlement?.customer_total ?? order.amount_to_collect ?? null;
  const totalIsComputed = settlement?.customer_total_is_computed ?? false;
  const mismatch = settlement?.total_mismatch ?? null;

  // Nothing to show at all: an order nobody has spent or taken money on, with no prices on it.
  if (expected === null && paid === null && toCollect === null && collected === null && total === null) {
    return null;
  }

  return (
    <Card className="mt-6">
      <CardHeader>
        <CardTitle className="flex items-center gap-2">
          <HandCoins className="h-4 w-4 text-primary" aria-hidden />
          {t("orders.money.title")}
        </CardTitle>
      </CardHeader>
      <CardContent className="space-y-6">
        {/*
          The order's total, first and largest, because it is the figure anybody opening this screen
          came to read — and beneath it the two parts it is made of, so "why is it 93,000" is
          answered on the same line rather than by adding the items up by hand.
        */}
        {total !== null ? (
          <div className="rounded-lg border bg-muted/40 p-4">
            <div className="flex flex-wrap items-baseline justify-between gap-2">
              <p className="text-xs text-muted-foreground">{t("orders.money.total")}</p>
              <p className="numeric text-2xl font-semibold text-foreground">
                {formatCurrency(total, currency, locale)}
              </p>
            </div>

            <div className="mt-2 space-y-1 text-xs text-muted-foreground">
              <p className="flex items-center justify-between gap-2">
                <span>{t("orders.money.goodsPart")}</span>
                <span className="numeric">
                  {goodsValue === null
                    ? t("orders.money.unpriced")
                    : formatCurrency(goodsValue, currency, locale)}
                </span>
              </p>
              <p className="flex items-center justify-between gap-2">
                <span>{t("orders.money.feePart")}</span>
                <span className="numeric">
                  {order.fee_waived ? t("orders.money.feeFree") : fee === null ? "—" : formatCurrency(fee, currency, locale)}
                </span>
              </p>

              {/*
                Why the fee is not what somebody typed.
                
                A band can price a delivery at nothing, and an operator who entered 80 and sees 0
                with no explanation concludes the form lost their input. Saying which band did it,
                and what was asked for, turns a suspected bug into a priced order.
              */}
              {order.fee_priced_by_rule ? (
                <p className="mt-1 text-xs text-muted-foreground">
                  {order.quoted_fee !== null && order.quoted_fee !== undefined
                    ? t("orders.money.feeOverruled", {
                        quoted: formatCurrency(order.quoted_fee, currency, locale),
                        area: order.fee_area?.name ?? t("common.notAvailable"),
                      })
                    : t("orders.money.feeByRule", { area: order.fee_area?.name ?? t("common.notAvailable") })}
                </p>
              ) : null}

              {/*
                Which band did it, in the band's own terms.

                "Priced by the rules" answers who, not why. The band is the why: an order just
                over a threshold is charged differently from one just under, and without the
                figures there is no way to tell a deliberate free delivery from a broken ladder.
              */}
              {order.fee_rule ? (
                <p className="text-xs text-muted-foreground">
                  {t("orders.money.feeBand", {
                    from: formatCurrency(order.fee_rule.min_goods_value, currency, locale),
                    to:
                      order.fee_rule.max_goods_value === null
                        ? t("orders.money.feeBandOpen")
                        : formatCurrency(order.fee_rule.max_goods_value, currency, locale),
                    share:
                      order.fee_rule.charge_share === undefined
                        ? t("common.notAvailable")
                        : `${Math.round(order.fee_rule.charge_share * 100)}%`,
                  })}
                </p>
              ) : null}
            </div>

            {/* Said in words, not left as a discrepancy for somebody to spot in two figures. */}
            {mismatch !== null && mismatch !== 0 ? (
              <p className="mt-2 flex items-start gap-1.5 text-xs text-warning">
                <TriangleAlert className="mt-0.5 h-3.5 w-3.5 shrink-0" aria-hidden />
                {t(mismatch > 0 ? "orders.money.mismatchOver" : "orders.money.mismatchUnder", {
                  amount: formatCurrency(Math.abs(mismatch), currency, locale),
                })}
              </p>
            ) : null}

            {totalIsComputed ? (
              // A prepaid order states no total, so this one was added up. Saying so is the
              // difference between a figure a store owns and one we inferred.
              <p className="mt-2 text-xs text-muted-foreground">{t("orders.money.totalComputed")}</p>
            ) : null}
          </div>
        ) : null}

        <div className="grid gap-4 sm:grid-cols-2">
          <Figure
            label={t("orders.money.goods")}
            expectedLabel={t("orders.money.expected")}
            actualLabel={t("orders.money.paid")}
            expected={expected}
            actual={paid}
            currency={currency}
            locale={locale}
            hint={t("orders.money.goodsHint")}
            reported={settlement?.amount_variance ?? order.amount_variance ?? null}
          />
          <Figure
            label={t("orders.money.cash")}
            expectedLabel={t("orders.money.toCollect")}
            actualLabel={t("orders.money.collected")}
            expected={toCollect}
            actual={collected}
            currency={currency}
            locale={locale}
            hint={t("orders.money.cashHint")}
          />
        </div>

        {cashFlow ? (
          <div className="rounded-lg border bg-muted/30 p-3">
            <p className="text-sm font-medium text-foreground">{t("orders.money.flowTitle")}</p>
            <p className="mt-0.5 text-xs text-muted-foreground">
              {acrossLegs ? t("orders.money.flowAcrossLegsHint") : t("orders.money.flowHint")}
            </p>

            <dl className="mt-3 grid grid-cols-3 gap-4 text-sm">
              <div>
                <dt className="text-xs text-muted-foreground">{t("orders.money.flowOut")}</dt>
                <dd className="numeric font-medium text-foreground">
                  {formatCurrency(cashFlow.goods_paid, currency, locale)}
                </dd>
              </div>
              <div>
                <dt className="text-xs text-muted-foreground">{t("orders.money.flowIn")}</dt>
                <dd className="numeric font-medium text-foreground">
                  {formatCurrency(cashFlow.cash_collected, currency, locale)}
                </dd>
              </div>
              <div>
                <dt className="text-xs text-muted-foreground">{t("orders.money.flowNet")}</dt>
                <dd
                  className={
                    cashFlow.net < 0
                      ? "numeric font-semibold text-warning"
                      : "numeric font-semibold text-foreground"
                  }
                >
                  {formatCurrency(cashFlow.net, currency, locale)}
                </dd>
              </div>
            </dl>
          </div>
        ) : null}

        <div>
          <p className="mb-2 text-sm font-medium text-foreground">
            {t("orders.money.movements")}
          </p>
          {entries.length === 0 ? (
            <p className="text-sm text-muted-foreground">{t("orders.money.noMovements")}</p>
          ) : (
            <div className="overflow-x-auto">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>{t("orders.money.movement")}</TableHead>
                    <TableHead>{t("orders.captain")}</TableHead>
                    <TableHead>{t("ledger.amount")}</TableHead>
                    <TableHead>{t("orders.money.expected")}</TableHead>
                    <TableHead>{t("common.createdAt")}</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {entries.map((entry) => (
                    <TableRow key={entry.uuid}>
                      <TableCell className="text-sm font-medium text-foreground">
                        {entry.type_label}
                      </TableCell>
                      <TableCell className="text-sm">{entry.captain?.name ?? "—"}</TableCell>
                      <TableCell className="numeric text-sm">
                        {/* Signed from the captain's side: positive means the company owes them. */}
                        <span
                          className={
                            entry.amount < 0 ? "text-warning" : "font-medium text-foreground"
                          }
                        >
                          {formatCurrency(entry.amount, entry.currency, locale)}
                        </span>
                      </TableCell>
                      <TableCell className="numeric text-sm text-muted-foreground">
                        {entry.expected_amount === null
                          ? "—"
                          : formatCurrency(entry.expected_amount, entry.currency, locale)}
                        {entry.variance !== null && entry.variance !== 0 ? (
                          <Badge variant="warning" className="ms-2">
                            <TriangleAlert className="h-3 w-3" aria-hidden />
                            {formatCurrency(entry.variance, entry.currency, locale)}
                          </Badge>
                        ) : null}
                      </TableCell>
                      <TableCell className="text-xs text-muted-foreground">
                        {formatDateTime(entry.created_at, locale)}
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
          )}
        </div>
      </CardContent>
    </Card>
  );
}

/**
 * One pair of figures — what was expected, and what happened — with the difference named when
 * there is one.
 */
function Figure({
  label,
  expectedLabel,
  actualLabel,
  expected,
  actual,
  currency,
  locale,
  hint,
  reported,
}: {
  label: string;
  expectedLabel: string;
  actualLabel: string;
  expected: number | null;
  actual: number | null;
  currency: string | null;
  locale: "en" | "ar";
  hint: string;
  reported?: number | null;
}) {
  const t = useT();
  /*
   * The server's figure when it sent one, and the subtraction only as a fallback.
   *
   * They disagree in the case that matters: on a wrapped order's delivery leg the goods were
   * bought on the other row, so the server reports no variance while subtracting here would
   * invent one the size of the whole basket.
   */
  const variance =
    reported !== undefined && reported !== null
      ? reported
      : expected !== null && actual !== null
        ? Math.round((actual - expected) * 100) / 100
        : null;

  return (
    <div className="rounded-lg border p-4">
      <p className="flex items-center gap-2 text-xs font-medium uppercase tracking-wide text-muted-foreground">
        <Banknote className="h-3.5 w-3.5" aria-hidden />
        {label}
      </p>

      <div className="mt-3 flex flex-wrap items-baseline gap-x-6 gap-y-2">
        <span>
          <span className="block text-[0.7rem] text-muted-foreground">{expectedLabel}</span>
          <span className="numeric text-sm text-foreground">
            {expected === null ? "—" : formatCurrency(expected, currency, locale)}
          </span>
        </span>
        <span>
          <span className="block text-[0.7rem] text-muted-foreground">{actualLabel}</span>
          <span className="numeric text-lg font-semibold text-foreground">
            {actual === null ? "—" : formatCurrency(actual, currency, locale)}
          </span>
        </span>
        {variance !== null && variance !== 0 ? (
          <Badge variant="warning">
            <TriangleAlert className="h-3 w-3" aria-hidden />
            {t("orders.money.variance", {
              amount: formatCurrency(variance, currency, locale),
            })}
          </Badge>
        ) : null}
      </div>

      <p className="mt-2 text-xs text-muted-foreground">{hint}</p>
    </div>
  );
}
