"use client";

import { useMemo } from "react";
import Link from "next/link";
import { useQuery } from "@tanstack/react-query";
import { ArrowUpRight, Package } from "lucide-react";
import { PageHeader } from "@/components/shared/page-header";
import { DebouncedSearch } from "@/components/shared/debounced-search";
import { Pagination } from "@/components/shared/pagination";
import { EmptyState, ErrorState, TableSkeleton } from "@/components/shared/states";
import { OrderStatusBadge } from "@/components/shared/status-badges";
import { OfferCountdown } from "@/features/orders/offer-status";
import { OrderLegBadge, WrappedOrderLink } from "@/features/orders/wrapped-order-link";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { getOrders, ORDER_STATUSES, type OrderListFilters } from "@/services/orders";
import { getStoreClients } from "@/services/store-clients";
import { queryKeys } from "@/lib/query-keys";
import { useUrlState } from "@/lib/use-url-state";
import { useI18n, useT } from "@/i18n";
import { useCan } from "@/features/auth/use-can";
import { formatCurrency, formatDateTime, truncate } from "@/lib/format";
import { friendlyErrorMessage } from "@/lib/errors";
import type { OrderStatus } from "@/types/order";

export default function OrdersPage() {
  const t = useT();
  const { locale } = useI18n();
  const { can } = useCan();

  const [page, setPage] = useUrlState("page", 1, (value) => {
    const n = Number(value);
    return Number.isFinite(n) && n >= 1 ? n : null;
  });
  const [status, setStatus] = useUrlState<OrderStatus | "">("status", "", (value) =>
    (ORDER_STATUSES as string[]).includes(value) ? (value as OrderStatus) : null,
  );
  const [search, setSearch] = useUrlState("search", "", (value) => value);
  // Deep-linked from a store's page, so "show me everything from this shop" is one click.
  const [storeUuid, setStoreUuid] = useUrlState("store_client_uuid", "", (value) => value);

  const filters = useMemo<OrderListFilters>(
    () => ({
      page,
      rows: 10,
      search: search || undefined,
      status: status || undefined,
      store_client_uuid: storeUuid || undefined,
    }),
    [page, search, status, storeUuid],
  );

  const { data, isLoading, isError, error, refetch } = useQuery({
    queryKey: queryKeys.orders.list(filters),
    queryFn: () => getOrders(filters),
  });

  // Only approved stores can have sent anything, so the picker lists those. Skipped entirely
  // for an admin without the directory permission — the orders themselves are still theirs
  // to read.
  const canSeeStores = can("store_clients.view");
  const storeQuery = useQuery({
    queryKey: queryKeys.storeClients.list({ page: 1, rows: 25, status: "approved" }),
    queryFn: () => getStoreClients({ page: 1, rows: 25, status: "approved" }),
    enabled: canSeeStores,
  });
  const storeOptions = storeQuery.data?.Model ?? [];

  const orders = data?.Model ?? [];

  return (
    <div>
      <PageHeader
        title={t("orders.title")}
        subtitle={t("orders.subtitle")}
        actions={
          can("orders.create") ? (
            <Link href="/orders/new">
              <Button>{t("orders.create")}</Button>
            </Link>
          ) : null
        }
      />

      <Card>
        <div className="flex flex-col gap-3 border-b p-4 sm:flex-row sm:items-center">
          <DebouncedSearch
            value={search}
            onChange={(value) => {
              setPage(1);
              setSearch(value);
            }}
            placeholder={t("orders.searchPlaceholder")}
            className="w-full sm:max-w-xs"
          />
          <div className="flex items-center gap-2 ms-auto">
            <span className="text-xs text-muted-foreground">{t("orders.filterStatus")}</span>
            <Select
              value={status || "all"}
              onValueChange={(value) => {
                setPage(1);
                setStatus(value === "all" ? "" : (value as OrderStatus));
              }}
            >
              <SelectTrigger className="w-[10.5rem]">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">{t("common.all")}</SelectItem>
                {ORDER_STATUSES.map((option) => (
                  <SelectItem key={option} value={option}>
                    {t(`orders.status.${option}`)}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {/*
            Only offered to somebody who can see the store directory — and only rendered once a
            store filter is in play or stores exist, so a deployment with no integration does not
            grow an empty dropdown.
          */}
          {canSeeStores && storeOptions.length > 0 ? (
            <div className="flex items-center gap-2">
              <span className="text-xs text-muted-foreground">{t("orders.filterStore")}</span>
              <Select
                value={storeUuid || "all"}
                onValueChange={(value) => {
                  setPage(1);
                  setStoreUuid(value === "all" ? "" : value);
                }}
              >
                <SelectTrigger className="w-[12rem]">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="all">{t("orders.allStores")}</SelectItem>
                  {storeOptions.map((option) => (
                    <SelectItem key={option.uuid} value={option.uuid}>
                      {option.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          ) : null}
        </div>

        {isLoading ? (
          <TableSkeleton rows={8} cols={6} />
        ) : isError ? (
          <ErrorState message={friendlyErrorMessage(error, t)} onRetry={() => refetch()} />
        ) : orders.length === 0 ? (
          <EmptyState title={t("orders.empty")} description={t("orders.emptyHint")} icon={Package} />
        ) : (
          <>
            <div className="overflow-x-auto">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>{t("orders.orderNumber")}</TableHead>
                    <TableHead>{t("orders.customer")}</TableHead>
                    <TableHead>{t("orders.source")}</TableHead>
                    <TableHead>{t("orders.dropoff")}</TableHead>
                    <TableHead>{t("orders.deliveryFee")}</TableHead>
                    <TableHead>{t("orders.captain")}</TableHead>
                    <TableHead>{t("common.status")}</TableHead>
                    <TableHead>{t("common.createdAt")}</TableHead>
                    <TableHead aria-label={t("common.actions")} />
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {orders.map((order) => {
                    /*
                      A wrapped order is two rows here on purpose — a captain is out driving the
                      collection leg, so a dispatcher has to see it. What they must not read it
                      as is a second, duplicate order.
                     
                      The server sorts the pair together with the customer's order on top, so
                      the collection leg is always the row directly beneath its parent. That is
                      what lets this be drawn as nesting rather than as a repeated label: the
                      indent, the elbow and the tinted band say "this belongs to the line above"
                      the way an indented row does in any file tree.
                    */
                    const isChild = order.leg === "collection";

                    return (
                    <TableRow key={order.uuid} className={isChild ? "bg-muted/30" : undefined}>
                      <TableCell className="font-semibold text-primary">
                        <div className="flex items-start gap-1.5">
                          {isChild ? (
                            <span
                              aria-hidden
                              className="relative ms-1 block h-4 w-4 shrink-0 self-stretch"
                            >
                              {/* elbow: down from the parent row, then across into this one */}
                              <span className="absolute start-0 top-0 h-2.5 w-px bg-border" />
                              <span className="absolute start-0 top-2.5 h-px w-3 bg-border" />
                            </span>
                          ) : null}

                          <div className="flex flex-wrap items-center gap-1.5">
                            {order.order_number}
                            <OrderLegBadge leg={order.leg} label={order.leg_label} />
                          </div>
                        </div>
                        <div className={isChild ? "ms-6" : undefined}>
                          <WrappedOrderLink order={order} />
                        </div>
                      </TableCell>
                      <TableCell>
                        <p className="font-medium text-foreground">{order.customer_name}</p>
                        {order.customer_phone ? (
                          <p className="text-xs text-muted-foreground">{order.customer_phone}</p>
                        ) : null}
                      </TableCell>
                      <TableCell>
                        {/*
                          Branching on `source`, never on `store`: the name is absent from the
                          create and assign responses, and keying off it there would label a
                          shop's own order "Back office".

                          A fed order is an ordinary order in every other respect, so this is a
                          quiet line rather than a badge — but support needs to see at a glance
                          which shop to ring, and the store's own reference is what they will
                          quote back at us.
                        */}
                        {order.source === "store_api" ? (
                          <>
                            <p className="text-sm text-foreground">
                              {order.store?.name ?? t("orders.source.store_api")}
                            </p>
                            {order.external_order_id ? (
                              <p className="text-[0.7rem] text-muted-foreground">
                                {order.external_order_id}
                              </p>
                            ) : null}
                          </>
                        ) : (
                          <span className="text-xs text-muted-foreground">
                            {t("orders.source.dashboard")}
                          </span>
                        )}
                      </TableCell>
                      <TableCell className="max-w-[16rem] text-muted-foreground">
                        {truncate(order.dropoff_address, 40)}
                      </TableCell>
                      <TableCell className="numeric">
                        {formatCurrency(order.fee, order.currency, locale)}
                      </TableCell>
                      <TableCell>{order.driver?.name ?? <span className="text-muted-foreground">{t("orders.unassigned")}</span>}</TableCell>
                      <TableCell>
                        <OrderStatusBadge status={order.status} label={order.status_label} />
                        {/* An offer is not a delivery: while one is open the row says how long is
                            left, so a dispatcher is not surprised when the order moves back. */}
                        <OfferCountdown order={order} />
                      </TableCell>
                      <TableCell className="text-xs text-muted-foreground">
                        {formatDateTime(order.created_at, locale)}
                      </TableCell>
                      <TableCell>
                        <Link href={`/orders/${order.uuid}`} className="inline-flex items-center gap-1 text-xs font-medium text-primary hover:underline">
                          {t("common.view")}
                          <ArrowUpRight className="h-3 w-3" aria-hidden />
                        </Link>
                      </TableCell>
                    </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            </div>
            <Pagination
              page={data!.Page}
              totalPages={data!.Total}
              records={data!.Records}
              onPageChange={(next) => setPage(next)}
            />
          </>
        )}
      </Card>
    </div>
  );
}