"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { useSearchParams } from "next/navigation";
import { useDispatch, useSelector } from "react-redux";
import type { AppDispatch, RootState } from "@/state/store";
import {
  fetchOffers,
  fetchOfferById,
  updateOffersStatus,
  deleteOffers,
  clearSelectedOffer,
  setSelectedOffer,
} from "@/state/offer/offerSlice";
import type { Offer, OfferStatus } from "@/types/offer";
import { useClickOutside } from "@/hooks/useClickOutside";
import DataTable, { type Column } from "../common/DataTable";
import ExportDropdown from "../common/ExportDropdown";
import FiltersDropdown from "../common/FiltersDropdown";
import type { ExportColumn } from "../common/export-utils";
import {
  CheckCircleIcon,
  EyeViewIcon,
  ExportArrowIcon,
  KebabIcon,
  LensThumb,
  TrashIcon,
  XCircleIcon,
} from "../dashboard/icons";
import OfferDetailsDrawer from "./OfferDetailsDrawer";
import OfferStatusBadge from "./OfferStatusBadge";
import { getImageUrl } from "@/lib/imageUrl";
import { formatListingNo } from "@/lib/listingNo";
import ProductImage from "../common/ProductImage";
import RemoveOfferModal from "./RemoveOfferModal";

const exportColumns: ExportColumn<Offer>[] = [
  {
    key: "listingNo",
    label: "Product No.",
    getValue: (o: Offer) => formatListingNo(o.product?.listingNo),
  },
  {
    key: "product",
    label: "Product",
    getValue: (o: Offer) => o.product?.title || "",
  },
  {
    key: "offerAmount",
    label: "Offer",
    getValue: (o: Offer) =>
      `$${Number(o.offerPrice).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`,
  },
  {
    key: "buyerName",
    label: "Buyer",
    getValue: (o: Offer) =>
      `${o.buyer?.firstName || ""} ${o.buyer?.lastName || ""}`.trim(),
  },
  {
    key: "sellerName",
    label: "Seller",
    getValue: (o: Offer) =>
      `${o.seller?.firstName || ""} ${o.seller?.lastName || ""}`.trim() ||
      o.seller?.businessName ||
      "",
  },
  {
    key: "date",
    label: "Date",
    getValue: (o: Offer) =>
      o.createdAt ? new Date(o.createdAt).toLocaleDateString() : "",
  },
  { key: "status", label: "Status", getValue: (o: Offer) => o.status },
];

