import { keepPreviousData, useQuery, useQueryClient } from "@tanstack/react-query";
import moment from "moment";
import { useCallback, useDeferredValue, useEffect, useRef, useState } from "react";
import GuardrailViewer from "@/components/view_logs/GuardrailViewer/GuardrailViewer";
import { formatNumberWithCommas } from "@/utils/dataUtils";
import { truncateString } from "@/utils/textUtils";
import { SettingOutlined, SyncOutlined } from "@ant-design/icons";
import { Row } from "@tanstack/react-table";
import { Switch, Tab, TabGroup, TabList, TabPanel, TabPanels } from "@tremor/react";
import { Button, Tag, Tooltip } from "antd";
import { internalUserRoles } from "../../utils/roles";
import DeletedKeysPage from "../DeletedKeysPage/DeletedKeysPage";
import DeletedTeamsPage from "../DeletedTeamsPage/DeletedTeamsPage";
import { KeyResponse, Team } from "../key_team_helpers/key_list";
import { PaginatedKeyAliasSelect } from "../KeyAliasSelect/PaginatedKeyAliasSelect/PaginatedKeyAliasSelect";
import { PaginatedModelSelect } from "../ModelSelect/PaginatedModelSelect/PaginatedModelSelect";
import FilterComponent, { FilterOption } from "../molecules/filter";
import { allEndUsersCall, keyInfoV1Call, uiSpendLogsCall } from "../networking";
import KeyInfoView from "../templates/key_info_view";
import AuditLogs from "./audit_logs";
import { createColumns, LogEntry, type LogsSortField } from "./columns";
import { ConfigInfoMessage } from "./ConfigInfoMessage";
import { AGENT_CALL_TYPES, ERROR_CODE_OPTIONS, MCP_CALL_TYPES, QUICK_SELECT_OPTIONS } from "./constants";
import { CostBreakdownViewer } from "./CostBreakdownViewer";
import { ErrorViewer } from "./ErrorViewer";
import { useLogFilterLogic } from "./log_filter_logic";
import { LogDetailsDrawer } from "./LogDetailsDrawer";
import { getTimeRangeDisplay } from "./logs_utils";
import { RequestResponsePanel } from "./RequestResponsePanel";
import SpendLogsSettingsModal from "./SpendLogsSettingsModal/SpendLogsSettingsModal";
import { DataTable } from "./table";
import { VectorStoreViewer } from "./VectorStoreViewer";

interface SpendLogsTableProps {
  accessToken: string | null;
  token: string | null;
  userRole: string | null;
  userID: string | null;
  allTeams: Team[];
  premiumUser: boolean;
}

export interface PaginatedResponse {
  data: LogEntry[];
  total: number;
  page: number;
  page_size: number;
  total_pages: number;
}

