import React, {
  useMemo,
  useState,
  useEffect,
  useRef,
  useCallback,
} from "react";
import {
  BrowserProvider,
  Contract,
  MaxUint256,
  formatUnits,
  parseUnits,
} from "ethers";
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title as ChartTitle,
  Tooltip as ChartTooltip,
  Legend as ChartLegend,
  Filler,
} from "chart.js";
import type { ChartOptions } from "chart.js";
import { Line } from "react-chartjs-2";
import {
  GOLD_ORDERBOOK_ADDRESS,
  GOLD_MARKETPLACE_ADDRESS,
  OREDERBOOK_ABI_KEY,
  MARKETPLACE_ABI_KEY,
  ERC20_ABI_KEY,
  FUTURE_TOKEN_ABI_APPROVE,
  GOLD_RGOLD_TOKEN_ADDRESS,
  GOLD_RGOLD_ABI,
} from "../../../const";
import {
  Box,
  Card,
  CardContent,
  CardHeader,
  Typography,
  Tabs,
  Tab,
  TextField,
  Button,
  Snackbar,
  Alert,
  Divider,
  Chip,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  IconButton,
  Tooltip,
  LinearProgress,
  Paper,
  Table,
  TableHead,
  TableBody,
  TableRow,
  TableCell,
  Stepper,
  Step,
  StepLabel,
  Skeleton,
  InputAdornment,
} from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";
import ShoppingCartOutlined from "@mui/icons-material/ShoppingCartOutlined";
import AssignmentTurnedInOutlined from "@mui/icons-material/AssignmentTurnedInOutlined";
import StorefrontOutlined from "@mui/icons-material/StorefrontOutlined";
import AddCircleOutline from "@mui/icons-material/AddCircleOutline";
import TrendingUp from "@mui/icons-material/TrendingUp";
import InfoOutlined from "@mui/icons-material/InfoOutlined";
import {
  Logout as LogoutIcon,
  ExpandMore as ExpandMoreIcon,
} from "@mui/icons-material";

type Commodity = { key: string; label: string };

type Series = {
  id: number;
  commodity: string;
  deliveryMonth: string;
  remaining: string;
};

type PayToken = { address: string; symbol: string; decimals: number };

type OrderRow = {
  seriesId: number;
  commodity: string;
  token: string;
  amount: string; // quantity (oz)
  delivery: string; // delivery date
  subDate: string; // subscription date
  apr: string; // e.g., 5.25%
  tx?: string;
};

type Listing = {
  id: number;
  token: string;
  seller: string;
  amount: string;
  price: string;
  currency: string;
};

// Helpers
const fmt = (n: string | number) =>
  new Intl.NumberFormat(undefined, { maximumFractionDigits: 6 }).format(
    Number(n)
  );
const shortAddr = (a?: string | null) =>
  a ? `${a.slice(0, 6)}...${a.slice(-4)}` : "—";

// ChartJS registration
ChartJS.register(
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  ChartTitle,
  ChartTooltip,
  ChartLegend,
  Filler
);

