"use client";

import * as React from "react";
import { toast } from "sonner";

import { type Header } from "@tanstack/react-table";

import {
  DataTableHeaderActions,
  DataTablePagination,
  DataTableShell,
  DATE_COMPARISONS,
  downloadCsv,
  useDashboardTable,
} from "@/app/dashboard/_components/data-table";
import { filterOrderRowsClient } from "@/app/dashboard/plans-orders/_lib/client-column-filters";
import { ErrorBanner } from "@/components/shared/error-banner";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { TableCell } from "@/components/ui/table";
import { cn, formatCurrency } from "@/lib/utils";

import type { OrdersResult } from "../_lib/orders-server-api";
import { fetchOrders } from "./api/orders.api";
import { createOrderColumns } from "./columns";
import {
  TRANSACTION_TYPE_OPTIONS,
  buildOrderStatusOptions,
  buildOrderTypeOptions,
  emptyOrderClientFilters,
  type DateComparison,
  type OrderClientFilters,
  type OrderRow,
} from "./schema";

const ALL_FILTER_VALUE = "__all__";

function toSelectValue(value: string) {
  return value || ALL_FILTER_VALUE;
}

function fromSelectValue(value: string) {
  return value === ALL_FILTER_VALUE ? "" : value;
}

function exportOrders(rows: OrderRow[]) {
  downloadCsv({
    filename: "orders",
    headers: [
      "Order UID",
      "Customer",
      "Email",
      "Plan",
      "Subtotal",
      "Discount",
      "Tax",
      "Total",
      "Currency",
      "Payment Type",
      "Status",
      "Date",
    ],
    rows,
    toRow: (row) => [
      row.uid,
      row.customerName,
      row.customerEmail,
      row.planName,
      row.subtotal,
      row.discount,
      row.taxValue,
      row.total,
      row.currency,
      row.transactionTypeLabel,
      row.statusLabel,
      row.dateAddedIso,
    ],
  });
}

type OrdersTableProps = {
  initialData: OrdersResult;
  initialErrorMessage?: string | null;
};

