// Shared "live PnL" hook — computes current unrealized PnL (across all
// open positions) and today's PnL (realized from trades closed today +
// unrealized from positions opened today) so the header, dashboard, and
// positions view all agree.
import { useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import { useBackendStream } from "@/hooks/use-backend-stream";
import { useDeltaTickers } from "@/hooks/use-delta-tickers";
import { backendApi, type DeltaPosition, type SignalHistoryItem } from "@/lib/backend-client";

export interface LivePnlState {
  positions: DeltaPosition[];
  currentPnl: number;
  dayPnl: number;
  realizedDayPnl: number;
  openCount: number;
  connected: boolean;
}

function startOfTodayIso() {
  const d = new Date();
  d.setHours(0, 0, 0, 0);
  return d.toISOString();
}

function realizedPnlFor(item: SignalHistoryItem): number {
  const raw = item as unknown as Record<string, unknown>;
  const entry = Number(item.entry_price) || 0;
  const size = Number(raw.order_size_value ?? raw.size ?? 0) || 0;
  const leverage = Number(raw.leverage ?? 1) || 1;
  if (!entry || !size) return 0;
  const dir = item.position_side === "LONG" ? 1 : -1;
  let exit: number | null = null;
  if (item.resolved_outcome === "target_hit") exit = Number(item.take_profit);
  else if (item.resolved_outcome === "stop_hit") exit = Number(item.stop_loss);
  if (exit == null || !Number.isFinite(exit) || !exit) return 0;
  const pct = ((exit - entry) / entry) * dir * leverage;
  return pct * size;
}

export function useLivePnl(): LivePnlState {
  const { positions, connection } = useBackendStream();

  const symbols = useMemo(
    () => Array.from(new Set(positions.map((p) => p.coin_symbol).filter(Boolean))),
    [positions],
  );
  const { tickers } = useDeltaTickers(symbols);

  const enriched = useMemo(() => {
    return positions.map((p) => {
      const anyP = p as unknown as Record<string, unknown>;
      const t = tickers[p.coin_symbol];
      const px = t
        ? [t.price, t.mark_price, t.last_price].find((v) => Number.isFinite(v))
        : undefined;
      if (!Number.isFinite(px)) return p;
      const dir = p.position_side === "LONG" ? 1 : -1;
      const entry = Number(p.entry_price) || 0;
      const leverage = Number(p.leverage) || 1;
      const size =
        Number(p.size ?? anyP.order_size_value ?? anyP.filled_size ?? 0) || 0;
      const pnl_pct = entry ? ((px! - entry) / entry) * 100 * dir * leverage : 0;
      const pnl = (pnl_pct / 100) * size;
      const opened_at =
        p.opened_at ?? (anyP.timestamp as string | undefined) ?? p.opened_at;
      return { ...p, opened_at, current_price: px!, pnl, pnl_pct };
    });
  }, [positions, tickers]);

  const currentPnl = enriched.reduce(
    (s, t) => s + (Number.isFinite(t.pnl) ? (t.pnl as number) : 0),
    0,
  );

  // Realized PnL from signals resolved today (target/stop hit).
  const { data: historyToday } = useQuery({
    queryKey: ["signals-history-today"],
    queryFn: () =>
      backendApi.listSignalHistory({
        from: startOfTodayIso(),
        limit: 200,
        page: 1,
        sort: "created_at",
        dir: "desc",
      }),
    refetchInterval: 30_000,
    staleTime: 15_000,
    retry: false,
  });

  const realizedDayPnl = useMemo(() => {
    const items = historyToday?.items ?? [];
    return items.reduce((s, it) => {
      if (it.resolved_outcome === "target_hit" || it.resolved_outcome === "stop_hit") {
        return s + realizedPnlFor(it);
      }
      return s;
    }, 0);
  }, [historyToday]);

  const unrealizedDayPnl = useMemo(() => {
    const start = new Date();
    start.setHours(0, 0, 0, 0);
    const cutoff = start.getTime();
    return enriched.reduce((s, t) => {
      const opened = t.opened_at ? Date.parse(t.opened_at) : NaN;
      if (Number.isFinite(opened) && opened >= cutoff && Number.isFinite(t.pnl))
        return s + (t.pnl as number);
      return s;
    }, 0);
  }, [enriched]);

  return {
    positions: enriched,
    currentPnl,
    dayPnl: realizedDayPnl + unrealizedDayPnl,
    realizedDayPnl,
    openCount: enriched.length,
    connected: connection.state === "open",
  };
}
