"use client";

import { useMemo, useState, useCallback, useTransition } from "react";
import { OrdersHeader } from "./components/orders-header";
import { OrderSummaryCards } from "./components/order-summary-cards";
import OrdersToolbar from "./components/orders-toolbar";
import OrdersTable from "./components/orders-table";
import { OrdersEmptyState } from "./components/orders-empty-state";
import { UpdateOrderStatusDialog } from "./components/update-order-status-dialog";
import { CancelOrderDialog } from "./components/cancel-order-dialog";
import { dateRangePresets } from "./data/orders-data";
import { formatCurrency, resolveDateRange } from "./lib/format-utils";
import { updateOrderStatus, cancelOrder } from "@/lib/actions/orders";
import type { Order, OrderStatus, FulfillmentStatus } from "./types";

const DEFAULT_PAGE_SIZE = 10;

/**
 * Keep the optimistic row in sync with what the Server Action actually
 * persists: status + derived fulfillment status (payment refunds only
 * happen through the explicit cancel flow).
 */
function deriveFulfillment(status: OrderStatus): FulfillmentStatus {
  switch (status) {
    case "shipped":
    case "delivered":
      return "fulfilled";
    case "cancelled":
      return "cancelled";
    case "processing":
      return "partially-fulfilled";
    default:
      return "unfulfilled";
  }
}

interface OrdersClientProps {
  orders: Order[];
}