export default function SpendLogsTable({
  accessToken,
  token,
  userRole,
  userID,
  allTeams,
  premiumUser,
}: SpendLogsTableProps) {
  const [searchTerm, setSearchTerm] = useState("");
  const [showFilters, setShowFilters] = useState(false);
  const [showColumnDropdown, setShowColumnDropdown] = useState(false);
  const [currentPage, setCurrentPage] = useState(1);
  const [pageSize] = useState(50);
  const dropdownRef = useRef<HTMLDivElement>(null);
  const filtersRef = useRef<HTMLDivElement>(null);
  const quickSelectRef = useRef<HTMLDivElement>(null);

  // New state variables for Start and End Time
  const [startTime, setStartTime] = useState<string>(moment().subtract(24, "hours").format("YYYY-MM-DDTHH:mm"));
  const [endTime, setEndTime] = useState<string>(moment().format("YYYY-MM-DDTHH:mm"));

  const [isCustomDate, setIsCustomDate] = useState(false);
  const [quickSelectOpen, setQuickSelectOpen] = useState(false);
  const [tempTeamId, setTempTeamId] = useState("");
  const [tempKeyHash, setTempKeyHash] = useState("");
  const [selectedTeamId, setSelectedTeamId] = useState("");
  const [selectedKeyHash, setSelectedKeyHash] = useState("");
  const [selectedModelId, setSelectedModelId] = useState("");
  const [selectedKeyInfo, setSelectedKeyInfo] = useState<KeyResponse | null>(null);
  const [selectedKeyIdInfoView, setSelectedKeyIdInfoView] = useState<string | null>(null);
  const [selectedStatus, setSelectedStatus] = useState("");
  const [selectedEndUser, setSelectedEndUser] = useState("");
  const [filterByCurrentUser, setFilterByCurrentUser] = useState(userRole && internalUserRoles.includes(userRole));
  const [activeTab, setActiveTab] = useState("request logs");

  const [selectedLog, setSelectedLog] = useState<LogEntry | null>(null);
  const [isDrawerOpen, setIsDrawerOpen] = useState(false);
  const [selectedSessionId, setSelectedSessionId] = useState<string | null>(null);
  const [isSpendLogsSettingsModalVisible, setIsSpendLogsSettingsModalVisible] = useState(false);

  const [sortBy, setSortBy] = useState<LogsSortField>("startTime");
  const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc");

  // Tracks whether any filter that uses performSearch (backend) is active.
  // Used to disable the main query so it doesn't fire redundant unfiltered requests
  // when time range / sort / page changes while a backend filter is in effect.
  const [isMainQueryEnabled, setIsMainQueryEnabled] = useState(true);

  const queryClient = useQueryClient();

  const [isLiveTail, setIsLiveTail] = useState<boolean>(() => {
    const storedValue = sessionStorage.getItem("isLiveTail");
    // default to true if nothing is stored
    return storedValue !== null ? JSON.parse(storedValue) : true;
  });

  useEffect(() => {
    sessionStorage.setItem("isLiveTail", JSON.stringify(isLiveTail));
  }, [isLiveTail]);

  const [selectedTimeInterval, setSelectedTimeInterval] = useState<{ value: number; unit: string }>({
    value: 24,
    unit: "hours",
  });

  useEffect(() => {
    const fetchKeyInfo = async () => {
      if (selectedKeyIdInfoView && accessToken) {
        const keyData = await keyInfoV1Call(accessToken, selectedKeyIdInfoView);

        const keyResponse: KeyResponse = {
          ...keyData["info"],
          token: selectedKeyIdInfoView,
          api_key: selectedKeyIdInfoView,
        };
        setSelectedKeyInfo(keyResponse);
      }
    };
    fetchKeyInfo();
  }, [selectedKeyIdInfoView, accessToken]);

  // Close dropdown when clicking outside
  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
        setShowColumnDropdown(false);
      }
      if (filtersRef.current && !filtersRef.current.contains(event.target as Node)) {
        setShowFilters(false);
      }
      if (quickSelectRef.current && !quickSelectRef.current.contains(event.target as Node)) {
        setQuickSelectOpen(false);
      }
    }

    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  useEffect(() => {
    if (userRole && internalUserRoles.includes(userRole)) {
      setFilterByCurrentUser(true);
    }
  }, [userRole]);

  const LiveTailControls = () => {
    return (
      <div className="flex items-center gap-2">
        <span className="text-sm font-medium text-gray-900">Live Tail</span>
        <Switch color="green" checked={isLiveTail} defaultChecked={true} onChange={setIsLiveTail} />
      </div>
    );
  };

  const logs = useQuery<PaginatedResponse>({
    queryKey: [
      "logs",
      "table",
      currentPage,
      pageSize,
      startTime,
      endTime,
      selectedTeamId,
      selectedKeyHash,
      filterByCurrentUser ? userID : null,
      selectedStatus,
      selectedModelId,
      sortBy,
      sortOrder,
    ],
    queryFn: async () => {
      if (!accessToken || !token || !userRole || !userID) {
        return {
          data: [],
          total: 0,
          page: 1,
          page_size: pageSize,
          total_pages: 0,
        };
      }

      const formattedStartTime = moment(startTime).utc().format("YYYY-MM-DD HH:mm:ss");
      const formattedEndTime = isCustomDate
        ? moment(endTime).utc().format("YYYY-MM-DD HH:mm:ss")
        : moment().utc().format("YYYY-MM-DD HH:mm:ss");

      // Get base response from API
      // NOTE: We only fetch the list of logs here (lightweight).
      // Log details (messages/response) are fetched on-demand when user clicks a row.
      const response = await uiSpendLogsCall({
        accessToken,
        start_date: formattedStartTime,
        end_date: formattedEndTime,
        page: currentPage,
        page_size: pageSize,
        params: {
          api_key: selectedKeyHash || undefined,
          team_id: selectedTeamId || undefined,
          user_id: filterByCurrentUser ? userID ?? undefined : undefined,
          end_user: selectedEndUser || undefined,
          status_filter: selectedStatus || undefined,
          model_id: selectedModelId || undefined,
          sort_by: sortBy,
          sort_order: sortOrder,
        },
      });

      return response;
    },
    enabled: !!accessToken && !!token && !!userRole && !!userID && activeTab === "request logs" && isMainQueryEnabled,
    refetchInterval: isLiveTail && currentPage === 1 ? 15000 : false,
    placeholderData: keepPreviousData,
    refetchIntervalInBackground: true,
  });

  // Defer the transition from "Fetching" to "Fetch" so the button stays loading until
  // the table has rendered with the new data (avoids the visual gap where the button
  // exits loading state before the table updates)
  const isFetchingDeferred = useDeferredValue(logs.isFetching);
  const isButtonLoading = logs.isFetching || isFetchingDeferred;

  const logsData = logs.data || {
    data: [],
    total: 0,
    page: 1,
    page_size: pageSize || 10,
    total_pages: 1,
  };

  const {
    filters,
    filteredLogs,
    hasBackendFilters,
    allTeams: hookAllTeams,
    handleFilterChange,
    handleFilterReset: handleFilterResetFromHook,
  } = useLogFilterLogic({
    logs: logsData,
    accessToken,
    startTime,
    endTime,
    pageSize,
    isCustomDate,
    setCurrentPage,
    userID,
    userRole,
    sortBy,
    sortOrder,
    currentPage,
  });

  const handleFilterReset = useCallback(() => {
    handleFilterResetFromHook();
    // Reset custom time range to default (last 24 hours)
    setStartTime(moment().subtract(24, "hours").format("YYYY-MM-DDTHH:mm"));
    setEndTime(moment().format("YYYY-MM-DDTHH:mm"));
    setIsCustomDate(false);
    setSelectedTimeInterval({ value: 24, unit: "hours" });
    setCurrentPage(1);
  }, [handleFilterResetFromHook]);

  // Disable the main query whenever backend filters are active so it doesn't fire
  // redundant unfiltered requests when time range / sort / page changes.
  useEffect(() => {
    setIsMainQueryEnabled(!hasBackendFilters);
  }, [hasBackendFilters]);

  // Sync filter state into the individual selectedX state variables used by the main query
  useEffect(() => {
    if (!accessToken) return;

    if (filters["Team ID"]) {
      setSelectedTeamId(filters["Team ID"]);
    } else {
      setSelectedTeamId("");
    }
    setSelectedStatus(filters["Status"] || "");
    setSelectedModelId(filters["Model"] || "");
    setSelectedEndUser(filters["End User"] || "");

    // Key Alias filtering is handled server-side by performSearch via the key_alias param.
    // We intentionally do not translate the alias to a hash here to avoid firing a
    // redundant main-query request (api_key=hash) alongside performSearch's key_alias request.
    setSelectedKeyHash(filters["Key Hash"] || "");
  }, [filters, accessToken]);

  if (!accessToken || !token || !userRole || !userID) {
    return null;
  }

  const searchedLogs = filteredLogs.data.filter((log) => {
    const matchesSearch =
      !searchTerm ||
      log.request_id.includes(searchTerm) ||
      log.model.includes(searchTerm) ||
      (log.user && log.user.includes(searchTerm));

    // No need for additional filtering since we're now handling this in the API call
    return matchesSearch;
  });

  const sessionCompositionById = searchedLogs.reduce<Record<string, { llm: number; agent: number; mcp: number }>>((acc, log) => {
    if (!log.session_id) return acc;
    if (!acc[log.session_id]) {
      acc[log.session_id] = { llm: 0, agent: 0, mcp: 0 };
    }
    if (MCP_CALL_TYPES.includes(log.call_type)) {
      acc[log.session_id].mcp += 1;
    } else if (AGENT_CALL_TYPES.includes(log.call_type)) {
      acc[log.session_id].agent += 1;
    } else {
      acc[log.session_id].llm += 1;
    }
    return acc;
  }, {});

  // Build a single-pass map of session_id → representative request_id.
  // Prefers an LLM row over an MCP row as the representative.
  const sessionRepresentativeMap = new Map<string, { requestId: string; isMcp: boolean }>();
  for (const log of searchedLogs) {
    if (!log.session_id || (log.session_total_count || 1) <= 1) continue;
    const isMcp = MCP_CALL_TYPES.includes(log.call_type);
    const existing = sessionRepresentativeMap.get(log.session_id);
    if (!existing || (existing.isMcp && !isMcp)) {
      sessionRepresentativeMap.set(log.session_id, { requestId: log.request_id, isMcp });
    }
  }

  const filteredData =
    searchedLogs
      .map((log) => {
        const sessionComposition = log.session_id ? sessionCompositionById[log.session_id] : undefined;
        return {
          ...log,
          request_duration_ms: log.request_duration_ms,
          session_llm_count: sessionComposition?.llm ?? undefined,
          session_mcp_count: sessionComposition?.mcp ?? undefined,
          session_agent_count: sessionComposition?.agent ?? undefined,
          onKeyHashClick: (keyHash: string) => setSelectedKeyIdInfoView(keyHash),
          onSessionClick: (sessionId: string) => {
            if (sessionId) {
              setSelectedSessionId(sessionId);
              setSelectedLog(log);
              setIsDrawerOpen(true);
            }
          },
        };
      })
      // Deduplicate multi-call sessions using the pre-built map (O(1) per row).
      .filter((log) => {
        if (!log.session_id || (log.session_total_count || 1) <= 1) return true;
        return sessionRepresentativeMap.get(log.session_id)?.requestId === log.request_id;
      }) || [];

  // Add this function to handle manual refresh
  const handleRefresh = () => {
    logs.refetch();
  };

  const handleRowClick = (log: LogEntry) => {
    // Multi-call session row: open in the same right-side drawer (session mode)
    if (log.session_id && (log.session_total_count || 1) > 1) {
      setSelectedSessionId(log.session_id);
      setSelectedLog(log);
      setIsDrawerOpen(true);
      return;
    }
    // Single-call row: open the detail drawer
    setSelectedSessionId(null);
    setSelectedLog(log);
    setIsDrawerOpen(true);
  };

  const handleCloseDrawer = () => {
    setIsDrawerOpen(false);
    setSelectedSessionId(null);
  };

  const handleSelectLog = (log: LogEntry) => {
    setSelectedLog(log);
  };

  const logFilterOptions: FilterOption[] = [
    {
      name: "Team ID",
      label: "Team ID",
      isSearchable: true,
      searchFn: async (searchText: string) => {
        if (!allTeams || allTeams.length === 0) return [];
        const filtered = allTeams.filter((team: Team) => {
          return (
            team.team_id.toLowerCase().includes(searchText.toLowerCase()) ||
            (team.team_alias && team.team_alias.toLowerCase().includes(searchText.toLowerCase()))
          );
        });
        return filtered.map((team: Team) => ({
          label: `${team.team_alias || team.team_id} (${team.team_id})`,
          value: team.team_id,
        }));
      },
    },
    {
      name: "Status",
      label: "Status",
      isSearchable: false,
      options: [
        { label: "Success", value: "success" },
        { label: "Failure", value: "failure" },
      ],
    },
    {
      name: "Model",
      label: "Model",
      customComponent: PaginatedModelSelect,
    },
    {
      name: "Key Alias",
      label: "Key Alias",
      customComponent: PaginatedKeyAliasSelect,
    },
    {
      name: "End User",
      label: "End User",
      isSearchable: true,
      searchFn: async (searchText: string) => {
        if (!accessToken) return [];
        const data = await allEndUsersCall(accessToken);
        // data if set, is a list of objects, with key = user_id
        const users = data?.map((u: any) => u.user_id) || [];
        const filtered = users.filter((u: string) => u.toLowerCase().includes(searchText.toLowerCase()));
        return filtered.map((u: string) => ({ label: u, value: u }));
      },
    },
    {
      name: "Error Code",
      label: "Error Code",
      isSearchable: true,
      searchFn: async (searchText: string) => {
        if (!searchText) return ERROR_CODE_OPTIONS;
        const lower = searchText.toLowerCase();
        const filtered = ERROR_CODE_OPTIONS.filter((opt) => opt.label.toLowerCase().includes(lower));
        const isExactValue = ERROR_CODE_OPTIONS.some((opt) => opt.value === searchText.trim());
        if (!isExactValue && searchText.trim()) {
          filtered.push({ label: `Use custom code: ${searchText.trim()}`, value: searchText.trim() });
        }
        return filtered;
      },
    },
    {
      name: "Key Hash",
      label: "Key Hash",
      isSearchable: false,
    },
    {
      name: "Error Message",
      label: "Error Message",
      isSearchable: false,
    },
  ];

  const formatTimeUnit = (value: number, unit: string) => {
    if (value === 1) {
      if (unit === "minutes") return "minute";
      if (unit === "hours") return "hour";
      if (unit === "days") return "day";
    }
    return unit;
  };

  const selectedOption = QUICK_SELECT_OPTIONS.find(
    (option) => option.value === selectedTimeInterval.value && option.unit === selectedTimeInterval.unit,
  );

  const displayLabel = isCustomDate ? getTimeRangeDisplay(isCustomDate, startTime, endTime) : selectedOption?.label;

  return (
    <div className="w-full max-w-screen p-6 overflow-x-hidden box-border">
      <TabGroup defaultIndex={0} onIndexChange={(index) => setActiveTab(index === 0 ? "request logs" : "audit logs")}>
        <TabList>
          <Tab>Request Logs</Tab>
          <Tab>Audit Logs</Tab>
          <Tab>Deleted Keys</Tab>
          <Tab>Deleted Teams</Tab>
        </TabList>
        <TabPanels>
          <TabPanel>
            <div className="flex items-center justify-between mb-4">
              <h1 className="text-xl font-semibold">Request Logs</h1>
              <Button
                icon={<SettingOutlined />}
                onClick={() => setIsSpendLogsSettingsModalVisible(true)}
                title="Spend Logs Settings"
              />
            </div>
            {selectedKeyInfo && selectedKeyIdInfoView && selectedKeyInfo.api_key === selectedKeyIdInfoView ? (
              <KeyInfoView
                keyId={selectedKeyIdInfoView}
                keyData={selectedKeyInfo}
                teams={allTeams}
                onClose={() => setSelectedKeyIdInfoView(null)}
                backButtonText="Back to Logs"
              />
            ) : (
              <>
                <FilterComponent
                  options={logFilterOptions}
                  onApplyFilters={handleFilterChange}
                  onResetFilters={handleFilterReset}
                />
                <SpendLogsSettingsModal
                  isVisible={isSpendLogsSettingsModalVisible}
                  onCancel={() => setIsSpendLogsSettingsModalVisible(false)}
                  onSuccess={() => setIsSpendLogsSettingsModalVisible(false)}
                />
                <div className="bg-white rounded-lg shadow w-full max-w-full box-border">
                  <div className="border-b px-6 py-4 w-full max-w-full box-border">
                    <div className="flex flex-col md:flex-row items-start md:items-center justify-between space-y-4 md:space-y-0 w-full max-w-full box-border">
                      <div className="flex flex-wrap items-center gap-3 w-full max-w-full box-border">
                        <div className="relative w-64 min-w-0 flex-shrink-0">
                          <input
                            type="text"
                            placeholder="Search by Request ID"
                            className="w-full px-3 py-2 pl-8 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                            value={searchTerm}
                            onChange={(e) => setSearchTerm(e.target.value)}
                          />
                          <svg
                            className="absolute left-2.5 top-2.5 h-4 w-4 text-gray-500"
                            fill="none"
                            stroke="currentColor"
                            viewBox="0 0 24 24"
                          >
                            <path
                              strokeLinecap="round"
                              strokeLinejoin="round"
                              strokeWidth={2}
                              d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
                            />
                          </svg>
                        </div>

                        <div className="flex items-center gap-2 min-w-0 flex-shrink">
                          <div className="relative z-50" ref={quickSelectRef}>
                            <button
                              onClick={() => setQuickSelectOpen(!quickSelectOpen)}
                              className="px-3 py-2 text-sm border rounded-md hover:bg-gray-50 flex items-center gap-2"
                            >
                              <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path
                                  strokeLinecap="round"
                                  strokeLinejoin="round"
                                  strokeWidth={2}
                                  d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
                                />
                              </svg>
                              {displayLabel}
                            </button>

                            {quickSelectOpen && (
                              <div className="absolute right-0 mt-2 w-64 bg-white rounded-lg shadow-lg border p-2 z-50">
                                <div className="space-y-1">
                                  {QUICK_SELECT_OPTIONS.map((option) => (
                                    <button
                                      key={option.label}
                                      className={`w-full px-3 py-2 text-left text-sm hover:bg-gray-50 rounded-md ${displayLabel === option.label ? "bg-blue-50 text-blue-600" : ""
                                        }`}
                                      onClick={() => {
                                        setCurrentPage(1);
                                        setEndTime(moment().format("YYYY-MM-DDTHH:mm"));
                                        setStartTime(
                                          moment()
                                            .subtract(option.value, option.unit as any)
                                            .format("YYYY-MM-DDTHH:mm"),
                                        );
                                        setSelectedTimeInterval({ value: option.value, unit: option.unit });
                                        setIsCustomDate(false);
                                        setQuickSelectOpen(false);
                                      }}
                                    >
                                      {option.label}
                                    </button>
                                  ))}
                                  <div className="border-t my-2" />
                                  <button
                                    className={`w-full px-3 py-2 text-left text-sm hover:bg-gray-50 rounded-md ${isCustomDate ? "bg-blue-50 text-blue-600" : ""
                                      }`}
                                    onClick={() => setIsCustomDate(!isCustomDate)}
                                  >
                                    Custom Range
                                  </button>
                                </div>
                              </div>
                            )}
                          </div>

                          <LiveTailControls />

                          <Button
                            type="default"
                            icon={<SyncOutlined spin={isButtonLoading} />}
                            onClick={handleRefresh}
                            disabled={isButtonLoading}
                            title="Fetch data"
                          >
                            {isButtonLoading ? "Fetching" : "Fetch"}
                          </Button>
                        </div>

                        {isCustomDate && (
                          <div className="flex items-center gap-2">
                            <div>
                              <input
                                type="datetime-local"
                                value={startTime}
                                onChange={(e) => {
                                  setStartTime(e.target.value);
                                  setCurrentPage(1);
                                }}
                                className="px-3 py-2 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                              />
                            </div>
                            <span className="text-gray-500">to</span>
                            <div>
                              <input
                                type="datetime-local"
                                value={endTime}
                                onChange={(e) => {
                                  setEndTime(e.target.value);
                                  setCurrentPage(1);
                                }}
                                className="px-3 py-2 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                              />
                            </div>
                          </div>
                        )}
                      </div>

                      <div className="flex items-center space-x-4">
                        <span className="text-sm text-gray-700 whitespace-nowrap">
                          Showing {logs.isLoading ? "..." : filteredLogs ? (currentPage - 1) * pageSize + 1 : 0} -{" "}
                          {logs.isLoading
                            ? "..."
                            : filteredLogs
                              ? Math.min(currentPage * pageSize, filteredLogs.total)
                              : 0}{" "}
                          of {logs.isLoading ? "..." : filteredLogs ? filteredLogs.total : 0} results
                        </span>
                        <div className="flex items-center space-x-2">
                          <span className="text-sm text-gray-700 min-w-[90px]">
                            Page {logs.isLoading ? "..." : currentPage} of{" "}
                            {logs.isLoading ? "..." : filteredLogs ? filteredLogs.total_pages : 1}
                          </span>
                          <button
                            onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
                            disabled={logs.isLoading || currentPage === 1}
                            className="px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
                          >
                            Previous
                          </button>
                          <button
                            onClick={() => setCurrentPage((p) => Math.min(filteredLogs.total_pages || 1, p + 1))}
                            disabled={logs.isLoading || currentPage === (filteredLogs.total_pages || 1)}
                            className="px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
                          >
                            Next
                          </button>
                        </div>
                      </div>
                    </div>
                  </div>
                  {isLiveTail && currentPage === 1 && isMainQueryEnabled && (
                    <div className="mb-4 px-4 py-2 bg-green-50 border border-greem-200 rounded-md flex items-center justify-between">
                      <div className="flex items-center gap-2">
                        <span className="text-sm text-green-700">Auto-refreshing every 15 seconds</span>
                      </div>
                      <button
                        onClick={() => setIsLiveTail(false)}
                        className="text-sm text-green-600 hover:text-green-800"
                      >
                        Stop
                      </button>
                    </div>
                  )}
                  <DataTable
                    columns={createColumns({
                      sortBy,
                      sortOrder,
                      onSortChange: (newSortBy, newSortOrder) => {
                        setSortBy(newSortBy);
                        setSortOrder(newSortOrder);
                        setCurrentPage(1);
                      },
                    })}
                    data={filteredData}
                    onRowClick={handleRowClick}
                    isLoading={logs.isLoading}
                  />
                </div>
              </>
            )}
          </TabPanel>
          <TabPanel>
            <AuditLogs
              userID={userID}
              userRole={userRole}
              token={token}
              accessToken={accessToken}
              isActive={activeTab === "audit logs"}
              premiumUser={premiumUser}
            />
          </TabPanel>
          <TabPanel><DeletedKeysPage /></TabPanel>
          <TabPanel><DeletedTeamsPage /></TabPanel>
        </TabPanels>
      </TabGroup>

      {/* Log Details Drawer */}
      <LogDetailsDrawer
        open={isDrawerOpen}
        onClose={handleCloseDrawer}
        logEntry={selectedLog}
        sessionId={selectedSessionId}
        accessToken={accessToken}
        onOpenSettings={() => setIsSpendLogsSettingsModalVisible(true)}
        allLogs={filteredData}
        onSelectLog={handleSelectLog}
        startTime={moment(startTime).utc().format("YYYY-MM-DD HH:mm:ss")}
      />
    </div>
  );
}

