import React, {
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import { AgGridReact } from "ag-grid-react";
import {
  ColDef,
  RowClassParams,
  RowNode,
  RowStyle,
  SizeColumnsToContentStrategy,
} from "ag-grid-community";
import "ag-grid-community/styles/ag-grid.css";
import "ag-grid-community/styles/ag-theme-alpine.css";
import InfoOutlineIcon from "@mui/icons-material/InfoOutline";
import {
  Alert,
  Box,
  Button,
  Checkbox,
  Dialog,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle,
  FormControlLabel,
  IconButton,
  Snackbar,
  SnackbarCloseReason,
  Tooltip,
  Typography,
} from "@mui/material";
import gameContext from "../../contexts/gameContext";
import { subscribeToEvent, unsubscribeFromEvent } from "../../utils/events";
import { useModal } from "../common/useModal";
import FileSaver from "file-saver";
import { Spacer } from "../common/Spacer";
import { Hourglass } from "react-loader-spinner";
import ErrorIcon from "@mui/icons-material/Error";
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
import { CountdownCircleTimer } from "react-countdown-circle-timer";
import {
  BuyContainer,
  BuyContainerDivider,
  BuyOrderBtn,
  MainContainer,
} from "./Table-styles";

// export const baseLocalHost = window.location.host;
export const baseLocalHost = "devnet-nodes.qortal.link:11111";

import CloseIcon from "@mui/icons-material/Close";
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
import moment from "moment";

const copyToClipboard = (text: string) => {
  navigator.clipboard.writeText(text);
};

interface RowData {
  amountQORT: number;
  priceUSD: number;
  totalUSD: number;
  seller: string;
}

export const saveFileToDisk = async (data) => {
  const dataString = JSON.stringify(data);
  const blob = new Blob([dataString], { type: "application/json" });
  const fileName = "traderecord_" + Date.now() + "_" + ".json";

  await FileSaver.saveAs(blob, fileName);
};

export const autoSizeStrategy: SizeColumnsToContentStrategy = {
  type: "fitCellContents",
};

export const TradeOffers: React.FC<any> = ({
  foreignCoinBalance,
  fee,
}: any) => {
  const [offers, setOffers] = useState<any[]>([]);
  const [signedUnlockingFees, setSignedUnlockingFees] = useState(null);
  const [qortalNames, setQortalNames] = useState({});
  const {
    fetchOngoingTransactions,
    onGoingTrades,
    updateTransactionInDB,
    isUsingGateway,
    getCoinLabel,
    selectedCoin,
  } = useContext(gameContext);
  const isRemoveOrdersWithoutUnlockingFees = useRef(false);
  const listOfOngoingTradesAts = useMemo(() => {
    return (
      onGoingTrades
        ?.filter((item) => item?.status !== "trade-failed")
        ?.map((trade) => trade?.qortalAtAddress) || []
    );
  }, [onGoingTrades]);
  const {
    isShow: isShowInfo,
    onCancel: onCancelInfo,
    onOk: onOkInfo,
    show: showInfo,
    message: messageInfo,
  } = useModal();

  const {
    isShow: isShowTradesUnknownFee,
    onCancel: onCancelTradesUnknownFee,
    onOk: onOkTradesUnknownFee,
    show: showTradesUnknownFee,
    message: messageTradesUnknownFee,
  } = useModal();

  const offersWithoutOngoing = useMemo(() => {
    return offers.filter(
      (item) => !listOfOngoingTradesAts.includes(item.qortalAtAddress)
    );
  }, [listOfOngoingTradesAts, offers]);
  const initiatedFetchPresence = useRef(false);
  const initiatedFetchPresenceSocket = useRef(false);
  const [isShowBuyInProgress, setIsShowBuyInProgress] = useState(null);
  const socketRef = useRef(null);
  const socketPresenceRef = useRef(null);
  const [selectedOffer, setSelectedOffer] = useState<any>(null);
  const [selectedOffers, setSelectedOffers] = useState<any>([]);
  const [record, setRecord] = useState(null);
  const tradePresenceTxns = useRef<any[]>([]);
  const offeringTrades = useRef<any[]>([]);
  const blockedTradesList = useRef([]);
  const gridRef = useRef<any>(null);
  const [openShowOfferDetails, setOpenShowOfferDetails] = useState(null);
  const [open, setOpen] = useState(false);
  const [info, setInfo] = useState<any>(null);
  const BuyButton = () => {
    return <BuyOrderBtn onClick={buyOrder}>BUY</BuyOrderBtn>;
  };

  const intervalGetSignedUnlockingFees = useRef<number | null>(null);

  const signedUnlockingFeesRef = useRef(signedUnlockingFees);
  const feeRef = useRef(fee);

  const knownFees = useMemo(() => {
    const offersWithKnownFees = [];

    selectedOffers.forEach((offer) => {
      const feeEntry = signedUnlockingFees.find(
        (item) => item?.atAddress === offer.qortalAtAddress
      );

      if (feeEntry && typeof feeEntry.fee === "number") {
        offersWithKnownFees.push({ ...offer, fee: feeEntry.fee });
      }
    });
    const totalKnownFees = offersWithKnownFees.reduce((sum, offer) => {
      return sum + (offer.fee || 0);
    }, 0);
    const feeInLtc = totalKnownFees / 1e8;
    return +feeInLtc.toFixed(8);
  }, [selectedOffers, signedUnlockingFees]);

  console.log("knownFees", knownFees);

  const defaultColDef = {
    resizable: true, // Make columns resizable by default
    sortable: true, // Make columns sortable by default
    suppressMovable: true, // Prevent columns from being movable
  };

  const getName = async (address) => {
    try {
      const response = await fetch("/names/address/" + address);
      const nameData = await response.json();
      if (nameData?.length > 0) {
        setQortalNames((prev) => {
          return {
            ...prev,
            [address]: nameData[0].name,
          };
        });
      } else {
        setQortalNames((prev) => {
          return {
            ...prev,
            [address]: null,
          };
        });
      }
    } catch (error) {
      // error
    }
  };

  const restartTradeOffers = () => {
    if (socketRef.current) {
      socketRef.current.close(1000, "forced"); // Close with a custom reason
      socketRef.current = null;
    }
    offeringTrades.current = [];
    setOffers([]);
    setSelectedOffer(null);
  };

  const restartPresence = () => {
    if (socketPresenceRef.current) {
      socketPresenceRef.current.close(1000, "forced"); // Close with a custom reason
      socketPresenceRef.current = null;
    }
  };

  const columnDefs: ColDef[] = useMemo(() => {
    return [
      {
        headerCheckboxSelection: true, // Adds a checkbox in the header for selecting all rows
        // checkboxSelection: true, // Adds checkboxes in each row for selection
        checkboxSelection: true, // disable default, we're rendering it manually
        headerName: "", // You can customize the header name
        width: 100, // Adjust the width as needed
        pinned: "left", // Optional, to pin this column on the left
        resizable: false,
        suppressRowClickSelection: true,

        cellRenderer: (params) => (
          <SelectWithInfoCell
            {...params}
            selectTradeForDetails={() => {
              const hasSignedFee = signedUnlockingFees?.find(
                (item) =>
                  item?.atAddress === params?.node?.data?.qortalAtAddress
              );
              let fee = null;
              if (hasSignedFee) {
                fee = hasSignedFee.fee;
              }

              setOpenShowOfferDetails({ ...(params?.node?.data || {}), fee });
            }}
          />
        ),
        // suppressRowClickSelection: true, // prevent whole row selection on click
      },
      {
        headerName: "QORT AMOUNT",
        field: "qortAmount",
        flex: 1, // Flex makes this column responsive
        minWidth: 150, // Ensure it doesn't shrink too much
        resizable: true,
      },
      {
        headerName: `${getCoinLabel()}/QORT`,
        valueGetter: (params) =>
          +params.data.foreignAmount / +params.data.qortAmount,
        sortable: true,
        sort: "asc",
        flex: 1, // Flex makes this column responsive
        minWidth: 150, // Ensure it doesn't shrink too much
        resizable: true,
      },
      {
        headerName: `Total ${getCoinLabel()} Value`,
        field: "foreignAmount",
        flex: 1, // Flex makes this column responsive
        minWidth: 150, // Ensure it doesn't shrink too much
        resizable: true,
      },
      {
        headerName: `Unlocking fee`,
        flex: 1, // Flex makes this column responsive
        minWidth: 150, // Ensure it doesn't shrink too much
        resizable: true,
        valueGetter: (params) => {
          if (params?.data?.qortalAtAddress) {
            console.log("22signedUnlockingFees", signedUnlockingFees);
            const hasSignedFee = signedUnlockingFees?.find(
              (item) => item?.atAddress === params.data.qortalAtAddress
            );
            if (!hasSignedFee) return "Unknown";
            return hasSignedFee.fee;
          } else return "Unknown";
        },
      },
      {
        headerName: "Seller",
        field: "qortalCreator",
        flex: 1, // Flex makes this column responsive
        minWidth: 300, // Ensure it doesn't shrink too much
        resizable: true,
        valueGetter: (params) => {
          if (params?.data?.qortalCreator) {
            if (qortalNames[params?.data?.qortalCreator]) {
              return qortalNames[params?.data?.qortalCreator];
            } else if (qortalNames[params?.data?.qortalCreator] === undefined) {
              getName(params?.data?.qortalCreator);

              return params?.data?.qortalCreator;
            } else {
              return params?.data?.qortalCreator;
            }
          }
        },
      },
    ];
  }, [qortalNames, getCoinLabel, signedUnlockingFees]);

  // const onRowClicked = (event: any) => {
  //   if(listOfOngoingTradesAts.includes(event.data.qortalAtAddress)) return
  //   setSelectedOffer(event.data)

  // };

  const restartTradePresenceWebSocket = () => {
    restartPresence();
    setTimeout(() => initTradePresenceWebSocket(true), 50);
  };

  const getNewBlockedTrades = async () => {
    const unconfirmedTransactionsList = async () => {
      const unconfirmedTransactionslUrl = `http://devnet-nodes.qortal.link:11112/transactions/unconfirmed?txType=MESSAGE&limit=0&reverse=true`;

      var addBlockedTrades = JSON.parse(
        localStorage.getItem("failedTrades") || "[]"
      );

      await fetch(unconfirmedTransactionslUrl)
        .then((response) => {
          return response.json();
        })
        .then((data) => {
          data.map((item: any) => {
            const unconfirmedNessageTimeDiff = Date.now() - item.timestamp;
            const timeOneHour = 60 * 60 * 1000;
            if (Number(unconfirmedNessageTimeDiff) > Number(timeOneHour)) {
              const addBlocked = {
                timestamp: item.timestamp,
                recipient: item.recipient,
              };
              addBlockedTrades.push(addBlocked);
            }
          });
          localStorage.setItem(
            "failedTrades",
            JSON.stringify(addBlockedTrades)
          );
          blockedTradesList.current = JSON.parse(
            localStorage.getItem("failedTrades") || "[]"
          );
        });
    };

    await unconfirmedTransactionsList();

    const filterUnconfirmedTransactionsList = async () => {
      let cleanBlockedTrades = blockedTradesList.current.reduce(
        (newArray, cut: any) => {
          if (
            cut &&
            !newArray.some((obj: any) => obj.recipient === cut.recipient)
          ) {
            newArray.push(cut);
          }
          return newArray;
        },
        [] as any[]
      );
      localStorage.setItem("failedTrades", JSON.stringify(cleanBlockedTrades));
      blockedTradesList.current = JSON.parse(
        localStorage.getItem("failedTrades") || "[]"
      );
    };

    await filterUnconfirmedTransactionsList();
    processOffersWithPresence();
  };

  const executeGetNewBlockTrades = useCallback(() => {
    getNewBlockedTrades();
  }, []);

  useEffect(() => {
    subscribeToEvent("execute-get-new-block-trades", executeGetNewBlockTrades);

    return () => {
      unsubscribeFromEvent(
        "execute-get-new-block-trades",
        executeGetNewBlockTrades
      );
    };
  }, []);

  const processOffersWithPresence = () => {
    if (offeringTrades.current === null) return;
    async function asyncForEach(array: any, callback: any) {
      for (let index = 0; index < array.length; index++) {
        await callback(array[index], index, array);
      }
    }

    const filterOffersUsingTradePresence = (offeringTrade: any) => {
      return offeringTrade.tradePresenceExpiry > Date.now();
    };

    const startOfferPresenceMapping = async () => {
      if (tradePresenceTxns.current) {
        for (const tradePresence of tradePresenceTxns.current) {
          const offerIndex = offeringTrades.current.findIndex(
            (offeringTrade) =>
              offeringTrade.qortalCreatorTradeAddress ===
              tradePresence.tradeAddress
          );
          if (offerIndex !== -1) {
            offeringTrades.current[offerIndex].tradePresenceExpiry =
              tradePresence.timestamp;
          }
        }
      }

      let filteredOffers =
        offeringTrades.current?.filter((offeringTrade) =>
          filterOffersUsingTradePresence(offeringTrade)
        ) || [];
      let tradesPresenceCleaned: any[] = filteredOffers;

      blockedTradesList.current.forEach((item: any) => {
        const toDelete = item.recipient;
        tradesPresenceCleaned =
          tradesPresenceCleaned?.filter((el) => {
            return el.qortalCreatorTradeAddress !== toDelete;
          }) || [];
      });

      if (tradesPresenceCleaned) {
        updateGridData(tradesPresenceCleaned);
      }
    };

    startOfferPresenceMapping();
  };

  const restartTradeOffersWebSocket = () => {
    setTimeout(() => initTradeOffersWebSocket(true), 50);
  };

  const initTradePresenceWebSocket = (restarted = false) => {
    if (socketPresenceRef.current) return;
    let socketTimeout: any;
    let socketLink;
    if (isUsingGateway) {
      socketLink = `wss://appnode.qortal.org/websockets/crosschain/tradepresence`;
    } else {
      socketLink = `${
        window.location.protocol === "https:" ? "wss:" : "ws:"
      }//${baseLocalHost}/websockets/crosschain/tradepresence`;
    }

    socketPresenceRef.current = new WebSocket(socketLink);
    socketPresenceRef.current.onopen = () => {
      setTimeout(pingSocket, 50);
    };
    socketPresenceRef.current.onmessage = (e) => {
      tradePresenceTxns.current = !initiatedFetchPresenceSocket.current
        ? JSON.parse(e.data)
        : [...tradePresenceTxns.current, ...JSON.parse(e.data)];
      initiatedFetchPresenceSocket.current = true;
      processOffersWithPresence();
      restarted = false;
    };
    socketPresenceRef.current.onclose = (event) => {
      clearTimeout(socketTimeout);
      if (event.reason === "forced") {
        return;
      }
      restartTradePresenceWebSocket();
    };
    socketPresenceRef.current.onerror = (e) => {
      clearTimeout(socketTimeout);
      restartTradePresenceWebSocket();
    };
    const pingSocket = () => {
      socketPresenceRef.current.send("ping");
      socketTimeout = setTimeout(pingSocket, 295000);
    };
  };

  const initTradeOffersWebSocket = (restarted = false) => {
    if (socketRef.current) return;
    let socketTimeout: any;

    let socketLink;
    if (isUsingGateway) {
      socketLink = `wss://appnode.qortal.org/websockets/crosschain/tradeoffers?foreignBlockchain=${selectedCoin}&includeHistoric=true`;
    } else {
      socketLink = `${
        window.location.protocol === "https:" ? "wss:" : "ws:"
      }//${baseLocalHost}/websockets/crosschain/tradeoffers?foreignBlockchain=${selectedCoin}&includeHistoric=true`;
    }
    socketRef.current = new WebSocket(socketLink);
    socketRef.current.onopen = () => {
      setTimeout(pingSocket, 50);
    };
    socketRef.current.onmessage = (e) => {
      offeringTrades.current = [
        ...offeringTrades.current?.filter(
          (coin) => coin?.foreignBlockchain === selectedCoin
        ),
        ...JSON.parse(e.data)?.filter(
          (coin) => coin?.foreignBlockchain === selectedCoin
        ),
      ];
      restarted = false;
      processOffersWithPresence();
    };
    socketRef.current.onclose = (event) => {
      clearTimeout(socketTimeout);
      if (event.reason === "forced") {
        return;
      }
      restartTradeOffersWebSocket();
      socketRef.current = null;
    };
    socketRef.current.onerror = (e) => {
      clearTimeout(socketTimeout);
    };
    const pingSocket = () => {
      socketRef.current.send("ping");
      socketTimeout = setTimeout(pingSocket, 295000);
    };
  };

  useEffect(() => {
    if (isUsingGateway === null) return;
    blockedTradesList.current = JSON.parse(
      localStorage.getItem("failedTrades") || "[]"
    );
    if (!initiatedFetchPresence.current) {
      initiatedFetchPresence.current = true;
      initTradePresenceWebSocket();
    }
    getNewBlockedTrades();
    const intervalBlockTrades = setInterval(() => {
      initiatedFetchPresenceSocket.current = false;
      restartPresence();
      initTradePresenceWebSocket();
      getNewBlockedTrades();
    }, 150000);

    return () => {
      clearInterval(intervalBlockTrades);
    };
  }, [isUsingGateway]);

  const getSignedUnlockingFees = useCallback(async () => {
    try {
      const response = await fetch(
        `http://devnet-nodes.qortal.link:11112/crosschain/signedfees`
      );
      const data = await response.json();
      if (data && Array.isArray(data)) {
        setSignedUnlockingFees(data);
      }
    } catch (error) {
      console.error(error);
    }
  }, []);

  console.log("signed", signedUnlockingFees);

  useEffect(() => {
    getSignedUnlockingFees();
    intervalGetSignedUnlockingFees.current = setInterval(() => {
      getSignedUnlockingFees();
    }, 150000);
    return () => {
      if (intervalGetSignedUnlockingFees.current) {
        clearInterval(intervalGetSignedUnlockingFees.current);
      }
    };
  }, [getSignedUnlockingFees]);

  useEffect(() => {
    if (isUsingGateway === null) return;
    if (selectedCoin === null) return;
    restartTradeOffers();
    setTimeout(() => {
      initTradeOffersWebSocket();
    }, 500);
    return () => {
      if (socketRef.current) {
        socketRef.current.close(1000, "forced");
      }
    };
  }, [isUsingGateway, selectedCoin]);

  const selectedTotalLTC = useMemo(() => {
    const total = selectedOffers.reduce((acc: number, curr: any) => {
      return acc + (+curr.foreignAmount || 0); // Ensure qortAmount is defined
    }, 0);

    const totalWithKnownFees = +total + +knownFees;
    return totalWithKnownFees;
  }, [selectedOffers, knownFees]);

  const buyOrder = async () => {
    try {
      isRemoveOrdersWithoutUnlockingFees.current = false;
      if (+foreignCoinBalance < +selectedTotalLTC.toFixed(4)) {
        setOpen(true);
        setInfo({
          type: "error",
          message: `You don't have enough ${getCoinLabel()} or your balance was not retrieved`,
        });
        return;
      }

      if (selectedOffers?.length < 1) return;
      let offersWithKnownFees = [];
      const offersWithUnknownFees = [];

      selectedOffers.forEach((offer) => {
        const feeEntry = signedUnlockingFees.find(
          (item) => item?.atAddress === offer.qortalAtAddress
        );

        if (feeEntry && typeof feeEntry.fee === "number") {
          offersWithKnownFees.push({ ...offer, fee: feeEntry.fee });
        } else {
          offersWithUnknownFees.push(offer);
        }
      });
      console.log("offersWithKnownFees", offersWithKnownFees);
      console.log("offersWithUnknownFees", offersWithUnknownFees);
      if (offersWithUnknownFees?.length > 0) {
        await showTradesUnknownFee({
          message: "",
        });

        if (!isRemoveOrdersWithoutUnlockingFees.current) {
          offersWithKnownFees = [
            ...offersWithKnownFees,
            ...offersWithUnknownFees,
          ];
        }
      }

      console.log("offersWithKnownFees", offersWithKnownFees);

      setIsShowBuyInProgress({ status: "buying" });

      // setOpen(true)
      // setInfo({
      //   type: 'info',
      //   message: "Attempting to submit buy order. Please wait..."
      // })
      const listOfATs = offersWithKnownFees;
      const response = await qortalRequestWithTimeout(
        {
          action: "CREATE_TRADE_BUY_ORDER",
          crosschainAtInfo: listOfATs,
          foreignBlockchain: selectedCoin,
        },
        900000
      );

      if (response?.error) {
        setIsShowBuyInProgress({
          status: "error",
          message: response?.error || "Failed to submit trade order.",
        });
        //   setOpen(true)
        // setInfo({
        //   type: 'error',
        //   message: response?.error || "Failed to submit trade order."
        // })
        return;
      }
      if (response?.extra?.atAddresses) {
        setIsShowBuyInProgress({ status: "success" });
        setSelectedOffers([]);
        const transactionData = {
          qortalAtAddresses: response?.extra?.atAddresses,
          qortAddress: response?.extra?.senderAddress,
          node: response?.extra?.node,
          status: response?.extra?.status
            ? response?.extra?.status
            : response.callResponse === true
            ? "trade-ongoing"
            : "trade-failed",
          encryptedMessageToBase58: response?.encryptedMessageToBase58,
          chatSignature: response?.chatSignature,
          sender: response?.extra?.senderAddress,
          senderPublicKey: response?.extra?.senderPublicKey,
          reference: response?.callResponse?.reference,
        };

        // Update transactions in IndexedDB
        const result = await updateTransactionInDB(transactionData);
        setOpen(true);
        setInfo({
          type: "success",
          message: "Submitted Order",
        });
        fetchOngoingTransactions();
        if (isUsingGateway) {
          setRecord(transactionData);
          await showInfo({
            message: `Keep a record of your order in case your trade gets stuck`,
          });
        }
      }
    } catch (error) {
      setIsShowBuyInProgress({
        status: "error",
        message:
          error?.error || error?.message || "Failed to submit trade order.",
      });
      // setOpen(true)
      // setInfo({
      //   type: 'error',
      //   message: error?.error || error?.message || "Failed to submit trade order."
      // })
      // console.error(error)
    }
  };

  const getRowStyle = (
    params: RowClassParams<any, any>
  ): RowStyle | undefined => {
    if (listOfOngoingTradesAts.includes(params.data.qortalAtAddress)) {
      return { background: "#D9D9D91A" };
    }
    if (params.data.qortalAtAddress === selectedOffer?.qortalAtAddress) {
      return { background: "#6D94F533" };
    }

    const hasSignedFee = signedUnlockingFees?.find(
      (item) => item?.atAddress === params.data.qortalAtAddress
    );
    console.log("hasSignedFee", hasSignedFee);
    if (hasSignedFee) {
      console.log("fee2fee", fee);
      if (fee && hasSignedFee?.fee > fee) {
        return { backgroundColor: "#ff6347" };
      }
    }

    return undefined;
  };
  // const onGridReady = (params) => {
  //   const allColumnIds = params.columnApi.getAllColumns().map(col => col.getColId());
  //   params.columnApi.autoSizeColumns(allColumnIds, false);
  // };

  const onSelectionChanged = (event: any) => {
    const selectedRows = event.api.getSelectedRows();

    setSelectedOffers([...selectedRows]); // Set all selected rows
  };

  const onRowClicked = (event: any) => {
    if (listOfOngoingTradesAts.includes(event.data.qortalAtAddress)) return;
    const selectedRows = gridRef.current?.api.getSelectedRows();
    setSelectedOffers([...selectedRows]); // Always spread the array to ensure state updates correctly
  };

  const updateGridData = (newData: any) => {
    if (gridRef.current) {
      setOffers(newData);
    }
  };

  const getRowId = useCallback(function (params: any) {
    return String(params.data.qortalAtAddress);
  }, []);

  const selectedTotalQORT = useMemo(() => {
    const total = selectedOffers.reduce((acc: number, curr: any) => {
      return acc + (+curr.qortAmount || 0); // Ensure qortAmount is defined
    }, 0);
    return total;
  }, [selectedOffers]);

  const onGridReady = useCallback((params: any) => {
    params.api.sizeColumnsToFit(); // Adjust columns to fit the grid width
    const allColumnIds = params.columnApi
      .getAllColumns()
      .map((col: any) => col.getColId());
    params.columnApi.autoSizeColumns(allColumnIds); // Automatically adjust the width to fit content
  }, []);

  const handleClose = (
    event?: React.SyntheticEvent | Event,
    reason?: SnackbarCloseReason
  ) => {
    if (reason === "clickaway") {
      return;
    }

    setOpen(false);
    setInfo(null);
  };

  useEffect(() => {
    signedUnlockingFeesRef.current = signedUnlockingFees;
    feeRef.current = fee;

    if (gridRef.current?.api) {
      console.log("Total rows:", gridRef.current.api.getDisplayedRowCount());

      gridRef.current.api.forEachNode((rowNode: RowNode) => {
        const qortalAtAddress = rowNode.data?.qortalAtAddress;
        const hasSignedFee = signedUnlockingFeesRef.current?.find(
          (item) => item?.atAddress === qortalAtAddress
        );

        const isSelectable =
          !hasSignedFee || hasSignedFee.fee <= feeRef.current;

        rowNode.setRowSelectable(isSelectable); // ✅ apply logic per row
      });

      // Optional: refresh selection/checkbox visuals
      gridRef.current.api.refreshCells({ force: true });
    }
  }, [signedUnlockingFees, fee]);
  console.log("signedUnlockingFees", signedUnlockingFees, fee);
  if (!signedUnlockingFees || !fee) return null;

  return (
    <MainContainer>
      <div
        className="ag-theme-alpine-dark"
        style={{ height: 400, width: "100%" }}
      >
        <AgGridReact
          ref={gridRef}
          columnDefs={columnDefs}
          defaultColDef={defaultColDef}
          rowData={offersWithoutOngoing}
          onRowClicked={onRowClicked}
          onSelectionChanged={onSelectionChanged}
          getRowStyle={getRowStyle}
          autoSizeStrategy={autoSizeStrategy}
          rowSelection={selectedCoin === "PIRATECHAIN" ? "single" : "multiple"} // Enable multi-select
          rowMultiSelectWithClick={true}
          suppressHorizontalScroll={false} // Allow horizontal scroll on mobile if needed
          suppressCellFocus={true} // Prevents cells from stealing focus in mobile
          // pagination={true}
          // paginationPageSize={10}
          onGridReady={onGridReady}
          //  domLayout='autoHeight'
          getRowId={(params) => params.data.qortalAtAddress} // Ensure rows have unique IDs
          gridOptions={{
            isRowSelectable: (params) => {
              let selectable = true;
              const hasSignedFee = signedUnlockingFeesRef.current?.find(
                (item) => item?.atAddress === params.data.qortalAtAddress
              );
              if (!hasSignedFee) selectable = true;
              console.log(
                "fee",
                feeRef.current,
                signedUnlockingFeesRef.current
              );
              if (hasSignedFee && hasSignedFee?.fee > feeRef.current)
                selectable = false;
              return selectable;
            },
          }}
        />
        {/* {selectedOffer && (
        <Button onClick={buyOrder}>Buy</Button>

      )} */}
      </div>
      <div
        style={{
          height: "150px",
        }}
      />
      <BuyContainer>
        <BuyContainerDivider />
        <Box
          sx={{
            display: "flex",
            gap: "5px",
            flexDirection: "column",
            width: "100%",
          }}
        >
          <Typography
            sx={{
              fontSize: "16px",
              color: "white",
              width: "calc(100% - 75px)",
            }}
          >
            {selectedTotalQORT?.toFixed(8)} QORT
          </Typography>
          <Box
            sx={{
              display: "flex",
              gap: "20px",
              alignItems: "center",
              width: "calc(100% - 75px)",
            }}
          >
            <Typography
              sx={{
                fontSize: "16px",
                backgroundColor:
                  selectedTotalLTC > foreignCoinBalance ? "red" : "unset",
                color: "white",
              }}
            >
              <span>{selectedTotalLTC?.toFixed(8)}</span>{" "}
              <span
                style={{
                  marginLeft: "auto",
                }}
              >{`${getCoinLabel()} (with known fees)`}</span>
            </Typography>
          </Box>
          <Typography
            sx={{
              fontSize: "16px",
              color: "white",
            }}
          >
            <span>{foreignCoinBalance?.toFixed(8)}</span>{" "}
            <span
              style={{
                marginLeft: "auto",
              }}
            >
              {`${getCoinLabel()} `} balance
            </span>
          </Typography>
        </Box>
        {BuyButton()}
      </BuyContainer>
      <Snackbar
        anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
        open={open}
        onClose={handleClose}
      >
        <Alert
          onClose={handleClose}
          severity={info?.type}
          variant="filled"
          sx={{ width: "100%" }}
        >
          {info?.message}
        </Alert>
      </Snackbar>
      {isShowInfo && (
        <Dialog
          open={isShowInfo}
          aria-labelledby="alert-dialog-title"
          aria-describedby="alert-dialog-description"
        >
          <DialogTitle id="alert-dialog-title">{"Download record"}</DialogTitle>
          <DialogContent>
            <DialogContentText
              id="alert-dialog-description"
              sx={{
                color: "white",
              }}
            >
              {messageInfo.message}
            </DialogContentText>
            <Button
              onClick={async () => {
                try {
                  const fileName = "traderecord_" + Date.now() + "_" + ".json";
                  const dataString = JSON.stringify(record);
                  const blob = new Blob([dataString], {
                    type: "application/json",
                  });
                  await qortalRequest({
                    action: "SAVE_FILE",
                    filename: fileName,
                    blob,
                  });
                } catch (error) {}
              }}
            >
              Save Record
            </Button>
          </DialogContent>
          <DialogActions>
            <Button variant="contained" onClick={onOkInfo} autoFocus>
              Close
            </Button>
          </DialogActions>
        </Dialog>
      )}
      {isShowTradesUnknownFee && (
        <Dialog
          open={isShowTradesUnknownFee}
          aria-labelledby="alert-dialog-title"
          aria-describedby="alert-dialog-description"
        >
          <DialogTitle id="alert-dialog-title">Warning</DialogTitle>
          <DialogContent>
            <DialogContentText
              id="alert-dialog-description"
              sx={{ color: "white" }}
            >
              Some of your buy orders have unknown unlocking fees.
            </DialogContentText>
            <Spacer height="20px" />
            <DialogContentText
              id="alert-dialog-description"
              sx={{ color: "white" }}
            >
              You may proceed with your purchases without removing these orders,
              but there is a higher risk that the trades may not go through. In
              such cases, you will be refunded.
            </DialogContentText>

            <Spacer height="20px" />
            <FormControlLabel
              sx={{
                margin: 0,
              }}
              control={
                <Checkbox
                  onChange={(e) =>
                    (isRemoveOrdersWithoutUnlockingFees.current =
                      e.target.checked)
                  }
                  edge="start"
                  tabIndex={-1}
                  disableRipple
                  sx={{
                    "&.Mui-checked": {
                      color: "white",
                    },
                    "& .MuiSvgIcon-root": {
                      color: "white",
                    },
                  }}
                />
              }
              label={
                <Box sx={{ display: "flex", alignItems: "center" }}>
                  <Typography sx={{ fontSize: "14px" }}>
                    Remove orders with unknown unlocking fees
                  </Typography>
                </Box>
              }
            />
          </DialogContent>
          <DialogActions>
            <Button
              variant="contained"
              onClick={onCancelTradesUnknownFee}
              autoFocus
            >
              Close
            </Button>
            <Button
              variant="contained"
              onClick={onOkTradesUnknownFee}
              autoFocus
            >
              Continue
            </Button>
          </DialogActions>
        </Dialog>
      )}
      {isShowBuyInProgress && (
        <Dialog
          open={isShowBuyInProgress}
          aria-labelledby="alert-dialog-title"
          aria-describedby="alert-dialog-description"
          PaperProps={{
            style: {
              backgroundColor: "rgb(39, 40, 44)",
              background: "rgb(39, 40, 44)",
            },
          }}
        >
          <DialogContent
            sx={{
              width: "450px",
              height: "450px",
              maxHeight: "calc(90vh - 55px)",
              maxWidth: "90%",
              background: "rgb(39, 40, 44)",
              overflow: "auto",
            }}
          >
            {isShowBuyInProgress?.status === "error" && (
              <Box>
                <Typography>
                  <ErrorIcon
                    sx={{
                      color: "red",
                    }}
                  />
                  {` Failed to submit buy order.`}
                </Typography>
                <Spacer height="20px" />
                <Typography>{isShowBuyInProgress?.message}</Typography>
              </Box>
            )}
            {isShowBuyInProgress?.status === "success" && (
              <Box>
                <Typography>
                  <CheckCircleIcon
                    sx={{
                      color: "green",
                    }}
                  />
                  {` Successfully submitted order.`}
                </Typography>
                <Spacer height="20px" />
                <Typography>
                  You can see the progress of your order in the "Pending" table.
                </Typography>
                <Spacer height="20px" />
                <Typography>
                  Note: Submission of an order does not necessarily mean that
                  your submission will be the one completing the order. Another
                  account may have submitted it before you.
                </Typography>
              </Box>
            )}
            {isShowBuyInProgress?.status === "buying" && (
              <Box>
                <Typography>
                  <Hourglass
                    visible={true}
                    height="25"
                    width="25"
                    ariaLabel="hourglass-loading"
                    wrapperStyle={{}}
                    wrapperClass=""
                    colors={["#306cce", "#72a1ed"]}
                  />
                  {` Attempting to submit buy order`}
                </Typography>
                <Spacer height="20px" />
                <Typography>
                  Please do not leave this application until there is a
                  response. Please wait!
                </Typography>
                <Spacer height="20px" />
                {isUsingGateway && (
                  <>
                    <Typography>
                      Using gateway: might take up to 3 minutes to submit the
                      buy order.
                    </Typography>
                    <Spacer height="20px" />
                    <Box
                      sx={{
                        width: "100%",
                        display: "flex",
                        justifyContent: "center",
                      }}
                    >
                      <CountdownCircleTimer
                        isPlaying
                        duration={180}
                        colors={["#004777", "#F7B801", "#A30000", "#A30000"]}
                        colorsTime={[7, 5, 2, 0]}
                        onComplete={() => {
                          //nothing
                        }}
                        size={60}
                        strokeWidth={4}
                      >
                        {({ remainingTime }) => (
                          <Typography>{remainingTime}</Typography>
                        )}
                      </CountdownCircleTimer>
                    </Box>
                  </>
                )}
              </Box>
            )}
          </DialogContent>
          <DialogActions
            sx={{
              background: "rgb(39, 40, 44)",
            }}
          >
            <Button
              disabled={isShowBuyInProgress?.status === "buying"}
              variant="outlined"
              onClick={() => {
                setIsShowBuyInProgress(null);
              }}
              autoFocus
            >
              Close
            </Button>
          </DialogActions>
        </Dialog>
      )}
      <Dialog
        open={!!openShowOfferDetails}
        aria-labelledby="alert-dialog-title"
        aria-describedby="alert-dialog-description"
        PaperProps={{
          style: {
            backgroundColor: "rgb(39, 40, 44)",
            background: "rgb(39, 40, 44)",
          },
        }}
      >
        <DialogTitle
          sx={{
            maxHeight: "calc(90vh - 55px)",
            maxWidth: "90%",
            background: "rgb(39, 40, 44)",
            overflow: "auto",
          }}
        >
          <Typography variant="subtitle1">
            Buy {openShowOfferDetails?.qortAmount} QORT @{" "}
            {openShowOfferDetails?.foreignAmount} {getCoinLabel()}
          </Typography>
        </DialogTitle>
        <IconButton
          aria-label="close"
          onClick={() => setOpenShowOfferDetails(null)}
          sx={{ position: "absolute", right: 8, top: 8, color: "#fff" }}
        >
          <CloseIcon />
        </IconButton>
        <DialogContent dividers sx={{ borderColor: "#333" }}>
          {fee &&
            openShowOfferDetails?.fee &&
            +fee < +openShowOfferDetails?.fee && (
              <Box
                sx={{
                  background: "red",
                  padding: "10px",
                  borderRadius: "5px",
                }}
              >
                <Typography sx={{ color: "white" }}>
                  The unlocking fee on this node is lower than the amount
                  required for this order.
                </Typography>
                <Spacer height="10px" />
                <Typography sx={{ color: "white" }}>
                  If you're using your own node, you can change the fee by
                  clicking the "Fee" button next to the coin selector.
                </Typography>
              </Box>
            )}
          <TradeRow
            enableSlice
            enableCopy
            label="Seller"
            value={openShowOfferDetails?.qortalCreator}
            extra={qortalNames[openShowOfferDetails?.qortalCreator]}
          />
          <TradeRow
            label="Amount"
            value={`${openShowOfferDetails?.qortAmount} QORT`}
          />
          <TradeRow
            label="Total"
            value={`${openShowOfferDetails?.foreignAmount} ${getCoinLabel()}`}
          />
          <TradeRow
            label="Price"
            value={`${
              +openShowOfferDetails?.foreignAmount /
              +openShowOfferDetails?.qortAmount
            } ${getCoinLabel()}/QORT`}
          />
          {openShowOfferDetails?.fee && (
            <TradeRow
              label="Unlocking fee"
              value={`${openShowOfferDetails?.fee} sats`}
            />
          )}

          <TradeRow
            enableSlice
            enableCopy
            label="AT Address"
            value={openShowOfferDetails?.qortalAtAddress}
          />
        </DialogContent>
        <DialogActions
          sx={{
            background: "rgb(39, 40, 44)",
          }}
        >
          <Button
            variant="outlined"
            onClick={() => {
              setOpenShowOfferDetails(null);
            }}
            autoFocus
          >
            Close
          </Button>
        </DialogActions>
      </Dialog>
    </MainContainer>
  );
};

const TradeRow = ({
  label,
  value,
  extra,
  enableSlice,
  enableCopy,
}: {
  label: string;
  value: string;
  extra?: string;
  enableSlice?: boolean;
  enableCopy?: boolean;
}) => (
  <Box
    sx={{
      display: "flex",
      flexDirection: "column",
      mb: 2,
    }}
  >
    <Typography variant="caption" color="gray">
      {label}
    </Typography>

    <Box
      sx={{
        display: "flex",
        alignItems: "center",
        gap: 1,
        flexWrap: "wrap",
      }}
    >
      <Typography variant="body2" sx={{ fontWeight: 500 }}>
        {enableSlice && value?.length > 18
          ? value?.slice(0, 6) + "..." + value.slice(-4)
          : value}
      </Typography>
      {enableCopy && (
        <Tooltip title="Copy">
          <IconButton size="small" onClick={() => copyToClipboard(value)}>
            <ContentCopyIcon fontSize="small" />
          </IconButton>
        </Tooltip>
      )}
      {extra && (
        <Typography variant="body2" color="gray">
          {extra}
        </Typography>
      )}
    </Box>
  </Box>
);

const SelectWithInfoCell = ({ selectTradeForDetails }) => {
  const handleInfoClick = (e: React.MouseEvent) => {
    e.stopPropagation(); // Prevents row selection
    selectTradeForDetails();
    // alert(`Info for ${data.qortalAtAddress}`); // Replace with your own UI
  };

  return (
    <div
      className="ag-cell-ignore-selection"
      style={{ display: "flex", alignItems: "center", gap: 6 }}
    >
      <IconButton
        size="small"
        onClick={handleInfoClick}
        onClickCapture={(e) => {
          e.stopPropagation();
          handleInfoClick(e);
        }}
        onMouseDown={(e) => e.stopPropagation()} // 👈 this is key
        sx={{ minWidth: 0, padding: "0 4px" }}
      >
        <InfoOutlineIcon />
      </IconButton>
    </div>
  );
};
