"use client";

import { useEffect, useMemo, useState } from "react";
import {
  DataGrid,
  GridColDef,
  GridPaginationModel,
  GridSortModel,
} from "@mui/x-data-grid";
import TextField from "@mui/material/TextField";
import { Box, debounce } from "@mui/material";
import useSWR from "swr";
import { getAudits } from "@/app/services/audits";
import {
  AuditQueryResult,
  AuditRow,
  DEFAULT_PAGE_SIZE,
} from "./auditTransforms";

const FALLBACK_COLUMNS: GridColDef[] = [
  {
    field: "placeholder",
    headerName: "Audit Data",
    flex: 1,
    sortable: false,
    filterable: false,
  },
];

const toTitle = (field: string) =>
  field
    .replace(/_/g, " ")
    .replace(/-/g, " ")
    .replace(/([a-z])([A-Z])/g, "$1 $2")
    .replace(/\s+/g, " ")
    .trim()
    .replace(/^\w/g, char => char.toUpperCase());

const deriveColumns = (rows: AuditRow[]): GridColDef[] => {
  if (!rows.length) return [];

  return Object.keys(rows[0]).map(field => ({
    field,
    headerName: toTitle(field),
    flex: field === "id" ? 0 : 1,
    minWidth: field === "id" ? 140 : 200,
    sortable: true,
  }));
};

interface AuditTableClientProps {
  initialData: AuditQueryResult;
}

const ENTITY_PREFIX = "LIKE/";

const buildSortParam = (sortModel: GridSortModel) =>
  sortModel.length && sortModel[0].field && sortModel[0].sort
    ? `${sortModel[0].field}:${sortModel[0].sort}`
    : undefined;

const buildEntityParam = (entitySearch: string) =>
  entitySearch.trim() ? `${ENTITY_PREFIX}${entitySearch.trim()}` : undefined;

export default function AuditTableClient({
  initialData,
}: AuditTableClientProps) {
  const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({
    page: initialData.pageIndex ?? 0,
    pageSize: DEFAULT_PAGE_SIZE,
  });
  const [sortModel, setSortModel] = useState<GridSortModel>([]);
  const [entitySearch, setEntitySearch] = useState<string>("");
  const [entitySearchInput, setEntitySearchInput] = useState<string>("");

  const [columns, setColumns] = useState<GridColDef[]>(
    initialData.rows.length ? deriveColumns(initialData.rows) : FALLBACK_COLUMNS
  );

  const debouncedSetEntitySearch = useMemo(
    () =>
      debounce((value: string) => {
        setEntitySearch(value);
        setPaginationModel(prev => ({ ...prev, page: 0 }));
      }, 500),
    []
  );

  useEffect(() => {
    return () => {
      debouncedSetEntitySearch.clear();
    };
  }, [debouncedSetEntitySearch]);

  const sortParam = useMemo(() => buildSortParam(sortModel), [sortModel]);
  const entityParam = useMemo(
    () => buildEntityParam(entitySearch),
    [entitySearch]
  );

  const { data, error, isLoading, isValidating } = useSWR(
    [
      "audits",
      paginationModel.page,
      paginationModel.pageSize,
      sortParam ?? "",
      entityParam ?? "",
    ],
    () =>
      getAudits({
        limit: paginationModel.pageSize,
        page: paginationModel.page + 1,
        sort: sortParam,
        entity: entityParam,
      }),
    {
      keepPreviousData: true,
      revalidateOnFocus: true,
      revalidateOnReconnect: true,
      fallbackData: initialData,
    }
  );

  const rows = data?.rows ?? initialData.rows;
  const rowCount = data?.total ?? initialData.total ?? rows.length;
  const loading = isLoading || (isValidating && !rows.length);
  const pageTitle = useMemo(
    () =>
      sortModel.length && sortModel[0].field
        ? `Audit Logs · sorted by ${toTitle(sortModel[0].field)}`
        : "Audit Logs",
    [sortModel]
  );

  useEffect(() => {
    setColumns(prev =>
      rows.length ? deriveColumns(rows) : prev.length ? prev : FALLBACK_COLUMNS
    );
  }, [rows]);

  const handlePaginationChange = (model: GridPaginationModel) => {
    setPaginationModel(model);
  };

  const handleSortModelChange = (model: GridSortModel) => {
    setSortModel(model);
    setPaginationModel(prev => ({ ...prev, page: 0 }));
  };

  const handleEntitySearchChange = (value: string) => {
    setEntitySearchInput(value);
    debouncedSetEntitySearch(value);
  };

  const errorMessage =
    error instanceof Error
      ? error.message
      : error
        ? "Failed to load audits"
        : null;

  return (
    <div className="audits-page">
      <Box sx={{ display: "flex", gap: 2, mt: 5 }}>
        <TextField
          label="Search by Entity"
          variant="outlined"
          size="small"
          value={entitySearchInput}
          onChange={e => handleEntitySearchChange(e.target.value)}
          sx={{ width: 300, backgroundColor: "#f0f0f0" }}
        />
      </Box>
      <h1 className="page-title">{pageTitle}</h1>
      {errorMessage && (
        <div className="error-alert" role="alert">
          {errorMessage}
        </div>
      )}
      <div className="table-container">
        <div className="scroll-wrapper">
          <div
            className="table-inner"
            style={{ minWidth: `${columns.length * 200}px` }}
          >
            <DataGrid
              rows={rows}
              columns={columns.length ? columns : FALLBACK_COLUMNS}
              loading={loading}
              paginationMode="server"
              sortingMode="server"
              paginationModel={paginationModel}
              onPaginationModelChange={handlePaginationChange}
              rowCount={rowCount}
              sortModel={sortModel}
              onSortModelChange={handleSortModelChange}
              pageSizeOptions={[10, 25, 50, 100]}
              disableRowSelectionOnClick
              sx={{
                border: 0,
                minHeight: 500,
                "& .MuiDataGrid-cell": {
                  whiteSpace: "nowrap",
                  overflow: "hidden",
                  textOverflow: "ellipsis",
                },
              }}
            />
          </div>
        </div>
      </div>
    </div>
  );
}
