"use client";

import type { PoWorkbenchListRow } from "@/components/PoWorkbench/types";
import PoWorkbenchSearchResultsListSkeleton from "@/components/PoWorkbench/PoWorkbenchSearchResultsListSkeleton";
import WorkbenchResultSummary from "@/components/PoWorkbench/WorkbenchResultSummary";
import SearchOffOutlinedIcon from "@mui/icons-material/SearchOffOutlined";
import Box from "@mui/material/Box";
import List from "@mui/material/List";
import ListItemButton from "@mui/material/ListItemButton";
import Skeleton from "@mui/material/Skeleton";
import Typography from "@mui/material/Typography";
import { alpha } from "@mui/material/styles";
import type { Theme } from "@mui/material/styles";
import { useCallback, useRef } from "react";
import { useTranslation } from "react-i18next";

const LIST_CONTAINER_SX = {
  position: "absolute",
  inset: 0,
  display: "flex",
  flexDirection: "column",
  overflow: "hidden",
  bgcolor: "background.paper",
} as const;

const LIST_HEADER_SX = {
  flexShrink: 0,
  px: 2,
  pt: 0.5,
  pb: 0.5,
  borderBottom: 1,
  borderColor: "divider",
  bgcolor: "background.paper",
} as const;

const EMPTY_STATE_SX = {
  flex: 1,
  minHeight: 0,
  display: "flex",
  flexDirection: "column",
  alignItems: "center",
  justifyContent: "center",
  px: 3,
  py: 4,
} as const;

const RESULTS_BODY_SX = {
  flex: 1,
  minHeight: 0,
  display: "flex",
  flexDirection: "column",
  bgcolor: "background.paper",
} as const;

const SCROLL_NEAR_BOTTOM_PX = 120;

/**
 * Scroll host: the list; load the next page when the user scrolls near the bottom.
 * Use `overflow-y: scroll` (not `auto`) so a scrollbar track stays visible when content is short;
 * the list still does not scroll until content overflows.
 */
const SCROLL_HOST_SX = {
  flex: 1,
  minHeight: 0,
  height: "100%",
  overflowY: "scroll",
  overflowX: "hidden",
  scrollbarGutter: "stable",
  py: 0,
} as const;

interface ResultListItemProps {
  row: PoWorkbenchListRow;
  selected: boolean;
  onSelect: (id: string) => void;
  theme: Theme;
}

function ResultListItem({
  row,
  selected,
  onSelect,
  theme,
}: ResultListItemProps) {
  const rowSx = {
    m: 0,
    mx: 0,
    borderRadius: 0,
    pt: 1.25,
    pb: 1,
    px: 2,
    borderBottom: 1,
    borderColor: "divider",
    borderLeftStyle: "solid",
    borderLeftWidth: 10,
    borderLeftColor: selected ? "primary.main" : "transparent",
    borderTopLeftRadius: 0,
    borderBottomLeftRadius: 0,
    borderTopRightRadius: 0,
    borderBottomRightRadius: 0,
    bgcolor: selected ? alpha(theme.palette.primary.main, 0.08) : "transparent",
    "&:hover": {
      borderTopRightRadius: 10,
      borderBottomRightRadius: 10,
      bgcolor: selected
        ? alpha(theme.palette.primary.main, 0.12)
        : "action.hover",
    },
    "&.Mui-selected": {
      borderTopRightRadius: 10,
      borderBottomRightRadius: 10,
      bgcolor: alpha(theme.palette.primary.main, 0.08),
      "&:hover": {
        borderTopRightRadius: 10,
        borderBottomRightRadius: 10,
        bgcolor: alpha(theme.palette.primary.main, 0.12),
      },
    },
  } as const;

  return (
    <ListItemButton
      selected={selected}
      onClick={() => onSelect(row.id)}
      alignItems="flex-start"
      sx={rowSx}
    >
      <WorkbenchResultSummary row={row} />
    </ListItemButton>
  );
}