export default function OrderBookGold() {
  // Config & addresses
  const ORDERBOOK_ADDR = GOLD_ORDERBOOK_ADDRESS;
  const MARKETPLACE_ADDR = GOLD_MARKETPLACE_ADDRESS;
  const ORDERBOOK_ABI = OREDERBOOK_ABI_KEY;
  const MARKETPLACE_ABI = MARKETPLACE_ABI_KEY;
  const ERC20_ABI = ERC20_ABI_KEY;
  const FUTURE_TOKEN_ABI = FUTURE_TOKEN_ABI_APPROVE;
  const ARBITRUM_CHAIN_ID = 42161;

  // App state
  const [wallet, setWallet] = useState<string | null>(null);
  const [isAdmin, setIsAdmin] = useState(false);
  const [status, setStatus] = useState<{
    message: string;
    kind: "info" | "success" | "error";
  }>({ message: "Ready.", kind: "info" });
  const statusTimer = useRef<number | null>(null);
  const [provider, setProvider] = useState<BrowserProvider | null>(null);
  const [signer, setSigner] = useState<any>(null);
  const [orderBook, setOrderBook] = useState<any>(null);
  const [marketplace, setMarketplace] = useState<any>(null);

  const [tab, setTab] = useState(0);

  // Spot / Projection
  const [apr, setApr] = useState<number>(5.25);
  const [startMonth, setStartMonth] = useState<string>("2025-09");
  const [spot, setSpot] = useState<string>("—");

  // Subscribe
  const [seriesList, setSeriesList] = useState<Series[]>([]);
  const [loadingSeries, setLoadingSeries] = useState(false);
  const [seriesId, setSeriesId] = useState<number | "">("");
  const [amount, setAmount] = useState<string>("");
  const [payToken, setPayToken] = useState<string>("IUSD");
  const [supportedPayTokens, setSupportedPayTokens] = useState<PayToken[]>([]);
  const [fullName, setFullName] = useState("");
  const [companyName, setCompanyName] = useState("");
  const [seriesStrike, setSeriesStrike] = useState<string>("–");
  const [seriesStrikeVal, setSeriesStrikeVal] = useState<number | null>(null);
  const [seriesStrikeRaw, setSeriesStrikeRaw] = useState<bigint | null>(null);
  const [seriesRemaining, setSeriesRemaining] = useState<string>("–");

  // Orders
  const [orders, setOrders] = useState<OrderRow[]>([]);
  const [loadingOrders, setLoadingOrders] = useState(false);

  // Marketplace
  const [listings, setListings] = useState<Listing[]>([]);
  const [listQty, setListQty] = useState("");
  const [listPrice, setListPrice] = useState("");
  const [listCurrency, setListCurrency] = useState("USDT");
  const [ownedTokens, setOwnedTokens] = useState<
    Array<{ token: string; seriesId: number }>
  >([]);
  const [ownedTokensStatus, setOwnedTokensStatus] = useState<
    "idle" | "loading" | "ready" | "error"
  >("idle");
  const [selectedOwnedToken, setSelectedOwnedToken] = useState<string>("");
  // Marketplace simple view (HTML parity): no search/sort controls

  // Admin: Create Series
  const [newSeriesDateTime, setNewSeriesDateTime] = useState("");
  const [newSeriesSupply, setNewSeriesSupply] = useState("");
  const [newSeriesCommodity, setNewSeriesCommodity] = useState("GOLD");
  const [newSeriesRatePct, setNewSeriesRatePct] = useState("");
  const [newSeriesName, setNewSeriesName] = useState("");
  const [newSeriesSymbol, setNewSeriesSymbol] = useState("");
  const [creatingSeries, setCreatingSeries] = useState(false);
  // Operation guard to avoid stale toasts after user cancels one attempt then succeeds on next
  const lastOpRef = useRef<number>(0);
  const isUserRejected = useCallback((e: any) => {
    const code = String(e?.code ?? "").toLowerCase();
    const msg = String(e?.message ?? e?.reason ?? "").toLowerCase();
    return (
      code === "4001" ||
      code.includes("action_rejected") ||
      /user (denied|rejected)/i.test(msg)
    );
  }, []);
  // Prefer nested RPC data.message when present
  const getRpcMessage = useCallback((e: any) => {
    try {
      // Prefer the provider nested message (what console shows)
      const candidates: Array<string | undefined> = [
        e?.data?.message, // ethers v6 / provider
        e?.error?.data?.message, // MetaMask nested
        e?.info?.error?.data?.message, // other wrappers
        e?.cause?.data?.message, // CALL_EXCEPTION cause
        e?.error?.message,
        e?.info?.error?.message,
        e?.reason,
        e?.shortMessage,
        e?.message,
      ];

      // Try to extract JSON-encoded message from stack/body blobs
      const blobs = [
        e?.stack,
        e?.error?.stack,
        e?.info?.stack,
        e?.body,
        e?.error?.body,
      ].filter(Boolean);
      for (const b of blobs) {
        if (typeof b === "string") {
          const m = b.match(/"message"\s*:\s*"([^"]+)"/);
          if (m && m[1]) candidates.unshift(m[1]);
        }
      }

      // Pick first non-empty
      const picked = candidates.find((m) => typeof m === "string" && m.trim());
      let msg = picked || "Transaction failed";

      // If any candidate contains "execution reverted", prefer that exact phrase
      const hay = candidates.join(" ").toLowerCase();
      if (hay.includes("execution reverted")) msg = "execution reverted";

      // Avoid ethers' noisy wrapper showing up in UI
      if (/missing revert data/i.test(msg)) {
        // Force the concise revert reason expected by UI
        msg = "execution reverted";
      }

      return msg;
    } catch {
      return "Transaction failed";
    }
  }, []);
  // Prefer the exact JSON-RPC nested message, fall back lightly.
  const rpcDataMessage = (e: any): string => {
    const msg =
      e?.data?.message ??
      e?.error?.data?.message ??
      e?.info?.error?.data?.message ??
      null;

    if (msg) return String(msg).trim();

    // Last-ditch: try to pull "message":"..." from a stack/body blob
    for (const s of [e?.stack, e?.error?.stack, e?.body, e?.error?.body]) {
      if (typeof s === "string") {
        const m = s.match(/"message"\s*:\s*"([^"]+)"/);
        if (m?.[1]) return m[1].trim();
      }
    }

    return "Transaction failed";
  };

  // Minimal snackbar mapping: show only provider message (data.message) when present
  const notifyError = useCallback((e: any, fallback: string) => {
    const m = rpcDataMessage(e) || fallback;
    notify(m, "error");
  }, []);

  // Snackbar
  const [snack, setSnack] = useState<{
    open: boolean;
    kind: "success" | "error" | "info";
    msg: string;
  }>({ open: false, kind: "info", msg: "" });
  const normalizeSnackMsg = (
    input: any,
    kind: "success" | "error" | "info"
  ) => {
    try {
      if (kind !== "error")
        return typeof input === "string" ? input : String(input ?? "");
      // For errors, prefer nested provider message and force concise text
      const pick = (...xs: Array<any>) =>
        xs.find((m) => typeof m === "string" && m.trim());
      let msg = "";
      if (typeof input === "string") {
        msg = input.trim();
      } else {
        msg =
          pick(
            input?.data?.message,
            input?.error?.data?.message,
            input?.info?.error?.data?.message,
            input?.cause?.data?.message,
            input?.error?.message,
            input?.info?.error?.message,
            input?.reason,
            input?.shortMessage,
            input?.message
          ) || "";
        const blobs = [
          input?.stack,
          input?.error?.stack,
          input?.info?.stack,
          input?.body,
          input?.error?.body,
        ].filter(Boolean);
        for (const b of blobs) {
          if (typeof b === "string") {
            const m = b.match(/"message"\s*:\s*"([^"]+)"/);
            if (m && m[1]) {
              msg = m[1];
              break;
            }
          }
        }
      }
      const hay = `${msg} ${
        typeof input?.stack === "string" ? input.stack : ""
      }`.toLowerCase();
      if (hay.includes("execution reverted")) return "execution reverted";
      if (/missing revert data/i.test(msg)) return "execution reverted";
      return msg || "Transaction failed";
    } catch {
      return typeof input === "string" ? input : "Transaction failed";
    }
  };
  const notify = (msg: any, kind: "success" | "error" | "info" = "info") =>
    setSnack({ open: true, kind, msg: normalizeSnackMsg(msg, kind) });
  const formatError = (err: any): string => {
    try {
      const msg =
        err?.reason ||
        err?.data?.message ||
        err?.error?.message ||
        err?.info?.error?.message ||
        err?.shortMessage ||
        err?.message ||
        String(err ?? "");
      const lower = String(msg).toLowerCase();
      if (
        err?.code === 4001 ||
        String(err?.code ?? "").toLowerCase() === "action_rejected" ||
        lower.includes("user denied transaction") ||
        lower.includes("user rejected") ||
        lower.includes("transaction was rejected")
      )
        return "Transaction failed: rejected";
      return String(msg)
        .replace("ethers-user-denied:", "")
        .replace("MetaMask Tx Signature:", "")
        .replace("execution reverted:", "")
        .trim();
    } catch {
      return "Transaction failed";
    }
  };
  const updateStatus = (
    message: string,
    kind: "info" | "success" | "error" = "info",
    duration = 4000
  ) => {
    setStatus({ message, kind });
    if (statusTimer.current) window.clearTimeout(statusTimer.current);
    if (duration)
      statusTimer.current = window.setTimeout(
        () => setStatus({ message: "Ready.", kind: "info" }),
        duration
      );
  };
  useEffect(
    () => () => {
      if (statusTimer.current) window.clearTimeout(statusTimer.current);
    },
    []
  );

  // Bootstrap
  useEffect(() => {
    setWallet(null);
    setIsAdmin(false);
    setSpot("—");
  }, []);

  // Fetch spot (RGOLD) — resilient to ABI differences
  const fetchSpot = useCallback(async () => {
    try {
      const prov =
        provider ??
        (typeof (window as any).ethereum !== "undefined"
          ? new BrowserProvider((window as any).ethereum, "any")
          : null);
      if (!prov) return;
      const rgold = new Contract(
        GOLD_RGOLD_TOKEN_ADDRESS,
        GOLD_RGOLD_ABI as any,
        (await prov.getSigner?.()) ?? prov
      );
      if ((rgold as any).getLatestPriceInUSD) {
        const p = await (rgold as any).getLatestPriceInUSD();
        setSpot(Number(formatUnits(p, 18)).toFixed(2));
        return;
      }
      if ((rgold as any).getLatestGoldPrice) {
        const [p, dec] = await (rgold as any).getLatestGoldPrice();
        setSpot(Number(formatUnits(p, Number(dec))).toFixed(2));
        return;
      }
      if ((rgold as any).price) {
        const p = await (rgold as any).price();
        setSpot(Number(formatUnits(p, 18)).toFixed(2));
        return;
      }
      if ((rgold as any).getLatestPrice) {
        const p = await (rgold as any).getLatestPrice();
        const guess = typeof p === "bigint" || typeof p === "number" ? 8 : 18;
        setSpot(Number(formatUnits(p as any, guess)).toFixed(2));
        return;
      }
    } catch {}
  }, [provider]);
  useEffect(() => {
    fetchSpot();
  }, [fetchSpot]);

  // Load supported payment tokens from the OrderBook (parity with HTML)
  useEffect(() => {
    const loadSupported = async () => {
      try {
        if (!orderBook) return;
        const candidates: PayToken[] = [
          {
            address: "0xFEF7D9E974713E56Be167C8685e253DE5ec9c8d0",
            symbol: "IUSD",
            decimals: 18,
          },
          {
            address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
            symbol: "USDC",
            decimals: 6,
          },
          {
            address: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
            symbol: "USDT",
            decimals: 6,
          },
        ];
        const out: PayToken[] = [];
        for (const t of candidates) {
          try {
            const ok = await (orderBook as any).isPaymentTokenSupported?.(
              t.address
            );
            if (ok) out.push(t);
          } catch {}
        }
        setSupportedPayTokens(out);
        if (out.length && !out.find((t) => t.symbol === payToken))
          setPayToken(out[0].symbol);
      } catch {}
    };
    loadSupported();
  }, [orderBook]);

  // Marketplace listings loader (to mirror HTML marketplace table)
  const loadListings = useCallback(async () => {
    if (!marketplace) return;
    try {
      const out: Listing[] = [];
      const nextId: bigint = await (marketplace as any).nextListingId?.();
      const last = Number(nextId ?? 0);
      for (let i = 1; i < last; i++) {
        try {
          const l = await (marketplace as any).listings?.(i);
          if (!l) continue;
          const active = Boolean(l.active ?? l[6]);
          if (!active) continue;
          const id = i;
          const seller = String(l.seller ?? l[0] ?? "");
          const token = String(l.seriesToken ?? l[1] ?? "");
          const amount = Number(
            formatUnits(l.amount ?? l[3] ?? BigInt(0), 18)
          ).toFixed(4);
          const priceNum = Number(
            formatUnits(l.pricePerToken ?? l[4] ?? BigInt(0), 18)
          ).toFixed(4);
          const currencyAddr = String(
            l.currencyForSale ?? l[5] ?? ""
          ).toLowerCase();
          const currency =
            (
              {
                ["0xfef7d9e974713e56be167c8685e253de5ec9c8d0".toLowerCase()]:
                  "IUSD",
                ["0xaf88d065e77c8cc2239327c5edb3a432268e5831".toLowerCase()]:
                  "USDC",
                ["0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9".toLowerCase()]:
                  "USDT",
              } as Record<string, string>
            )[currencyAddr] || currencyAddr;
          out.push({ id, token, seller, amount, price: priceNum, currency });
        } catch {}
      }
      setListings(out);
    } catch (e: any) {
      notify(getRpcMessage(e) || "Failed to load listings", "error");
    }
  }, [marketplace]);

  useEffect(() => {
    if (tab === 2) loadListings();
  }, [tab, loadListings]);

  // Load owned series tokens for the connected wallet (parity with HTML's listTokenSelect)
  const loadOwnedTokens = useCallback(async () => {
    if (!orderBook || !provider || !wallet) return;
    try {
      setOwnedTokensStatus("loading");
      const filter =
        (orderBook as any).filters?.Subscribed?.(null, wallet) ?? null;
      const logs =
        filter && (orderBook as any).queryFilter
          ? await (orderBook as any).queryFilter(filter)
          : [];
      const uniq = new Map<string, number>();
      for (const e of logs ?? []) {
        try {
          const args: any = (e as any).args ?? {};
          const sid = Number(args.seriesId ?? args[0] ?? 0);
          if (!sid) continue;
          const sInfo = await ((orderBook as any).series?.(sid) ??
            (orderBook as any).seriesInfo?.(sid) ??
            (orderBook as any).getSeries?.(sid));
          const tokenAddr = String(sInfo?.seriesToken ?? sInfo?.[2] ?? "");
          if (tokenAddr && !uniq.has(tokenAddr.toLowerCase()))
            uniq.set(tokenAddr.toLowerCase(), sid);
        } catch {}
      }
      const arr = Array.from(uniq.entries()).map(([token, sid]) => ({
        token,
        seriesId: sid,
      }));
      setOwnedTokens(arr);
      if (!selectedOwnedToken && arr.length)
        setSelectedOwnedToken(arr[0].token);
      setOwnedTokensStatus("ready");
    } catch (e: any) {
      /* silent */
    } finally {
      if (ownedTokensStatus !== "ready") setOwnedTokensStatus("error");
    }
  }, [orderBook, provider, wallet, selectedOwnedToken]);

  useEffect(() => {
    if (tab === 2) loadOwnedTokens();
  }, [tab, loadOwnedTokens]);

  // Projection
  const projection = useMemo(() => {
    const months = 12;
    const rate = apr / 100;
    const out: { m: number; v: number }[] = [];
    const base = Number.isFinite(Number(spot)) ? Number(spot) : 3500;
    let val = base;
    const monthly = 1 + rate / 12;
    for (let i = 0; i < months; i++) {
      val = i ? val * monthly : val;
      out.push({ m: i + 1, v: val });
    }
    return out;
  }, [apr, spot]);

  const projectionLabels = useMemo(() => {
    try {
      const [y, m] = startMonth.split("-").map(Number);
      if (!y || !m) throw 0;
      const base = new Date(y, m - 1, 1);
      const labels: string[] = [];
      for (let i = 0; i < 12; i++) {
        const d = new Date(base);
        d.setMonth(base.getMonth() + i);
        labels.push(
          d.toLocaleString(undefined, { month: "short", year: "numeric" })
        );
      }
      return labels;
    } catch {
      return projection.map((p) => `M${p.m}`);
    }
  }, [startMonth, projection]);

  const projectionData = useMemo(
    () => ({
      labels: projectionLabels,
      datasets: [
        {
          label: "Projected Price (USD/Oz)",
          data: projection.map((p) => Number(p.v.toFixed(2))),
          borderColor: "#0f172a",
          backgroundColor: "rgba(15, 23, 42, 0.08)",
          fill: true,
          tension: 0.05,
          borderWidth: 2,
          pointRadius: 2.5,
          pointBackgroundColor: "#fff",
          pointBorderColor: "#0f172a",
          pointBorderWidth: 1.5,
        },
      ],
    }),
    [projection, projectionLabels]
  );

  const projectionOptions: ChartOptions<"line"> = useMemo(() => {
    const vals = projection.map((p) => p.v);
    const minV = Math.min(...vals);
    const maxV = Math.max(...vals);
    const step = 20;
    const suggestedMin = Math.floor(minV / step) * step;
    const suggestedMax = Math.ceil(maxV / step) * step + step;
    return {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: { display: false },
        title: { display: false },
        tooltip: { mode: "index", intersect: false },
      },
      interaction: { mode: "index", intersect: false },
      scales: {
        x: {
          grid: { display: false },
          ticks: { maxRotation: 35, minRotation: 35, font: { size: 11 } },
          title: { display: true, text: "Date" },
        },
        y: {
          grid: { color: "rgba(0,0,0,0.06)" },
          ticks: { stepSize: step, font: { size: 11 } },
          title: { display: true, text: "Projected Price (USD/Oz)" },
          suggestedMin,
          suggestedMax,
        },
      },
    };
  }, [projection]);

  // Connect / Disconnect
  const onConnect = async () => {
    try {
      if (typeof (window as any).ethereum === "undefined") {
        notify("Please install MetaMask.", "error");
        updateStatus("MetaMask not detected.", "error");
        return;
      }
      const prov = new BrowserProvider((window as any).ethereum, "any");
      try {
        await prov.send("eth_requestAccounts", []);
      } catch (e: any) {
        // If a request is already pending in MetaMask
        if (String(e?.code) === "-32002") {
          updateStatus(
            "MetaMask request already pending. Please open MetaMask.",
            "info"
          );
          return;
        }
        throw e;
      }
      const net = await prov.getNetwork();
      if (Number(net.chainId) !== ARBITRUM_CHAIN_ID) {
        try {
          await (window as any).ethereum.request({
            method: "wallet_switchEthereumChain",
            params: [{ chainId: "0xA4B1" }],
          });
        } catch (e: any) {
          updateStatus("Please switch to Arbitrum One in MetaMask.", "error");
          notify("Wrong network: switch to Arbitrum One.", "error");
          return;
        }
      }
      const s = await prov.getSigner();
      const addr = await s.getAddress();
      setProvider(prov);
      setSigner(s);
      const ob = new Contract(ORDERBOOK_ADDR, ORDERBOOK_ABI as any, s);
      const mp = new Contract(MARKETPLACE_ADDR, MARKETPLACE_ABI as any, s);
      setOrderBook(ob);
      setMarketplace(mp);
      try {
        const adminRole = await (ob as any).ADMIN_ROLE?.();
        if (adminRole) {
          const has = await (ob as any).hasRole?.(adminRole, addr);
          if (typeof has === "boolean") setIsAdmin(has);
        }
      } catch {}
      try {
        await loadSeriesList();
      } catch {}
      setWallet(addr);
      updateStatus("Connected.", "success");
      notify("Wallet connected.", "success");
    } catch (e: any) {
      const msg = e?.message || "Failed to connect wallet";
      notify(msg, "error");
      updateStatus(msg, "error");
    }
  };

  const onDisconnect = () => {
    setWallet(null);
    setProvider(null);
    setSigner(null);
    setOrderBook(null);
    setMarketplace(null);
    updateStatus("Disconnected.", "info");
    notify("Disconnected.", "info");
  };

  useEffect(() => {
    const eth = (window as any).ethereum;
    if (!eth) return;
    const onAccounts = (accs: string[]) => setWallet(accs?.[0] || null);
    const onChain = () => setWallet(null);
    eth.on?.("accountsChanged", onAccounts);
    eth.on?.("chainChanged", onChain);
    return () => {
      eth?.removeListener?.("accountsChanged", onAccounts);
      eth?.removeListener?.("chainChanged", onChain);
    };
  }, []);

  // Refresh orders when switching to the Orders tab (parity with HTML which loads on tab click)
  useEffect(() => {
    if (tab === 1) {
      try {
        onRefreshOrders();
      } catch {}
    }
  }, [tab]);

  // Series list & detail
  const loadSeriesList = useCallback(async () => {
    if (!orderBook) return;
    setLoadingSeries(true);
    const list: Series[] = [];
    try {
      try {
        const nextId: bigint | undefined = await orderBook.nextSeriesId?.();
        if (nextId && Number(nextId) > 1) {
          for (let i = 1; i < Number(nextId); i++) {
            try {
              const info = await ((orderBook as any).series?.(i) ??
                (orderBook as any).seriesInfo?.(i) ??
                (orderBook as any).getSeries?.(i));
              const deliveryTs =
                Number((info?.deliveryTimestamp ?? info?.[3] ?? 0) as any) *
                1000;
              const month = deliveryTs
                ? new Date(deliveryTs).toISOString().slice(0, 7)
                : "";
              list.push({
                id: i,
                commodity: "Gold",
                deliveryMonth: month,
                remaining: "",
              });
            } catch {}
          }
        }
      } catch {}
      if (list.length === 0) {
        try {
          const count: bigint | undefined = await orderBook.seriesCount?.();
          if (count && Number(count) > 0) {
            for (let i = 1; i <= Number(count); i++) {
              try {
                const info = await ((orderBook as any).series?.(i) ??
                  (orderBook as any).seriesInfo?.(i) ??
                  (orderBook as any).getSeries?.(i));
                const deliveryTs =
                  Number((info?.deliveryTimestamp ?? info?.[3] ?? 0) as any) *
                  1000;
                const month = deliveryTs
                  ? new Date(deliveryTs).toISOString().slice(0, 7)
                  : "";
                list.push({
                  id: i,
                  commodity: "Gold",
                  deliveryMonth: month,
                  remaining: "",
                });
              } catch {}
            }
          }
        } catch {}
      }
      if (
        list.length === 0 &&
        (orderBook as any).filters?.SeriesCreated &&
        (orderBook as any).queryFilter
      ) {
        try {
          const ev = (orderBook as any).filters.SeriesCreated();
          const logs = await (orderBook as any).queryFilter(ev);
          const seen = new Set<number>();
          for (const e of logs) {
            const id = Number(
              (e as any)?.args?.seriesId ?? (e as any)?.args?.[0] ?? 0
            );
            if (!id || seen.has(id)) continue;
            seen.add(id);
            list.push({
              id,
              commodity: "Gold",
              deliveryMonth: "",
              remaining: "",
            });
          }
        } catch {}
      }
    } finally {
      setSeriesList(list);
      setLoadingSeries(false);
    }
  }, [orderBook]);

  const loadSeriesDetail = useCallback(
    async (id: number) => {
      if (!orderBook || !id) {
        setSeriesStrike("–");
        setSeriesStrikeVal(null);
        setSeriesStrikeRaw(null);
        setSeriesRemaining("–");
        return;
      }
      try {
        const info = await ((orderBook as any).series?.(id) ??
          (orderBook as any).seriesInfo?.(id) ??
          (orderBook as any).getSeries?.(id));
        if (!info) {
          setSeriesStrike("–");
          setSeriesRemaining("–");
          return;
        }
        const strike = (info.strikePrice ??
          info[5] ??
          info[6] ??
          BigInt(0)) as bigint;
        const totalAmt = (info.totalAmount ?? info[6] ?? BigInt(0)) as bigint;
        const soldAmt = (info.amountSold ?? info[1] ?? BigInt(0)) as bigint;
        const rem = (info.remainingAmount ??
          info[7] ??
          (totalAmt as bigint) - (soldAmt as bigint)) as bigint;
        setSeriesStrikeRaw(strike);
        const strikeNum = Number(formatUnits(strike, 18));
        setSeriesStrike(`${strikeNum.toFixed(4)} USD/Ounce`);
        setSeriesStrikeVal(Number.isFinite(strikeNum) ? strikeNum : null);
        const remNum = Number(formatUnits(rem, 18));
        setSeriesRemaining(`${remNum.toFixed(4)} Ounce`);
      } catch {
        setSeriesStrike("–");
        setSeriesStrikeVal(null);
        setSeriesStrikeRaw(null);
        setSeriesRemaining("–");
      }
    },
    [orderBook]
  );
  useEffect(() => {
    loadSeriesList();
  }, [loadSeriesList]);
  useEffect(() => {
    if (wallet && !seriesId && seriesList.length > 0) {
      setSeriesId(seriesList[0].id);
    }
  }, [wallet, seriesId, seriesList]);
  useEffect(() => {
    if (typeof seriesId === "number") loadSeriesDetail(seriesId);
  }, [seriesId, loadSeriesDetail]);

  // Orders
  const onRefreshOrders = async () => {
    if (!wallet || !orderBook || !provider) return;
    setLoadingOrders(true);
    try {
      const filter =
        (orderBook as any).filters?.Subscribed?.(null, wallet) ?? null;
      // Explicitly query from genesis to latest to avoid node default range limits
      const logs =
        filter && (orderBook as any).queryFilter
          ? await (orderBook as any).queryFilter(filter, 0, "latest")
          : [];
      const rows: OrderRow[] = [];
      for (const e of logs ?? []) {
        try {
          const args: any = (e as any).args ?? {};
          const sid = Number(args.seriesId ?? args[0] ?? 0);
          const amt = args.amountSubscribed ?? args[1] ?? BigInt(0);
          const bnum = Number((e as any).blockNumber ?? 0);
          const block = bnum ? await provider.getBlock(bnum) : null;
          const sInfo = await ((orderBook as any).series?.(sid) ??
            (orderBook as any).seriesInfo?.(sid) ??
            (orderBook as any).getSeries?.(sid));
          const tokenAddr = String(sInfo?.seriesToken ?? sInfo?.[2] ?? "");
          const deliveryTs =
            Number((sInfo?.deliveryTimestamp ?? sInfo?.[3] ?? 0) as any) * 1000;
          const aprBpsVal = Number(sInfo?.annualRateBPS ?? sInfo?.[4] ?? 0);
          const row: OrderRow = {
            seriesId: sid,
            commodity: "Gold",
            token: tokenAddr,
            amount: Number(formatUnits(amt, 18)).toFixed(4),
            delivery: deliveryTs
              ? new Date(deliveryTs).toLocaleDateString()
              : "",
            subDate: block
              ? new Date(
                  Number((block as any).timestamp) * 1000
                ).toLocaleDateString()
              : "",
            apr: `${(aprBpsVal / 100).toFixed(2)}%`,
            tx: String((e as any).transactionHash ?? ""),
          };
          rows.push(row);
        } catch {}
      }
      setOrders(rows.reverse());
      notify("Orders refreshed.", "success");
    } catch (e: any) {
      notify(getRpcMessage(e) || "Failed to load orders", "error");
    } finally {
      setLoadingOrders(false);
    }
  };

  // Subscribe actions
  const onApproveSubscribe = async () => {
    if (!wallet || !signer)
      return notify("Please connect your wallet.", "error");
    const opId = Date.now();
    lastOpRef.current = opId;
    try {
      const tok = supportedPayTokens.find((t) => t.symbol === payToken);
      if (!tok) return notify("Select a supported currency.", "error");
      const erc20 = new Contract(tok.address, ERC20_ABI as any, signer);
      const tx = await erc20.approve(ORDERBOOK_ADDR, MaxUint256);
      if (!tx?.hash) {
        if (lastOpRef.current === opId)
          updateStatus("Transaction was not submitted", "error");
        return;
      }
      await tx.wait?.();
      if (lastOpRef.current === opId) notify("Token approved.", "success");
    } catch (e: any) {
      if (isUserRejected(e)) {
        if (lastOpRef.current === opId)
          updateStatus("Approval cancelled by user", "info");
        return;
      }
      if (lastOpRef.current === opId) notifyError(e, "Approval failed");
    }
  };

  const onSubscribe = async () => {
    if (!wallet || !signer || !orderBook)
      return notify("Please connect your wallet.", "error");
    if (!seriesId || !amount) return notify("Enter series & amount", "error");
    if (!fullName.trim()) return notify("Full name is required", "error");
    const opId = Date.now();
    lastOpRef.current = opId;
    try {
      const tok = supportedPayTokens.find((t) => t.symbol === payToken);
      if (!tok) return notify("Select a supported currency.", "error");
      const amt18 = parseUnits(amount, 18);
      updateStatus("Processing subscription...", "info");
      const tx = await (orderBook as any).subscribe?.(
        seriesId,
        amt18,
        tok.address,
        fullName,
        companyName
      );
      if (!tx?.hash) {
        if (lastOpRef.current === opId)
          updateStatus("Transaction was not submitted", "error");
        return;
      }
      await tx?.wait?.();
      if (lastOpRef.current === opId) {
        notify(`Subscribed ${amount} to #${seriesId}.`, "success");
        updateStatus("Ready.", "success");
      }
      setAmount("");
      onRefreshOrders();
      loadSeriesDetail(Number(seriesId));
      loadSeriesList();
    } catch (e: any) {
      if (isUserRejected(e)) {
        if (lastOpRef.current === opId)
          updateStatus("Subscription cancelled by user", "info");
        return;
      }
      if (lastOpRef.current === opId) notifyError(e, "Subscription failed");
    }
  };

  // Marketplace actions
  const onApproveSeriesToken = async () => {
    if (!signer) return notify("Please connect your wallet.", "error");
    const tokenAddr = selectedOwnedToken;
    if (!tokenAddr) return notify("Select a series token you own.", "error");
    const opId = Date.now();
    lastOpRef.current = opId;
    try {
      const token = new Contract(tokenAddr, FUTURE_TOKEN_ABI as any, signer);
      const tx = await token.approve(MARKETPLACE_ADDR, MaxUint256);
      if (!tx?.hash) {
        if (lastOpRef.current === opId)
          updateStatus("Transaction was not submitted", "error");
        return;
      }
      await tx.wait?.();
      if (lastOpRef.current === opId)
        notify("Series token approved for marketplace.", "success");
    } catch (e: any) {
      if (isUserRejected(e)) {
        if (lastOpRef.current === opId)
          updateStatus("Approval cancelled by user", "info");
        return;
      }
      if (lastOpRef.current === opId) notifyError(e, "Approval failed");
    }
  };

  const onListForSale = async () => {
    if (!signer || !marketplace)
      return notify("Please connect your wallet.", "error");
    if (!listQty || !listPrice) return notify("Enter qty & price", "error");
    if (!selectedOwnedToken)
      return notify("Select a series token you own.", "error");
    const opId = Date.now();
    lastOpRef.current = opId;
    try {
      const tokenAddr = selectedOwnedToken;
      const currencyMap: Record<string, string> = {
        IUSD: "0xFEF7D9E974713E56Be167C8685e253DE5ec9c8d0",
        USDC: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
        USDT: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
      };
      const currencyAddr = currencyMap[listCurrency] ?? "";
      if (!currencyAddr) return notify("Unsupported currency.", "error");
      const qty18 = parseUnits(listQty, 18);
      const price18 = parseUnits(listPrice, 18);
      const tx = await (marketplace as any).listForSale?.(
        tokenAddr,
        qty18,
        price18,
        currencyAddr
      );
      if (!tx?.hash) {
        if (lastOpRef.current === opId)
          updateStatus("Transaction was not submitted", "error");
        return;
      }
      await tx?.wait?.();
      if (lastOpRef.current === opId) notify("Listing created.", "success");
      setListQty("");
      setListPrice("");
      loadListings();
    } catch (e: any) {
      if (isUserRejected(e)) {
        if (lastOpRef.current === opId)
          updateStatus("Listing cancelled by user", "info");
        return;
      }
      if (lastOpRef.current === opId) notifyError(e, "Listing failed");
    }
  };

  const onBuyListing = async (id: number) => {
    if (!marketplace || !provider || !wallet)
      return notify("Please connect your wallet.", "error");
    const opId = Date.now();
    lastOpRef.current = opId;
    try {
      const qtyStr = window.prompt(`Quantity to buy for listing #${id}?`);
      if (!qtyStr) return;
      const listing = await (marketplace as any).listings?.(id);
      if (!listing) return notify("Listing not found.", "error");
      const qty18 = parseUnits(qtyStr, 18);
      // Guard: ensure desired <= available
      const avail = (listing.amount ?? listing[3] ?? BigInt(0)) as bigint;
      if (qty18 > avail)
        return notify("Not enough quantity in listing.", "error");

      const pricePerToken = (listing.pricePerToken ??
        listing[4] ??
        BigInt(0)) as bigint;
      const WAD = parseUnits("1", 18);
      const totalPayment = (pricePerToken * qty18) / WAD; // 18-decimal convention (mirrors HTML)
      const currencyAddr = String(listing.currencyForSale ?? listing[5] ?? "");

      const erc20 = new Contract(
        currencyAddr,
        ERC20_ABI as any,
        await provider.getSigner()
      );
      const allowance: bigint = await (erc20 as any).allowance?.(
        wallet,
        MARKETPLACE_ADDR
      );
      if (allowance < totalPayment) {
        notify("Approving payment token...", "info");
        const approveTx = await (erc20 as any).approve?.(
          MARKETPLACE_ADDR,
          MaxUint256
        );
        await approveTx?.wait?.();
      }

      const tx = await (marketplace as any).buy?.(id, qty18);
      if (!tx?.hash) {
        if (lastOpRef.current === opId)
          updateStatus("Transaction was not submitted", "error");
        return;
      }
      await tx?.wait?.();
      if (lastOpRef.current === opId)
        notify(`Purchased from listing #${id}.`, "success");
      loadListings();
    } catch (e: any) {
      if (isUserRejected(e)) {
        if (lastOpRef.current === opId)
          updateStatus("Purchase cancelled by user", "info");
        return;
      }
      if (lastOpRef.current === opId) notifyError(e, "Purchase failed");
    }
  };

  // Admin: Create Series (call contract with struct param)
  const onCreateSeries = async () => {
    if (!isAdmin || !orderBook) return notify("Admin only.", "error");
    try {
      if (
        !newSeriesCommodity ||
        !newSeriesDateTime ||
        !newSeriesSupply ||
        !newSeriesName ||
        !newSeriesSymbol
      ) {
        return notify("Fill all fields for Create Series.", "error");
      }
      setCreatingSeries(true);
      const parsed = new Date(newSeriesDateTime);
      if (isNaN(parsed.getTime()))
        return notify("Invalid delivery date/time.", "error");
      const dt = parsed;
      const deliveryTimestamp = Math.floor(dt.getTime() / 1000);
      const totalAmount = parseUnits(newSeriesSupply, 18);
      const annualRateBPS =
        Math.round(parseFloat(newSeriesRatePct || "0") * 100) || 0;
      const params = {
        commoditySymbol: newSeriesCommodity,
        deliveryTimestamp,
        totalAmount,
        annualRateBPS,
        tokenName: newSeriesName,
        tokenSymbol: newSeriesSymbol,
      } as any;
      const tx = await (orderBook as any).createSeries?.(params);
      await tx?.wait?.();
      notify(`Series created (${newSeriesCommodity}).`, "success");
      setNewSeriesSupply("");
      setNewSeriesRatePct("");
      setNewSeriesName("");
      setNewSeriesSymbol("");
      setNewSeriesDateTime("");
      await loadSeriesList();
    } catch (e: any) {
      notify(getRpcMessage(e) || "Create series failed", "error");
    } finally {
      setCreatingSeries(false);
    }
  };

  // Derived: estimated pay
  const estimatedPay = useMemo(() => {
    try {
      const amtStr = String(amount || "").trim();
      if (!amtStr) return "";
      const amtNum = parseFloat(amtStr);
      if (!Number.isFinite(amtNum) || amtNum <= 0) return "";
      const amt18 = parseUnits(amtStr, 18);
      let strikeRaw = seriesStrikeRaw;
      if (!strikeRaw && seriesStrikeVal != null)
        strikeRaw = parseUnits(seriesStrikeVal.toString(), 18);
      if (!strikeRaw) {
        const spotNum = Number(spot);
        if (Number.isFinite(spotNum) && spotNum > 0)
          strikeRaw = parseUnits(spotNum.toString(), 18);
      }
      if (!strikeRaw) return "";
      const WAD = parseUnits("1", 18);
      const cost18 = (strikeRaw * amt18) / WAD;
      const decs =
        ({ IUSD: 18, USDC: 6, USDT: 6 } as Record<string, number>)[payToken] ??
        18;
      let final = cost18;
      if (decs < 18) final = cost18 / parseUnits("1", 18 - decs);
      else if (decs > 18) final = cost18 * parseUnits("1", decs - 18);
      const num = Number(formatUnits(final, decs));
      if (!Number.isFinite(num)) return "";
      return `${new Intl.NumberFormat(undefined, {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
      }).format(num)} ${payToken}`;
    } catch {
      return "";
    }
  }, [amount, seriesStrikeRaw, payToken, seriesStrikeVal, spot]);

  // ----------------------------- UI -----------------------------
  const Header = (
    <Card
      sx={{ border: "1px solid #D4DBE3", boxShadow: "none", borderRadius: 2 }}
    >
      <CardHeader
        avatar={<TrendingUp />}
        title={<Typography variant="h6">IntelliWealth Platform</Typography>}
        action={
          <Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
            {wallet ? (
              <>
                <Chip
                  size="small"
                  color="success"
                  variant="outlined"
                  label={shortAddr(wallet)}
                />
                <Button onClick={onDisconnect} variant="outlined" startIcon={<LogoutIcon />} sx={{
                bgcolor: "#0b3d91",
                textTransform: "none",
                fontSize: 14,
                color: "#FFFFFF",
                "&:hover": { bgcolor: "#083475" },
              }}>
                  Disconnect
                </Button>
              </>
            ) : (
              <Button onClick={onConnect} variant="contained"sx={{
                bgcolor: "#0b3d91",
                textTransform: "none",
                fontSize: 14,
                color: "#FFFFFF",
                "&:hover": { bgcolor: "#083475" },
              }}>
                Connect Wallet
              </Button>
            )}
          </Box>
        }
      />
      <CardContent>
        <Box
          sx={{
            display: "flex",
            flexDirection: { xs: "column", md: "row" },
            alignItems: { xs: "flex-start", md: "center" },
            justifyContent: "space-between",
            gap: 3,
          }}
        >
          <Box>
            <Typography variant="subtitle2">Commodity</Typography>
            <TextField
              size="small"
              value="GOLD"
              InputProps={{ readOnly: true }}
            />
          </Box>
          <Box>
            <Typography variant="subtitle2">Spot Price</Typography>
            <Chip variant="filled" label={`${spot || "—"} USD/Oz`} />
          </Box>
        </Box>
      </CardContent>
    </Card>
  );

  const Projection = (
    <Card
      sx={{ border: "1px solid #D4DBE3", boxShadow: "none", borderRadius: 2 }}
    >
      <CardHeader
        title={<Typography variant="h6">Price Projection</Typography>}
      />
      <Divider />
      <CardContent>
        <Box
          sx={{
            display: "grid",
            gridTemplateColumns: { xs: "1fr", md: "1fr 1fr" },
            gap: 2,
            mb: 2,
          }}
        >
          <TextField
            label="Annual Interest Rate (%)"
            type="number"
            inputProps={{ step: 0.01 }}
            value={apr}
            onChange={(e) => setApr(Number(e.target.value))}
            fullWidth
          />
          <TextField
            label="Projection Start Month"
            type="month"
            value={startMonth}
            onChange={(e) => setStartMonth(e.target.value)}
            fullWidth
          />
        </Box>
        <Box style={{ height: 260 }}>
          <Line
            height={120}
            options={projectionOptions}
            data={projectionData}
          />
        </Box>
      </CardContent>
    </Card>
  );

  const Subscribe = (
    <Card
      sx={{ border: "1px solid #D4DBE3", boxShadow: "none", borderRadius: 2 }}
    >
      <CardHeader
        title={<Typography variant="h6">Subscribe to a Series</Typography>}
      />
      <Divider />
      <CardContent>
        {/* Stepper */}
        <Stepper
          activeStep={seriesId ? (amount ? 2 : 1) : 0}
          alternativeLabel
          sx={{ mb: 2 }}
        >
          <Step>
            <StepLabel>Select Series</StepLabel>
          </Step>
          <Step>
            <StepLabel>Amount & Currency</StepLabel>
          </Step>
          <Step>
            <StepLabel>Confirm</StepLabel>
          </Step>
        </Stepper>

        {/* Strike / Remaining */}
        <Box
          sx={{
            display: "flex",
            flexDirection: { xs: "column", md: "row" },
            gap: 2,
            mb: 2,
          }}
        >
          <Chip label={`Strike: ${seriesStrike}`} variant="outlined" />
          <Chip label={`Remaining: ${seriesRemaining}`} variant="outlined" />
        </Box>

        {/* 1) Series */}
        <Typography variant="subtitle2" sx={{ mb: 2 }}>
          1. Choose Series
        </Typography>
        <Box sx={{ display: "flex", flexDirection: "column", gap: 2, mb: 3 }}>
          <FormControl fullWidth>
            <InputLabel>Series</InputLabel>
            <Select
              label="Series"
              value={seriesId}
              onChange={(e) => setSeriesId(Number(e.target.value))}
              disabled={!wallet || loadingSeries || seriesList.length === 0}
            >
              <MenuItem value="" disabled>
                -- Select a Series --
              </MenuItem>
              {loadingSeries && (
                <MenuItem value="" disabled>
                  <Box sx={{ display: "flex", alignItems: "center", gap: 1.5 }}>
                    <Skeleton variant="circular" width={16} height={16} />{" "}
                    Loading…
                  </Box>
                </MenuItem>
              )}
              {seriesList.map((s) => (
                <MenuItem key={s.id} value={s.id}>
                  Series #{s.id} ({s.commodity})
                </MenuItem>
              ))}
            </Select>
            {!wallet && (
              <Typography variant="caption" color="text.secondary">
                Connect wallet to load available series.
              </Typography>
            )}
          </FormControl>
        </Box>

        {/* 2) Amount & Currency */}
        <Typography variant="subtitle2" sx={{ mb: 2 }}>
          2. Amount & Payment
        </Typography>
        <Box
          sx={{
            display: "flex",
            flexDirection: { xs: "column", md: "row" },
            gap: 2,
            mb: 3,
          }}
        >
          <TextField
            label="Amount"
            placeholder="10.5"
            type="number"
            inputProps={{ min: 0, step: 0.001 }}
            value={amount}
            onChange={(e) => setAmount(e.target.value)}
            fullWidth
            InputProps={{
              endAdornment: <InputAdornment position="end">oz</InputAdornment>,
            }}
          />
          <FormControl fullWidth>
            <InputLabel>Currency</InputLabel>
            <Select
              label="Currency"
              value={payToken}
              onChange={(e) => setPayToken(String(e.target.value))}
              disabled={!wallet}
            >
              {supportedPayTokens.length === 0 && (
                <MenuItem value={payToken} disabled>
                  No supported tokens
                </MenuItem>
              )}
              {supportedPayTokens.map((t) => (
                <MenuItem key={t.symbol} value={t.symbol}>
                  {t.symbol}
                </MenuItem>
              ))}
            </Select>
          </FormControl>
        </Box>

        {/* Estimate */}
        <Paper
          variant="outlined"
          sx={{
            p: 2,
            borderRadius: 2,
            mb: 2,
            display: "flex",
            justifyContent: "space-between",
            alignItems: "center",
          }}
        >
          <Typography variant="body2" color="text.secondary">
            Estimated Cost
          </Typography>
          <Typography variant="h6">{estimatedPay || "—"}</Typography>
        </Paper>

        {/* 3) Details */}
        <Typography variant="subtitle2" sx={{ mb: 1 }}>
          3. Buyer Details
        </Typography>
        <Box sx={{ display: "flex", flexDirection: "column", gap: 2, mb: 3 }}>
          <TextField
            label="Full Name"
            placeholder="John Doe"
            value={fullName}
            onChange={(e) => setFullName(e.target.value)}
            fullWidth
          />
          <TextField
            label="Company (Optional)"
            placeholder="IntelliWealth Inc."
            value={companyName}
            onChange={(e) => setCompanyName(e.target.value)}
            fullWidth
          />
        </Box>

        {/* Sticky action bar */}
        <Box
          sx={{
            mt: 2,
            position: "sticky",
            bottom: 0,
            bgcolor: "background.paper",
            py: 1,
            borderTop: "1px solid",
            borderColor: "divider",
            display: "flex",
            gap: 1,
            flexDirection: { xs: "column", sm: "row" },
          }}
        >
          <Button
            onClick={onApproveSubscribe}
            variant="outlined"
            fullWidth
            disabled={!wallet || !seriesId || !amount}
          >
            Approve Token
          </Button>
          <Button
            onClick={onSubscribe}
            variant="contained"
            fullWidth
            disabled={!wallet || !seriesId || !amount}
          >
            Confirm Subscription
          </Button>
        </Box>

        {/* <Divider sx={{ my: 2 }} />
        <Alert
          severity="info"
          variant="outlined"
          icon={<InfoOutlined />}
          sx={{
            mb: 2,
            borderColor: "info.main",
            color: "info.main",
            bgcolor: "rgba(2, 136, 209, 0.06)",
            borderLeft: "4px solid",
            borderLeftColor: "info.main",
            alignItems: "center",
          }}
        >
          After subscribing, submit delivery instructions.
        </Alert>*/}
        {/* <DeliveryForm orderBook={orderBook} notify={notify} />  */}
      </CardContent>
    </Card>
  );

  const Orders = (
    <Card
      sx={{ border: "1px solid #D4DBE3", boxShadow: "none", borderRadius: 2 }}
    >
      <CardHeader
        title={<Typography variant="h6">Your Subscriptions</Typography>}
      />
      <Divider />
      <CardContent>
        <Box
          sx={{
            display: "grid",
            gridTemplateColumns: "repeat(7, 1fr)",
            gap: 2,
            px: 2,
            py: 1,
            color: "text.secondary",
            fontSize: 12,
            textTransform: "uppercase",
            letterSpacing: "0.06em",
          }}
        >
          <span>Series</span>
          <span>Commodity</span>
          <span>Token</span>
          <span>Quantity</span>
          <span>Delivery</span>
          <span>Subscription Date</span>
          <span>APR</span>
        </Box>
        <Box
          sx={{
            border: "1px solid",
            borderColor: "divider",
            borderRadius: 2,
            maxHeight: 384,
            overflow: "auto",
          }}
        >
          {loadingOrders && <LinearProgress />}
          {!loadingOrders && orders.length === 0 && (
            <Box sx={{ p: 3, textAlign: "center", color: "text.secondary" }}>
              No subscriptions found.
            </Box>
          )}
          {!!orders.length &&
            orders.map((o, i) => (
              <Box
                key={i}
                sx={{
                  display: "grid",
                  gridTemplateColumns: "repeat(7, 1fr)",
                  gap: 2,
                  alignItems: "center",
                  px: 2,
                  py: 1.25,
                  borderBottom: "1px solid",
                  borderColor: "divider",
                }}
              >
                <Typography variant="body2">#{o.seriesId}</Typography>
                <Typography variant="body2">{o.commodity}</Typography>
                <Typography
                  variant="caption"
                  sx={{ fontFamily: "monospace", wordBreak: "break-all" }}
                >
                  {o.token}
                </Typography>
                <Typography variant="body2">{o.amount}</Typography>
                <Typography variant="body2">{o.delivery}</Typography>
                <Typography variant="body2">{o.subDate}</Typography>
                <Typography variant="body2">{o.apr}</Typography>
              </Box>
            ))}
        </Box>
        {/* <Box sx={{ display: 'flex', gap: 2, mt: 1 }}>
          <Button size="small" variant="text" onClick={onRefreshOrders}>Refresh</Button>
        </Box> */}
      </CardContent>
    </Card>
  );

  const Marketplace = (
    <Card
      sx={{ border: "1px solid #D4DBE3", boxShadow: "none", borderRadius: 2 }}
    >
      <CardHeader
        title={
          <Typography variant="h6">List Your Series Token for Sale</Typography>
        }
      />{" "}
      <Divider />
      <CardContent>
        <Box className="flex flex-col md:flex-row gap-6">
          <Box
            sx={{ flex: 1, display: "flex", flexDirection: "column", gap: 2 }}
          >
            <Typography variant="subtitle2">Series Token You Own</Typography>
            <FormControl fullWidth>
              <Select
                value={selectedOwnedToken}
                onChange={(e) => setSelectedOwnedToken(String(e.target.value))}
                displayEmpty
              >
                {selectedOwnedToken === "" && (
                  <MenuItem value="" disabled>
                    {ownedTokensStatus === "loading" &&
                      "… Loading your tokens …"}
                    {ownedTokensStatus === "error" &&
                      "— Error loading your tokens —"}
                    {ownedTokensStatus !== "loading" &&
                      ownedTokensStatus !== "error" &&
                      ownedTokens.length === 0 &&
                      "— No tokens found —"}
                  </MenuItem>
                )}
                {ownedTokens.map((o) => (
                  <MenuItem key={o.token} value={o.token}>{`Series #${
                    o.seriesId
                  } — ${shortAddr(o.token)}`}</MenuItem>
                ))}
              </Select>
            </FormControl>
            <Box
              sx={{
                display: "flex",
                flexDirection: { xs: "column", sm: "row" },
                gap: 2,
              }}
            >
              <TextField
                label="Quantity to List"
                type="number"
                value={listQty}
                onChange={(e) => setListQty(e.target.value)}
                inputProps={{ step: "0.0001" }}
                fullWidth
                helperText="Ounces"
                InputProps={{
                  endAdornment: (
                    <InputAdornment position="end">oz</InputAdornment>
                  ),
                }}
              />
              <TextField
                label="Price Per Token"
                type="number"
                value={listPrice}
                onChange={(e) => setListPrice(e.target.value)}
                inputProps={{ step: "0.01" }}
                fullWidth
                helperText="Per ounce"
                InputProps={{
                  endAdornment: (
                    <InputAdornment position="end">
                      {listCurrency}
                    </InputAdornment>
                  ),
                }}
              />
            </Box>
            <FormControl fullWidth>
              <InputLabel>Currency for Sale</InputLabel>
              <Select
                label="Currency for Sale"
                value={listCurrency}
                onChange={(e) => setListCurrency(String(e.target.value))}
              >
                {["IUSD", "USDC", "USDT"].map((sym) => (
                  <MenuItem key={sym} value={sym}>
                    {sym}
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
            <Button
              onClick={onApproveSeriesToken}
              disabled={!selectedOwnedToken}
              variant="contained"
              color="success"
              fullWidth
              sx={{ mt: 1, py: 1.25 }}
            >
              1. Approve Token for Marketplace
            </Button>
            <Button
              onClick={onListForSale}
              disabled={!selectedOwnedToken || !listQty || !listPrice}
              variant="contained"
              color="primary"
              fullWidth
              sx={{ mt: 1, py: 1.25 }}
            >
              2. List for Sale
            </Button>
          </Box>
          <Divider
            orientation="vertical"
            flexItem
            sx={{ display: { xs: "none", md: "block" } }}
          />
          <Box
            sx={{ flex: 1, display: "flex", flexDirection: "column", gap: 2 }}
          >
            <CardHeader
              title={<Typography variant="h6">Browse Listings</Typography>}
            />
            <Divider />
            <Button
              onClick={loadListings}
              variant="contained"
              color="primary"
              fullWidth
              sx={{ mb: 1 }}
            >
              Refresh Listings
            </Button>
            <Box
              sx={{
                border: "1px solid",
                borderColor: "divider",
                borderRadius: 1,
                overflow: "hidden",
              }}
            >
              <Table size="small" aria-label="Marketplace listings">
                <TableHead>
                  <TableRow>
                    <TableCell>ID</TableCell>
                    <TableCell>Seller</TableCell>
                    <TableCell>Commodity</TableCell>
                    <TableCell>Amount</TableCell>
                    <TableCell>Price</TableCell>
                    <TableCell>Currency</TableCell>
                    <TableCell>Buy</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  {listings.map((l) => (
                    <TableRow key={l.id}>
                      <TableCell>{l.id}</TableCell>
                      <TableCell className="address-cell">{l.seller}</TableCell>
                      <TableCell>Gold</TableCell>
                      <TableCell>{l.amount}</TableCell>
                      <TableCell>{l.price}</TableCell>
                      <TableCell>{l.currency}</TableCell>
                      <TableCell>
                        <Button
                          size="small"
                          variant="contained"
                          onClick={() => onBuyListing(l.id)}
                        >
                          Buy
                        </Button>
                      </TableCell>
                    </TableRow>
                  ))}
                  {listings.length === 0 && (
                    <TableRow>
                      <TableCell colSpan={7} align="center">
                        No active listings.
                      </TableCell>
                    </TableRow>
                  )}
                </TableBody>
              </Table>
            </Box>
            <Box
              sx={{
                mt: 2,
                textAlign: "center",
                color:
                  status.kind === "error"
                    ? "error.main"
                    : status.kind === "success"
                    ? "success.main"
                    : "text.secondary",
              }}
            >
              {status.message}
            </Box>
          </Box>
        </Box>
      </CardContent>
    </Card>
  );

  return (
    <Box
      sx={{
        p: { xs: 2, md: 3 },
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
      }}
    >
      <Box
        sx={{
          width: "100%",
          maxWidth: 1040,
          display: "flex",
          flexDirection: "column",
          gap: 6,
        }}
      >
        {Header}
        {wallet && Projection}
        {wallet && (
          <Card
            sx={{
              border: "1px solid #D4DBE3",
              boxShadow: "none",
              borderRadius: 2,
            }}
          >
            <CardContent>
              <Tabs
                value={tab}
                onChange={(_, v) => setTab(v)}
                sx={{ mb: 2 }}
                variant="scrollable"
                allowScrollButtonsMobile
              >
                <Tab
                  icon={<ShoppingCartOutlined />}
                  iconPosition="start"
                  label="Subscribe"
                />
                <Tab
                  icon={<AssignmentTurnedInOutlined />}
                  iconPosition="start"
                  label={`My Orders${
                    orders.length ? ` (${orders.length})` : ""
                  }`}
                />
                {/* {isAdmin && ( */}
                  <Tab
                    icon={<StorefrontOutlined />}
                    iconPosition="start"
                    label="Marketplace"
                  />
                {/* )} */}
                {isAdmin && (
                  <Tab
                    icon={<AddCircleOutline />}
                    iconPosition="start"
                    label="Create Series"
                  />
                )}
              </Tabs>
              <Box>
                {tab === 0 && Subscribe}
                {tab === 1 && Orders}
                {
                // isAdmin && 
                tab === 2 && Marketplace}
                {isAdmin && tab === 3 && (
                  <Card
                    sx={{
                      border: "1px solid #D4DBE3",
                      boxShadow: "none",
                      borderRadius: 2,
                    }}
                  >
                    <CardHeader
                      title={
                        <Typography variant="h6">
                          Create New Series (Admin Only)
                        </Typography>
                      }
                    />
                    <Divider />
                    <CardContent>
                      <Box
                        sx={{
                          display: "flex",
                          flexDirection: "column",
                          gap: 3,
                        }}
                      >
                        <Box
                          sx={{
                            display: "flex",
                            flexDirection: { xs: "column", md: "row" },
                            gap: 2,
                          }}
                        >
                          <Box
                            sx={{
                              flex: 1,
                              display: "flex",
                              flexDirection: "column",
                              gap: 1,
                            }}
                          >
                            <Typography variant="subtitle2">
                              Commodity Symbol
                            </Typography>
                            <TextField
                              placeholder="GOLD"
                              value={newSeriesCommodity}
                              onChange={(e) =>
                                setNewSeriesCommodity(e.target.value)
                              }
                              fullWidth
                            />
                          </Box>
                          <Box
                            sx={{
                              flex: 1,
                              display: "flex",
                              flexDirection: "column",
                              gap: 1,
                            }}
                          >
                            <Typography variant="subtitle2">
                              Delivery Date & Time (UTC)
                            </Typography>
                            <TextField
                              type="datetime-local"
                              value={newSeriesDateTime}
                              onChange={(e) =>
                                setNewSeriesDateTime(e.target.value)
                              }
                              fullWidth
                            />
                          </Box>
                        </Box>
                        <Box
                          sx={{
                            display: "flex",
                            flexDirection: { xs: "column", md: "row" },
                            gap: 2,
                          }}
                        >
                          <Box
                            sx={{
                              flex: 1,
                              display: "flex",
                              flexDirection: "column",
                              gap: 1,
                            }}
                          >
                            <Typography variant="subtitle2">
                              Total Amount (Ounce)
                            </Typography>
                            <TextField
                              type="number"
                              placeholder="100"
                              value={newSeriesSupply}
                              onChange={(e) =>
                                setNewSeriesSupply(e.target.value)
                              }
                              fullWidth
                            />
                          </Box>
                          <Box
                            sx={{
                              flex: 1,
                              display: "flex",
                              flexDirection: "column",
                              gap: 1,
                            }}
                          >
                            <Typography variant="subtitle2">
                              Annual Rate (%)
                            </Typography>
                            <TextField
                              type="number"
                              placeholder="-5 for discount, 5 for premium"
                              value={newSeriesRatePct}
                              onChange={(e) =>
                                setNewSeriesRatePct(e.target.value)
                              }
                              fullWidth
                            />
                          </Box>
                        </Box>
                        <Box
                          sx={{
                            display: "flex",
                            flexDirection: { xs: "column", md: "row" },
                            gap: 2,
                          }}
                        >
                          <Box
                            sx={{
                              flex: 1,
                              display: "flex",
                              flexDirection: "column",
                              gap: 1,
                            }}
                          >
                            <Typography variant="subtitle2">
                              Token Name
                            </Typography>
                            <TextField
                              placeholder="e.g., IntelliGold Aug26"
                              value={newSeriesName}
                              onChange={(e) => setNewSeriesName(e.target.value)}
                              fullWidth
                            />
                          </Box>
                          <Box
                            sx={{
                              flex: 1,
                              display: "flex",
                              flexDirection: "column",
                              gap: 1,
                            }}
                          >
                            <Typography variant="subtitle2">
                              Token Symbol
                            </Typography>
                            <TextField
                              placeholder="e.g., IGAUG26"
                              value={newSeriesSymbol}
                              onChange={(e) =>
                                setNewSeriesSymbol(e.target.value)
                              }
                              fullWidth
                            />
                          </Box>
                        </Box>
                        <Box>
                          <Button
                            onClick={onCreateSeries}
                            disabled={creatingSeries}
                            variant="contained"
                            sx={{ alignSelf: "flex-start" }}
                          >
                            {creatingSeries ? "Creating..." : "Create Series"}
                          </Button>
                        </Box>
                      </Box>
                    </CardContent>
                  </Card>
                )}
              </Box>
            </CardContent>
          </Card>
        )}
        <Snackbar
          open={snack.open}
          autoHideDuration={2000}
          onClose={() => setSnack((s) => ({ ...s, open: false }))}
          anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
          aria-label="Notification"
        >
          <Alert
            severity={snack.kind}
            sx={{
              maxWidth: 420,
              width: "auto",
              border: "1px solid #D4DBE3",
              boxShadow: "none",
              wordBreak: "break-word",
              whiteSpace: "pre-line",
            }}
            aria-label={`Notification: ${snack.msg}`}
            action={
              <IconButton
                size="small"
                color="inherit"
                onClick={() => setSnack((s) => ({ ...s, open: false }))}
              >
                <CloseIcon fontSize="small" />
              </IconButton>
            }
          >
            {snack.msg}
          </Alert>
        </Snackbar>
      </Box>
    </Box>
  );
}

function DeliveryForm({
  orderBook,
  notify,
}: {
  orderBook: any;
  notify: (msg: string, kind?: any) => void;
}) {
  const [seriesForDelivery, setSeriesForDelivery] = React.useState("");
  const [instructions, setInstructions] = React.useState("");
  const [submitting, setSubmitting] = React.useState(false);
  const onSubmit = async () => {
    try {
      if (!orderBook) return notify("Connect wallet.", "error");
      if (!seriesForDelivery || !instructions)
        return notify("Series and instructions required.", "error");
      setSubmitting(true);
      const sid = Number(seriesForDelivery);
      const tx = await (orderBook as any).submitDeliveryInstructions?.(
        sid,
        instructions
      );
      await tx?.wait?.();
      notify("Delivery instructions submitted.", "success");
      setSeriesForDelivery("");
      setInstructions("");
    } catch (e: any) {
      const m =
        e?.data?.message ||
        e?.error?.data?.message ||
        e?.error?.message ||
        e?.message ||
        "Failed to submit";
      notify(m, "error");
    } finally {
      setSubmitting(false);
    }
  };
  return (
    <Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
      <TextField
        label="Series ID for Delivery"
        type="number"
        placeholder="e.g., 101"
        value={seriesForDelivery}
        onChange={(e) => setSeriesForDelivery(e.target.value)}
        fullWidth
      />
      <TextField
        label="Delivery Instructions"
        placeholder="e.g., Your full name and vault address"
        value={instructions}
        onChange={(e) => setInstructions(e.target.value)}
        fullWidth
      />
      <Button
        onClick={onSubmit}
        disabled={submitting || !seriesForDelivery}
        variant="outlined"
      >
        Submit
      </Button>
    </Box>
  );
}