export function RequestViewer({ row, onOpenSettings }: { row: Row<LogEntry>; onOpenSettings?: () => void }) {
  // Helper function to clean metadata by removing specific fields
  const formatData = (input: any) => {
    if (typeof input === "string") {
      try {
        return JSON.parse(input);
      } catch {
        return input;
      }
    }
    return input;
  };

  // New helper function to get raw request
  const getRawRequest = () => {
    // First check if proxy_server_request exists in metadata
    if (row.original?.proxy_server_request) {
      return formatData(row.original.proxy_server_request);
    }
    // Fall back to messages if proxy_server_request is empty
    return formatData(row.original.messages);
  };

  // Extract error information from metadata if available
  const metadata = row.original.metadata || {};
  const hasError = metadata.status === "failure";
  const errorInfo = hasError ? metadata.error_information : null;

  // Check if request/response data is missing
  const hasMessages =
    row.original.messages &&
    (Array.isArray(row.original.messages)
      ? row.original.messages.length > 0
      : Object.keys(row.original.messages).length > 0);
  const hasResponse = row.original.response && Object.keys(formatData(row.original.response)).length > 0;
  const missingData = !hasMessages && !hasResponse && !hasError;

  // Format the response with error details if present
  const formattedResponse = () => {
    if (hasError && errorInfo) {
      return {
        error: {
          message: errorInfo.error_message || "An error occurred",
          type: errorInfo.error_class || "error",
          code: errorInfo.error_code || "unknown",
          param: null,
        },
      };
    }
    return formatData(row.original.response);
  };

  // Extract vector store request metadata if available
  const hasVectorStoreData =
    metadata.vector_store_request_metadata &&
    Array.isArray(metadata.vector_store_request_metadata) &&
    metadata.vector_store_request_metadata.length > 0;

  // Extract guardrail information from metadata if available
  const guardrailInfo = row.original.metadata?.guardrail_information;
  const guardrailEntries = Array.isArray(guardrailInfo) ? guardrailInfo : guardrailInfo ? [guardrailInfo] : [];
  const hasGuardrailData = guardrailEntries.length > 0;

  // Calculate total masked entities if guardrail data exists
  const totalMaskedEntities = guardrailEntries.reduce((sum, entry) => {
    const maskedCounts = entry?.masked_entity_count;
    if (!maskedCounts) {
      return sum;
    }
    return (
      sum +
      Object.values(maskedCounts).reduce<number>((acc, count) => (typeof count === "number" ? acc + count : acc), 0)
    );
  }, 0);

  const primaryGuardrailLabel =
    guardrailEntries.length === 1
      ? guardrailEntries[0]?.guardrail_name ?? "-"
      : guardrailEntries.length > 1
        ? `${guardrailEntries.length} guardrails`
        : "-";

  const truncatedRequestId = truncateString(row.original.request_id, 64);

  return (
    <div className="p-6 bg-gray-50 space-y-6 w-full max-w-full overflow-hidden box-border">
      {/* Combined Info Card */}
      <div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden">
        <div className="p-4 border-b">
          <h3 className="text-lg font-medium">Request Details</h3>
        </div>
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4 p-4 w-full max-w-full overflow-hidden">
          <div className="space-y-2">
            <div className="flex">
              <span className="font-medium w-1/3">Request ID:</span>
              {row.original.request_id.length > 64 ? (
                <Tooltip title={row.original.request_id}>
                  <span className="font-mono text-sm">{truncatedRequestId}</span>
                </Tooltip>
              ) : (
                <span className="font-mono text-sm">{row.original.request_id}</span>
              )}
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">Model:</span>
              <span>{row.original.model}</span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">Model ID:</span>
              <span>{row.original.model_id}</span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">Call Type:</span>
              <span>{row.original.call_type}</span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">Provider:</span>
              <span>{row.original.custom_llm_provider || "-"}</span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">API Base:</span>
              <Tooltip title={row.original.api_base || "-"}>
                <span className="max-w-[15ch] truncate block">{row.original.api_base || "-"}</span>
              </Tooltip>
            </div>
            {row?.original?.requester_ip_address && (
              <div className="flex">
                <span className="font-medium w-1/3">IP Address:</span>
                <span>{row?.original?.requester_ip_address}</span>
              </div>
            )}
            {hasGuardrailData && (
              <div className="flex">
                <span className="font-medium w-1/3">Guardrail:</span>
                <div>
                  <span className="font-mono">{primaryGuardrailLabel}</span>
                  {totalMaskedEntities > 0 && (
                    <span className="ml-2 px-2 py-0.5 bg-blue-50 text-blue-700 rounded-md text-xs font-medium">
                      {totalMaskedEntities} masked
                    </span>
                  )}
                </div>
              </div>
            )}
          </div>
          <div className="space-y-2">
            <div className="flex">
              <span className="font-medium w-1/3">Tokens:</span>
              <span>
                {row.original.total_tokens} ({row.original.prompt_tokens} prompt tokens +{" "}
                {row.original.completion_tokens} completion tokens)
              </span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">Cache Read Tokens:</span>
              <span>
                {formatNumberWithCommas(row.original.metadata?.additional_usage_values?.cache_read_input_tokens || 0)}
              </span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">Cache Creation Tokens:</span>
              <span>
                {formatNumberWithCommas(row.original.metadata?.additional_usage_values.cache_creation_input_tokens)}
              </span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">Cost:</span>
              <span>${formatNumberWithCommas(row.original.spend || 0, 6)}</span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">Cache Hit:</span>
              <span>{row.original.cache_hit}</span>
            </div>

            <div className="flex">
              <span className="font-medium w-1/3">Status:</span>
              <span
                className={`px-2 py-1 rounded-md text-xs font-medium inline-block text-center w-16 ${(row.original.metadata?.status || "Success").toLowerCase() !== "failure"
                  ? "bg-green-100 text-green-800"
                  : "bg-red-100 text-red-800"
                  }`}
              >
                {(row.original.metadata?.status || "Success").toLowerCase() !== "failure" ? "Success" : "Failure"}
              </span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">Start Time:</span>
              <span>{row.original.startTime}</span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">End Time:</span>
              <span>{row.original.endTime}</span>
            </div>
            <div className="flex">
              <span className="font-medium w-1/3">Duration:</span>
              <span>{row.original.request_duration_ms != null ? (row.original.request_duration_ms / 1000).toFixed(3) : "-"} s.</span>
            </div>
            {row.original.metadata?.litellm_overhead_time_ms !== undefined && (
              <div className="flex">
                <span className="font-medium w-1/3">LiteLLM Overhead:</span>
                <span>{row.original.metadata.litellm_overhead_time_ms} ms</span>
              </div>
            )}
            <div className="flex">
              <span className="font-medium w-1/3">Retries:</span>
              <span>
                {row.original.metadata?.attempted_retries !== undefined && row.original.metadata?.attempted_retries !== null
                  ? row.original.metadata.attempted_retries > 0
                    ? `${row.original.metadata.attempted_retries}${row.original.metadata.max_retries !== undefined && row.original.metadata.max_retries !== null ? ` / ${row.original.metadata.max_retries}` : ''}`
                    : <Tag color="green">None</Tag>
                  : '-'}
              </span>
            </div>
          </div>
        </div>
      </div>

      {/* Cost Breakdown - Show if cost breakdown data is available */}
      <CostBreakdownViewer
        costBreakdown={row.original.metadata?.cost_breakdown}
        totalSpend={row.original.spend ?? 0}
        promptTokens={row.original.prompt_tokens}
        completionTokens={row.original.completion_tokens}
        cacheHit={row.original.cache_hit}
      />

      {/* Configuration Info Message - Show when data is missing */}
      <ConfigInfoMessage show={missingData} onOpenSettings={onOpenSettings} />

      {/* Request/Response Panel */}
      <div className="w-full max-w-full overflow-hidden">
        <RequestResponsePanel
          row={row}
          hasMessages={hasMessages}
          hasResponse={hasResponse}
          hasError={hasError}
          errorInfo={errorInfo}
          getRawRequest={getRawRequest}
          formattedResponse={formattedResponse}
        />
      </div>

      {/* Guardrail Data - Show only if present */}
      {hasGuardrailData && <GuardrailViewer data={guardrailInfo} />}

      {/* Vector Store Request Data - Show only if present */}
      {hasVectorStoreData && <VectorStoreViewer data={metadata.vector_store_request_metadata} />}

      {/* Error Card - Only show for failures */}
      {hasError && errorInfo && <ErrorViewer errorInfo={errorInfo} />}

      {/* Tags Card - Only show if there are tags */}
      {row.original.request_tags && Object.keys(row.original.request_tags).length > 0 && (
        <div className="bg-white rounded-lg shadow">
          <div className="flex justify-between items-center p-4 border-b">
            <h3 className="text-lg font-medium">Request Tags</h3>
          </div>
          <div className="p-4">
            <div className="flex flex-wrap gap-2">
              {Object.entries(row.original.request_tags).map(([key, value]) => (
                <span key={key} className="px-2 py-1 bg-gray-100 rounded-full text-xs">
                  {key}: {String(value)}
                </span>
              ))}
            </div>
          </div>
        </div>
      )}

      {/* Metadata Card - Only show if there's metadata */}
      {row.original.metadata && Object.keys(row.original.metadata).length > 0 && (
        <div className="bg-white rounded-lg shadow">
          <div className="flex justify-between items-center p-4 border-b">
            <h3 className="text-lg font-medium">Metadata</h3>
            <button
              onClick={() => {
                navigator.clipboard.writeText(JSON.stringify(row.original.metadata, null, 2));
              }}
              className="p-1 hover:bg-gray-200 rounded"
              title="Copy metadata"
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="16"
                height="16"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
                <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
              </svg>
            </button>
          </div>
          <div className="p-4 overflow-auto max-h-64">
            <pre className="text-xs font-mono whitespace-pre-wrap break-all">
              {JSON.stringify(row.original.metadata, null, 2)}
            </pre>
          </div>
        </div>
      )}
    </div>
  );
}