export interface PoWorkbenchSearchResultsListProps {
  results: readonly PoWorkbenchListRow[];
  totalMatches: number;
  isLoading: boolean;
  isLoadingMore: boolean;
  loadError: string | null;
  hasMore: boolean;
  onLoadMore: () => void;
  selectedId: string | null;
  onSelect: (id: string) => void;
  theme: Theme;
}

export default function PoWorkbenchSearchResultsList({
  results,
  totalMatches,
  isLoading,
  isLoadingMore,
  loadError,
  hasMore,
  onLoadMore,
  selectedId,
  onSelect,
  theme,
}: PoWorkbenchSearchResultsListProps) {
  const { t } = useTranslation("poWorkbench");
  const scrollRootRef = useRef<HTMLDivElement | null>(null);

  /**
   * Load the next page when the user scrolls near the bottom.
   * No auto-chaining on first paint (avoids firing many /po/list calls before any scroll).
   */
  const handleScroll = useCallback(
    (e: React.UIEvent<HTMLDivElement>) => {
      if (!hasMore || isLoading || isLoadingMore) {
        return;
      }
      const el = e.currentTarget;
      if (el.scrollTop <= 0) {
        return;
      }
      if (
        el.scrollTop + el.clientHeight >=
        el.scrollHeight - SCROLL_NEAR_BOTTOM_PX
      ) {
        onLoadMore();
      }
    },
    [hasMore, isLoading, isLoadingMore, onLoadMore],
  );

  const showLoadingHeaderOnly = isLoading && results.length === 0;

  return (
    <Box sx={LIST_CONTAINER_SX}>
      <Box sx={LIST_HEADER_SX}>
        {showLoadingHeaderOnly ? (
          <Skeleton
            variant="text"
            width={200}
            height={20}
            sx={{ my: 0.25 }}
            aria-label={t("results.loading")}
          />
        ) : (
          <>
            <Typography
              variant="caption"
              color="text.secondary"
              component="p"
              sx={{ m: 0 }}
            >
              {t("results.totalMatches", { total: totalMatches })}
            </Typography>
          </>
        )}
      </Box>

      {loadError && results.length > 0 ? (
        <Box sx={{ flexShrink: 0, px: 2, py: 0.5, bgcolor: "error.light" }}>
          <Typography variant="caption" color="error.contrastText">
            {loadError}
          </Typography>
        </Box>
      ) : null}

      {isLoading && results.length === 0 ? (
        <Box sx={RESULTS_BODY_SX}>
          <Box
            ref={scrollRootRef}
            onScroll={handleScroll}
            sx={SCROLL_HOST_SX}
            aria-busy="true"
            aria-label={t("results.loading")}
          >
            <PoWorkbenchSearchResultsListSkeleton />
          </Box>
        </Box>
      ) : null}

      {!isLoading && results.length === 0 ? (
        <Box sx={EMPTY_STATE_SX}>
          <SearchOffOutlinedIcon
            sx={{
              fontSize: 88,
              color: (p) => p.palette.grey[400],
            }}
            aria-hidden
          />
          <Typography
            variant="body2"
            component="p"
            sx={{
              mt: 2,
              maxWidth: 320,
              textAlign: "center",
              color: "text.secondary",
              fontWeight: 700,
              lineHeight: 1.6,
            }}
          >
            {loadError ?? t("results.emptyState")}
          </Typography>
        </Box>
      ) : null}

      {results.length > 0 ? (
        <Box sx={RESULTS_BODY_SX}>
          <Box ref={scrollRootRef} onScroll={handleScroll} sx={SCROLL_HOST_SX}>
            <List disablePadding>
              {results.map((row) => (
                <ResultListItem
                  key={row.id}
                  row={row}
                  selected={row.id === selectedId}
                  onSelect={onSelect}
                  theme={theme}
                />
              ))}
            </List>
            {isLoadingMore ? (
              <Box sx={{ display: "flex", justifyContent: "center", py: 1.5 }}>
                <Typography
                  variant="caption"
                  color="text.secondary"
                  component="p"
                  sx={{ m: 0 }}
                >
                  {t("results.loading")}
                </Typography>
              </Box>
            ) : null}
          </Box>
        </Box>
      ) : null}
    </Box>
  );
}