export function OrdersTable({
  initialData,
  initialErrorMessage = null,
}: OrdersTableProps) {
  const [data, setData] = React.useState(initialData);
  const [errorMessage, setErrorMessage] = React.useState(initialErrorMessage);
  const [isRefreshing, setIsRefreshing] = React.useState(false);
  const [toolbarStatus, setToolbarStatus] = React.useState(toSelectValue(initialData.filters.status));
  const [toolbarType, setToolbarType] = React.useState(toSelectValue(initialData.filters.type));
  const [toolbarDateStart, setToolbarDateStart] = React.useState(initialData.filters.date_start);
  const [toolbarDateEnd, setToolbarDateEnd] = React.useState(initialData.filters.date_end);

  const statusOptions = React.useMemo(
    () => buildOrderStatusOptions(data.filterOptions.statuses),
    [data.filterOptions.statuses],
  );
  const orderTypeOptions = React.useMemo(
    () => buildOrderTypeOptions(data.filterOptions.types),
    [data.filterOptions.types],
  );

  const loadOrders = React.useCallback(async (nextFilters: typeof initialData.filters, showToast = false) => {
    setIsRefreshing(true);
    try {
      const result = await fetchOrders(nextFilters);
      setData(result);
      setErrorMessage(null);
      if (showToast) toast.success("Orders refreshed");
    } catch (error) {
      const message = error instanceof Error ? error.message : "Failed to load orders";
      setErrorMessage(message);
      toast.error(message);
    } finally {
      setIsRefreshing(false);
    }
  }, []);

  const columns = React.useMemo(
    () => createOrderColumns({ onDeleted: () => void loadOrders(data.filters) }),
    [data.filters, loadOrders],
  );

  const { filters, resetPage, filteredData, table, updateFilter } =
    useDashboardTable<OrderRow, OrderClientFilters>({
      data: data.items,
      columns,
      initialFilters: emptyOrderClientFilters,
      filterRows: filterOrderRowsClient,
      getRowId: (row) => String(row.id),
    });

  const applyToolbarSearch = () => {
    const nextFilters = {
      type: fromSelectValue(toolbarType),
      status: fromSelectValue(toolbarStatus),
      date_start: toolbarDateStart,
      date_end: toolbarDateEnd,
    };

    resetPage();
    void loadOrders(nextFilters, true);
  };

  const completedCount = filteredData.filter((r) => r.status === "complete").length;
  const pendingCount = filteredData.filter((r) =>
    ["pending", "due", "incomplete"].includes(r.status),
  ).length;
  const revenue = filteredData
    .filter((r) => r.status === "complete")
    .reduce((sum, r) => sum + r.total, 0);

  return (
    <div className="space-y-4">
      <ErrorBanner message={errorMessage} />

      <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
        <SummaryTile label="Orders" value={String(filteredData.length)} tone="muted" />
        <SummaryTile label="Completed" value={String(completedCount)} tone="emerald" />
        <SummaryTile label="In progress" value={String(pendingCount)} tone="amber" />
        <SummaryTile label="Revenue (completed)" value={formatCurrency(revenue)} tone="primary" />
      </div>

      <div className="flex flex-col gap-3 lg:flex-row lg:items-end lg:justify-between">
        <div className="flex flex-wrap items-end gap-2">
          <div className="space-y-1">
            <Label htmlFor="orders-toolbar-status" className="text-xs">
              Status
            </Label>
            <Select value={toolbarStatus} onValueChange={setToolbarStatus}>
              <SelectTrigger id="orders-toolbar-status" className="h-9 w-[180px]">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectGroup>
                  {statusOptions.map((option) => (
                    <SelectItem key={option.value} value={toSelectValue(option.value)}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectGroup>
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-1">
            <Label htmlFor="orders-toolbar-type" className="text-xs">
              Order type
            </Label>
            <Select value={toolbarType} onValueChange={setToolbarType}>
              <SelectTrigger id="orders-toolbar-type" className="h-9 w-[180px]">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectGroup>
                  {orderTypeOptions.map((option) => (
                    <SelectItem key={option.value} value={toSelectValue(option.value)}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectGroup>
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-1">
            <Label htmlFor="orders-toolbar-date-start" className="text-xs">
              From
            </Label>
            <Input
              id="orders-toolbar-date-start"
              type="date"
              value={toolbarDateStart}
              onChange={(event) => setToolbarDateStart(event.target.value)}
              className="h-9 w-[160px]"
            />
          </div>
          <div className="space-y-1">
            <Label htmlFor="orders-toolbar-date-end" className="text-xs">
              To
            </Label>
            <Input
              id="orders-toolbar-date-end"
              type="date"
              value={toolbarDateEnd}
              onChange={(event) => setToolbarDateEnd(event.target.value)}
              className="h-9 w-[160px]"
            />
          </div>
          <Button
            type="button"
            className="h-9"
            onClick={applyToolbarSearch}
            disabled={isRefreshing}
          >
            {isRefreshing ? "Searching..." : "Search"}
          </Button>
        </div>
      </div>

      <DataTableShell
        table={table}
        columnCount={columns.length}
        emptyMessage="No orders match your filters."
        renderFilterCell={(header) => renderFilterCell(header, filters, updateFilter)}
      />

      <DataTablePagination
        table={table}
        totalRows={filteredData.length}
        itemNoun="order"
        idPrefix="orders"
      />
    </div>
  );
}

const summaryToneClass: Record<"muted" | "emerald" | "amber" | "primary", string> = {
  muted: "bg-muted/40 text-foreground",
  emerald: "bg-emerald-50 text-emerald-700",
  amber: "bg-amber-50 text-amber-800",
  primary: "bg-primary/10 text-primary",
};

function SummaryTile({
  label,
  value,
  tone,
}: {
  label: string;
  value: string;
  tone: keyof typeof summaryToneClass;
}) {
  return (
    <div className={cn("rounded-lg border px-4 py-3", summaryToneClass[tone])}>
      <div className="text-[11px] uppercase tracking-wide opacity-80">{label}</div>
      <div className="mt-1 font-semibold text-xl leading-tight tabular-nums">{value}</div>
    </div>
  );
}

function renderFilterCell(
  header: Header<OrderRow, unknown>,
  filters: OrderClientFilters,
  updateFilter: <K extends keyof OrderClientFilters>(key: K, value: OrderClientFilters[K]) => void,
) {
  const columnId = header.column.id;

  if (columnId === "uid") {
    return (
      <TableCell key={header.id} className="p-2">
        <Input
          value={filters.uid}
          onChange={(event) => updateFilter("uid", event.target.value)}
          placeholder="Order UID"
          className="h-8 bg-background text-xs"
        />
      </TableCell>
    );
  }

  if (columnId === "customer") {
    return (
      <TableCell key={header.id} className="p-2">
        <Input
          value={filters.customer}
          onChange={(event) => updateFilter("customer", event.target.value)}
          placeholder="Name or email"
          className="h-8 bg-background text-xs"
        />
      </TableCell>
    );
  }

  if (columnId === "total") {
    return (
      <TableCell key={header.id} className="p-2">
        <Input
          value={filters.total}
          onChange={(event) => updateFilter("total", event.target.value)}
          placeholder="Total"
          className="h-8 bg-background text-xs"
        />
      </TableCell>
    );
  }

  if (columnId === "transactionType") {
    return (
      <TableCell key={header.id} className="p-2">
        <Select
          value={filters.transactionType}
          onValueChange={(value) => updateFilter("transactionType", value)}
        >
          <SelectTrigger className="h-8 bg-background text-xs">
            <SelectValue placeholder="Type" />
          </SelectTrigger>
          <SelectContent>
            {TRANSACTION_TYPE_OPTIONS.map((option) => (
              <SelectItem key={option.value} value={option.value}>
                {option.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </TableCell>
    );
  }

  if (columnId === "dateAdded") {
    return (
      <TableCell key={header.id} className="p-2">
        <div className="flex items-center gap-1">
          <Select
            value={filters.dateComparison}
            onValueChange={(value) => updateFilter("dateComparison", value as DateComparison)}
          >
            <SelectTrigger className="h-8 w-14 bg-background px-2 text-xs">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              {DATE_COMPARISONS.map((opt) => (
                <SelectItem key={opt.value} value={opt.value}>
                  {opt.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Input
            type="date"
            value={filters.date}
            onChange={(event) => updateFilter("date", event.target.value)}
            className="h-8 flex-1 bg-background text-xs"
          />
        </div>
      </TableCell>
    );
  }

  return null;
}

export function OrdersHeaderActions({ data }: { data: OrderRow[] }) {
  return (
    <DataTableHeaderActions
      createHref="/dashboard/plans-orders/orders/create"
      onExport={() => exportOrders(data)}
    />
  );
}