export default function OffersTable() {
  const dispatch = useDispatch<AppDispatch>();
  const searchParams = useSearchParams();

  const {
    offers,
    totalPages,
    totalResults,
    loading,
    actionLoading,
    selectedOffer,
  } = useSelector((state: RootState) => state.offer);

  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [openMenu, setOpenMenu] = useState<string | null>(null);
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(12);
  const [searchQuery, setSearchQuery] = useState("");
  const [statusFilter, setStatusFilter] = useState("All");
  const [exportOpen, setExportOpen] = useState(false);
  const [bulkExportOpen, setBulkExportOpen] = useState(false);
  const [filtersOpen, setFiltersOpen] = useState(false);
  const [deleteIds, setDeleteIds] = useState<string[] | null>(null);

  // Deep-link: If ?id=... is present in URL, fetch and open drawer
  useEffect(() => {
    const idFromUrl = searchParams.get("id");
    if (idFromUrl) {
      dispatch(fetchOfferById(idFromUrl));
    }
  }, [searchParams, dispatch]);

  // Fetch offers when page, pageSize, search, or status filter changes
  useEffect(() => {
    const timer = setTimeout(() => {
      let statusParam: OfferStatus | "all" | undefined;
      if (statusFilter === "Pending") statusParam = "pending";
      else if (statusFilter === "Shared") statusParam = "shared";
      else if (statusFilter === "Sold") statusParam = "sold";
      else if (statusFilter === "Rejected") statusParam = "rejected";
      else statusParam = "all";

      dispatch(
        fetchOffers({
          page,
          limit: pageSize,
          search: searchQuery.trim() || undefined,
          status: statusParam,
        })
      );
    }, 250);

    return () => clearTimeout(timer);
  }, [dispatch, page, pageSize, searchQuery, statusFilter]);

  const selectedOffers = useMemo(
    () => offers.filter((o) => selected.has(o.id)),
    [offers, selected]
  );

  const handleStatusChange = async (ids: string[], status: OfferStatus) => {
    await dispatch(updateOffersStatus({ ids, status }));
  };

  const handleDeleteConfirm = async () => {
    if (deleteIds && deleteIds.length > 0) {
      await dispatch(deleteOffers(deleteIds));
      setSelected((prev) => {
        const next = new Set(prev);
        deleteIds.forEach((id) => next.delete(id));
        return next;
      });
      setDeleteIds(null);
    }
  };

  const columns: Column<Offer>[] = [
    {
      key: "id",
      label: "ID",
      sortable: true,
      sortValue: (offer) => offer.product?.listingNo ?? 0,
      render: (offer) => (
        <span className="text-[14px] font-medium text-[var(--color-blue)]">
          {formatListingNo(offer.product?.listingNo)}
        </span>
      ),
    },
    {
      key: "product",
      label: "Product",
      sortable: true,
      sortValue: (offer) => offer.product?.title || "",
      render: (offer) => {
        const productTitle = offer.product?.title || "Unknown Product";
        return (
          <div className="flex items-center gap-2.5">
            <ProductImage
              src={offer.product?.images?.[0]}
              alt={productTitle}
            />
            <span className="max-w-[220px] truncate text-[14px] text-[#101828]">
              {productTitle}
            </span>
          </div>
        );
      },
    },
    {
      key: "offerAmount",
      label: "Offer",
      sortable: true,
      sortValue: (offer) => offer.offerPrice,
      render: (offer) => (
        <span className="whitespace-nowrap text-[13px] font-medium text-[#101828]">
          ${Number(offer.offerPrice).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
        </span>
      ),
    },
    {
      key: "buyerName",
      label: "Buyer",
      sortable: true,
      sortValue: (offer) =>
        `${offer.buyer?.firstName || ""} ${offer.buyer?.lastName || ""}`.trim(),
      render: (offer) => {
        const buyerName = offer.buyer
          ? `${offer.buyer.firstName || ""} ${offer.buyer.lastName || ""}`.trim() || "Unknown"
          : "Unknown";
        const buyerEmail = offer.buyer?.email || "—";
        return (
          <>
            <p className="whitespace-nowrap text-[13px] font-medium text-[#101828]">
              {buyerName}
            </p>
            <p className="whitespace-nowrap text-[12px] text-[var(--color-blue)]">
              {buyerEmail}
            </p>
          </>
        );
      },
    },
    {
      key: "sellerName",
      label: "Seller",
      sortable: true,
      sortValue: (offer) =>
        `${offer.seller?.firstName || ""} ${offer.seller?.lastName || ""}`.trim() ||
        offer.seller?.businessName ||
        "",
      render: (offer) => {
        const sellerName = offer.seller
          ? `${offer.seller.firstName || ""} ${offer.seller.lastName || ""}`.trim() ||
            offer.seller.businessName ||
            "—"
          : "—";
        const sellerEmail = offer.seller?.email || "—";
        return (
          <>
            <p className="whitespace-nowrap text-[13px] font-medium text-[#101828]">
              {sellerName}
            </p>
            <p className="whitespace-nowrap text-[12px] text-[var(--color-blue)]">
              {sellerEmail}
            </p>
          </>
        );
      },
    },
    {
      key: "date",
      label: "Date",
      sortable: true,
      sortValue: (offer) =>
        offer.createdAt ? new Date(offer.createdAt).getTime() : 0,
      render: (offer) => (
        <span className="whitespace-nowrap text-[13px] text-[#475467]">
          {offer.createdAt
            ? new Date(offer.createdAt).toLocaleDateString()
            : "—"}
        </span>
      ),
    },
    {
      key: "status",
      label: "Status",
      sortable: true,
      sortValue: (offer) => offer.status,
      render: (offer) => <OfferStatusBadge status={offer.status} />,
    },
  ];

  return (
    <div className="min-w-0">
      <div>
        <h1 className="text-[20px] font-bold text-[#101828]">Offers Management</h1>
        <p className="mt-1 text-[13px] text-[#667085]">
          Manage and track all offers on used products
        </p>
      </div>

      <div className="mt-6">
        <DataTable<Offer>
          columns={columns}
          data={offers}
          rowKey={(offer) => offer.id}
          searchPlaceholder="Search offers..."
          searchValue={searchQuery}
          onSearchChange={(q) => {
            setSearchQuery(q);
            setPage(1);
          }}
          showFilters
          onFiltersClick={() => setFiltersOpen((prev) => !prev)}
          filtersSlot={
            <FiltersDropdown
              open={filtersOpen}
              onClose={() => setFiltersOpen(false)}
              statusOptions={["All", "Pending", "Shared", "Sold", "Rejected"]}
              ranges={[]}
              initialStatus={new Set([statusFilter])}
              onApply={(selectedStatus) => {
                const arr = Array.from(selectedStatus);
                const active = arr.find((s) => s !== "All") || "All";
                setStatusFilter(active);
                setPage(1);
              }}
              onClear={() => {
                setStatusFilter("All");
                setPage(1);
              }}
            />
          }
          showExport
          onExportClick={() => setExportOpen((prev) => !prev)}
          exportSlot={
            <ExportDropdown<Offer>
              open={exportOpen}
              onClose={() => setExportOpen(false)}
              allRows={offers}
              selectedRows={selectedOffers}
              columns={exportColumns}
              fileName="offers"
              title="Offers Management"
            />
          }
          selectedIds={selected}
          onSelectionChange={setSelected}
          pageSize={pageSize}
          onPageSizeChange={(size) => {
            setPageSize(size);
            setPage(1);
          }}
          externalPagination={{
            currentPage: page,
            totalPages: Math.max(1, totalPages),
            onPageChange: setPage,
          }}
          renderRowActions={(offer) => (
            <RowActionMenu
              open={openMenu === offer.id}
              status={offer.status}
              onToggle={() =>
                setOpenMenu(openMenu === offer.id ? null : offer.id)
              }
              onClose={() => setOpenMenu(null)}
              onViewDetails={() => {
                setOpenMenu(null);
                dispatch(setSelectedOffer(offer));
              }}
              onMarkShared={() => {
                setOpenMenu(null);
                handleStatusChange([offer.id], "shared");
              }}
              onMarkSold={() => {
                setOpenMenu(null);
                handleStatusChange([offer.id], "sold");
              }}
              onMarkRejected={() => {
                setOpenMenu(null);
                handleStatusChange([offer.id], "rejected");
              }}
              onDelete={() => {
                setOpenMenu(null);
                setDeleteIds([offer.id]);
              }}
            />
          )}
          renderBulkActionBar={() => {
            // Each button acts only on the selected offers that can still make that change
            const pendingIds = selectedOffers.filter((o) => o.status === "pending").map((o) => o.id);
            const openIds = selectedOffers
              .filter((o) => o.status === "pending" || o.status === "shared")
              .map((o) => o.id);
            return (
              <>
                <button
                  type="button"
                  onClick={() => setDeleteIds(Array.from(selected))}
                  className="flex h-9 items-center gap-2 rounded-lg border border-[var(--color-red)] bg-white px-4 text-[13px] font-medium text-[var(--color-red)] transition-colors hover:bg-red-50 cursor-pointer"
                >
                  <TrashIcon />
                  Delete Offers
                </button>
                {openIds.length > 0 && (
                  <button
                    type="button"
                    onClick={() => handleStatusChange(openIds, "sold")}
                    className="flex h-9 items-center gap-2 rounded-lg border border-[var(--color-green)] bg-white px-4 text-[13px] font-medium text-[var(--color-green)] transition-colors hover:bg-green-50 cursor-pointer"
                  >
                    <CheckCircleIcon />
                    Mark as Sold
                  </button>
                )}
                {pendingIds.length > 0 && (
                  <button
                    type="button"
                    onClick={() => handleStatusChange(pendingIds, "shared")}
                    className="flex h-9 items-center gap-2 rounded-lg border border-[var(--color-blue)] bg-white px-4 text-[13px] font-medium text-[var(--color-blue)] transition-colors hover:bg-blue-50 cursor-pointer"
                  >
                    <CheckCircleIcon />
                    Mark as Shared
                  </button>
                )}
                {openIds.length > 0 && (
                  <button
                    type="button"
                    onClick={() => handleStatusChange(openIds, "rejected")}
                    className="flex h-9 items-center gap-2 rounded-lg border border-[var(--color-red)] bg-white px-4 text-[13px] font-medium text-[var(--color-red)] transition-colors hover:bg-red-50 cursor-pointer"
                  >
                    <XCircleIcon />
                    Mark as Rejected
                  </button>
                )}
                <div className="relative">
                  <button
                    type="button"
                    onClick={() => setBulkExportOpen((prev) => !prev)}
                    className="flex h-9 items-center gap-2 rounded-lg border border-[var(--color-blue)] bg-white px-4 text-[13px] font-medium text-[var(--color-blue)] transition-colors hover:bg-blue-50 cursor-pointer"
                  >
                    <ExportArrowIcon />
                    Export Selection
                  </button>
                  <ExportDropdown<Offer>
                    open={bulkExportOpen}
                    onClose={() => setBulkExportOpen(false)}
                    allRows={offers}
                    selectedRows={selectedOffers}
                    columns={exportColumns}
                    fileName="offers-selection"
                    title="Offers Management"
                  />
                </div>
              </>
            );
          }}
        />
      </div>

      <OfferDetailsDrawer
        offer={selectedOffer}
        open={selectedOffer !== null}
        loading={actionLoading}
        onClose={() => dispatch(clearSelectedOffer())}
        onDelete={() => {
          if (selectedOffer) setDeleteIds([selectedOffer.id]);
        }}
        onMarkShared={() => {
          if (selectedOffer) handleStatusChange([selectedOffer.id], "shared");
        }}
        onMarkSold={() => {
          if (selectedOffer) handleStatusChange([selectedOffer.id], "sold");
        }}
        onMarkRejected={() => {
          if (selectedOffer) handleStatusChange([selectedOffer.id], "rejected");
        }}
      />

      <RemoveOfferModal
        open={deleteIds !== null}
        count={deleteIds?.length ?? 0}
        onClose={() => setDeleteIds(null)}
        onConfirm={handleDeleteConfirm}
      />
    </div>
  );
}

function RowActionMenu({
  open,
  status,
  onToggle,
  onClose,
  onViewDetails,
  onMarkShared,
  onMarkSold,
  onMarkRejected,
  onDelete,
}: {
  open: boolean;
  status: OfferStatus;
  onToggle: () => void;
  onClose: () => void;
  onViewDetails: () => void;
  onMarkShared: () => void;
  onMarkSold: () => void;
  onMarkRejected: () => void;
  onDelete: () => void;
}) {
  const ref = useRef<HTMLDivElement | null>(null);
  const [openUpward, setOpenUpward] = useState(false);
  useClickOutside(ref, onClose, open);

  useEffect(() => {
    if (open && ref.current) {
      const rect = ref.current.getBoundingClientRect();
      const spaceBelow = window.innerHeight - rect.bottom;
      setOpenUpward(spaceBelow < 220);
    }
  }, [open]);

  // Sold and rejected are final, so only a pending or shared offer can still be sold or rejected
  const isOpenOffer = status === "pending" || status === "shared";

  const itemClass =
    "flex w-full items-center gap-2.5 whitespace-nowrap px-3.5 py-2 text-left text-[13px] font-medium hover:bg-[#F5F7F9] cursor-pointer";

  return (
    <div ref={ref} className={`relative ${open ? "z-50" : ""}`}>
      <button
        type="button"
        onClick={onToggle}
        className="flex h-7 w-7 items-center justify-center rounded-full text-[#667085] transition-colors hover:bg-[#F2F4F7] cursor-pointer"
      >
        <KebabIcon />
      </button>
      {open && (
        <div
          className={`absolute right-0 ${
            openUpward ? "bottom-[calc(100%+4px)]" : "top-[calc(100%+4px)]"
          } z-50 min-w-[170px] rounded-lg border border-[#E4E7EC] bg-white py-1.5 shadow-[0_10px_24px_rgba(15,23,42,0.12)]`}
        >
          <button
            type="button"
            onClick={onViewDetails}
            className={`${itemClass} text-[#344054]`}
          >
            <EyeViewIcon />
            View Details
          </button>
          {status === "pending" && (
            <button
              type="button"
              onClick={onMarkShared}
              className={`${itemClass} text-[#344054]`}
            >
              <CheckCircleIcon />
              Mark as Shared
            </button>
          )}
          {isOpenOffer && (
            <button
              type="button"
              onClick={onMarkSold}
              className={`${itemClass} text-[var(--color-green)]`}
            >
              <CheckCircleIcon />
              Mark as Sold
            </button>
          )}
          {isOpenOffer && (
            <button
              type="button"
              onClick={onMarkRejected}
              className={`${itemClass} text-[var(--color-red)]`}
            >
              <XCircleIcon />
              Mark as Rejected
            </button>
          )}
          <button
            type="button"
            onClick={onDelete}
            className={`${itemClass} text-[var(--color-red)]`}
          >
            <TrashIcon />
            Remove Offer
          </button>
        </div>
      )}
    </div>
  );
}