export function OrdersClient({ orders: initialOrders }: OrdersClientProps) {
  const [, startTransition] = useTransition();

  // ── Filters ──
  const [searchQuery, setSearchQuery] = useState("");
  const [orderStatus, setOrderStatus] = useState("all");
  const [paymentStatus, setPaymentStatus] = useState("all");
  const [fulfillmentStatus, setFulfillmentStatus] = useState("all");
  const [dateRangeValue, setDateRangeValue] = useState("all");

  // ── Table state ──
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE);

  // ── Data ──
  // Orders held in state so status updates re-render optimistically while
  // the Server Action persists and revalidates the RSC payload.
  const [ordersList, setOrdersList] = useState(initialOrders);

  // ── Action feedback ──
  const [actionError, setActionError] = useState<string | null>(null);

  // ── Dialog state ──
  const [statusTarget, setStatusTarget] = useState<Order | null>(null);
  const [statusOpen, setStatusOpen] = useState(false);
  const [cancelTarget, setCancelTarget] = useState<Order | null>(null);
  const [cancelOpen, setCancelOpen] = useState(false);

  const hasActiveFilters =
    searchQuery.trim() !== "" ||
    orderStatus !== "all" ||
    paymentStatus !== "all" ||
    fulfillmentStatus !== "all" ||
    dateRangeValue !== "all";

  const dateRangeLabel =
    dateRangePresets.find((p) => p.value === dateRangeValue)?.label ?? "All Time";

  const handleReset = useCallback(() => {
    setSearchQuery("");
    setOrderStatus("all");
    setPaymentStatus("all");
    setFulfillmentStatus("all");
    setDateRangeValue("all");
    setPage(1);
  }, []);

  // ── Derived: filtered orders ──
  const filteredOrders = useMemo(() => {
    const q = searchQuery.toLowerCase().trim();
    const range = resolveDateRange(dateRangeValue);

    return ordersList.filter((order) => {
      const matchesSearch =
        q === "" ||
        order.orderNumber.toLowerCase().includes(q) ||
        order.customer.name.toLowerCase().includes(q) ||
        order.customer.email.toLowerCase().includes(q);

      const matchesStatus =
        orderStatus === "all" || order.status === orderStatus;
      const matchesPayment =
        paymentStatus === "all" || order.payment.status === paymentStatus;
      const matchesFulfillment =
        fulfillmentStatus === "all" ||
        order.fulfillmentStatus === fulfillmentStatus;

      let matchesDate = true;
      if (range.from || range.to) {
        const orderDate = new Date(order.date);
        if (range.from) {
          const fromDate = new Date(`${range.from}T00:00:00`);
          if (orderDate < fromDate) matchesDate = false;
        }
        if (range.to) {
          const toDate = new Date(`${range.to}T23:59:59.999`);
          if (orderDate > toDate) matchesDate = false;
        }
      }

      return (
        matchesSearch &&
        matchesStatus &&
        matchesPayment &&
        matchesFulfillment &&
        matchesDate
      );
    });
  }, [
    ordersList,
    searchQuery,
    orderStatus,
    paymentStatus,
    fulfillmentStatus,
    dateRangeValue,
  ]);

  const totalPages = Math.ceil(filteredOrders.length / pageSize) || 1;
  const currentPage = Math.min(page, totalPages);

  // ── Handlers ──
  const handleStatusChange = useCallback(
    (orderId: string, status: OrderStatus) => {
      setOrdersList((prev) =>
        prev.map((o) =>
          o.id === orderId
            ? { ...o, status, fulfillmentStatus: deriveFulfillment(status) }
            : o,
        ),
      );
      setActionError(null);
      startTransition(() => {
        void updateOrderStatus(orderId, status).then((result) => {
          if (!result.ok) setActionError(result.error);
        });
      });
    },
    [startTransition],
  );

  const handleCancelOrder = useCallback(
    (orderId: string, options: { refund: boolean }) => {
      setOrdersList((prev) =>
        prev.map((o) =>
          o.id === orderId
            ? {
                ...o,
                status: "cancelled",
                fulfillmentStatus: "cancelled",
                payment:
                  options.refund && o.payment.status === "paid"
                    ? { ...o.payment, status: "refunded" }
                    : o.payment,
              }
            : o,
        ),
      );
      setActionError(null);
      startTransition(() => {
        void cancelOrder(orderId, options).then((result) => {
          if (!result.ok) setActionError(result.error);
        });
      });
    },
    [startTransition],
  );

  const handleExport = useCallback(() => {
    const headers = [
      "Order ID",
      "Customer",
      "Email",
      "Items",
      "Subtotal",
      "Shipping",
      "Discount",
      "Tax",
      "Total",
      "Payment Status",
      "Order Status",
      "Created",
    ];

    const rows = filteredOrders.map((o) => [
      o.orderNumber,
      o.customer.name,
      o.customer.email,
      o.items.map((i) => `${i.name} x${i.quantity}`).join(" | "),
      formatCurrency(o.subtotal),
      formatCurrency(o.shippingCost),
      formatCurrency(o.discount),
      formatCurrency(o.tax),
      formatCurrency(o.grandTotal),
      o.payment.status,
      o.status,
      o.date,
    ]);

    const csvContent = [headers, ...rows]
      .map((row) => row.map((cell) => `"${cell}"`).join(","))
      .join("\n");

    const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
    const link = document.createElement("a");
    const url = URL.createObjectURL(blob);
    link.setAttribute("href", url);
    link.setAttribute(
      "download",
      `orders-export-${new Date().toISOString().split("T")[0]}.csv`,
    );
    link.style.visibility = "hidden";
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
  }, [filteredOrders]);

  const showTable = filteredOrders.length > 0;

  return (
    <div className="flex flex-col gap-6">
      {/* Header */}
      <OrdersHeader dateRangeLabel={dateRangeLabel} />

      {/* Action feedback */}
      {actionError && (
        <div className="flex items-center justify-between gap-4 rounded-lg border border-destructive/40 bg-destructive/5 px-4 py-3 text-sm text-destructive">
          <span>{actionError}</span>
          <button
            type="button"
            aria-label="Dismiss"
            onClick={() => setActionError(null)}
            className="text-destructive/70 hover:text-destructive"
          >
            ✕
          </button>
        </div>
      )}

      {/* Summary cards */}
      <OrderSummaryCards orders={filteredOrders} />

      {/* Toolbar */}
      <OrdersToolbar
        searchQuery={searchQuery}
        onSearchChange={(q) => {
          setSearchQuery(q);
          setPage(1);
        }}
        orderStatus={orderStatus}
        onOrderStatusChange={(v) => {
          setOrderStatus(v);
          setPage(1);
        }}
        paymentStatus={paymentStatus}
        onPaymentStatusChange={(v) => {
          setPaymentStatus(v);
          setPage(1);
        }}
        fulfillmentStatus={fulfillmentStatus}
        onFulfillmentStatusChange={(v) => {
          setFulfillmentStatus(v);
          setPage(1);
        }}
        dateRange={dateRangeValue}
        onDateRangeChange={(v) => {
          setDateRangeValue(v);
          setPage(1);
        }}
        onExport={handleExport}
        onReset={handleReset}
        hasActiveFilters={hasActiveFilters}
      />

      {/* Table / empty state */}
      {showTable ? (
        <OrdersTable
          orders={filteredOrders}
          page={currentPage}
          pageSize={pageSize}
          totalPages={totalPages}
          onPageChange={setPage}
          onPageSizeChange={(size) => {
            setPageSize(size);
            setPage(1);
          }}
          onUpdateStatus={(order) => {
            setStatusTarget(order);
            setStatusOpen(true);
          }}
          onCancelOrder={(order) => {
            setCancelTarget(order);
            setCancelOpen(true);
          }}
        />
      ) : (
        <OrdersEmptyState
          hasActiveFilters={hasActiveFilters}
          onReset={handleReset}
        />
      )}

      {/* Dialogs */}
      {statusTarget && (
        <UpdateOrderStatusDialog
          order={statusTarget}
          open={statusOpen}
          onOpenChange={setStatusOpen}
          onConfirm={(status) => handleStatusChange(statusTarget.id, status)}
        />
      )}
      {cancelTarget && (
        <CancelOrderDialog
          order={cancelTarget}
          open={cancelOpen}
          onOpenChange={setCancelOpen}
          onConfirm={(options) => handleCancelOrder(cancelTarget.id, options)}
        />
      )}
    </div>
  );
}