"use client";

import { useEffect, useMemo, useState } from "react";
import {
  DataGrid,
  GridColDef,
  GridPaginationModel,
  GridSortModel,
} from "@mui/x-data-grid";
import { getAudits } from "@/app/services/audits";
import "./page.scss";

type AuditRow = Record<string, unknown> & { id: string | number };

interface AuditApiResponse {
  total?: number;
  limit?: number;
  page?: number;
  data?: unknown;
  items?: unknown[];
  audits?: unknown[];
  logs?: unknown[];
  results?: unknown[];
  records?: unknown[];
  meta?: { total?: number };
  pagination?: { total?: number };
}

const DEFAULT_PAGE_SIZE = 25;

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

const CANDIDATE_ARRAY_KEYS: (keyof AuditApiResponse)[] = [
  "items",
  "audits",
  "logs",
  "results",
  "records",
];

const normalizeValue = (value: unknown): string | number => {
  if (value === null || value === undefined) {
    return "";
  }

  if (typeof value === "string" || typeof value === "number") {
    return value;
  }

  if (typeof value === "boolean") {
    return value ? "true" : "false";
  }

  return JSON.stringify(value);
};

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,
  }));
};

const extractArray = (payload: AuditApiResponse): unknown[] => {
  if (Array.isArray(payload)) {
    return payload;
  }

  for (const key of CANDIDATE_ARRAY_KEYS) {
    const candidate = payload[key];
    if (Array.isArray(candidate)) {
      return candidate;
    }
  }

  const dataRecord =
    payload.data &&
    typeof payload.data === "object" &&
    !Array.isArray(payload.data)
      ? (payload.data as Record<string, unknown>)
      : null;

  if (dataRecord) {
    for (const key of CANDIDATE_ARRAY_KEYS) {
      const candidate = dataRecord[key];
      if (Array.isArray(candidate)) {
        return candidate;
      }
    }
  }

  if (Array.isArray(payload.data)) {
    return payload.data;
  }

  return [];
};

const resolveTotal = (payload: AuditApiResponse, fallback: number): number => {
  const fromPayload = payload.total;
  const fromMeta = payload.meta?.total;
  const fromPagination = payload.pagination?.total;
  const fromData =
    payload.data &&
    typeof payload.data === "object" &&
    !Array.isArray(payload.data)
      ? (payload.data as { total?: number }).total
      : undefined;

  return (
    (typeof fromPayload === "number" && fromPayload) ||
    (typeof fromMeta === "number" && fromMeta) ||
    (typeof fromPagination === "number" && fromPagination) ||
    (typeof fromData === "number" && fromData) ||
    fallback
  );
};

const normalizeRows = (entries: unknown[], page: number): AuditRow[] =>
  entries.map((entry, index) => {
    if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
      return {
        id: `${page}-${index}`,
        value: normalizeValue(entry),
      };
    }

    const record = entry as Record<string, unknown>;

    const normalized: Record<string, unknown> = {};
    Object.entries(record).forEach(([key, value]) => {
      normalized[key] = normalizeValue(value);
    });

    const identifier =
      record.id ??
      record.audit_id ??
      record.log_id ??
      record._id ??
      `${page}-${index}`;

    return {
      id: (identifier as string | number) ?? `${page}-${index}`,
      ...normalized,
    };
  });

export default function AuditPage() {
  const [rows, setRows] = useState<AuditRow[]>([]);
  const [columns, setColumns] = useState<GridColDef[]>([]);
  const [rowCount, setRowCount] = useState(0);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({
    page: 0,
    pageSize: DEFAULT_PAGE_SIZE,
  });
  const [sortModel, setSortModel] = useState<GridSortModel>([]);

  useEffect(() => {
    const controller = new AbortController();

    const fetchAudits = async () => {
      setLoading(true);
      setError(null);

      const sortParam =
        sortModel.length && sortModel[0].field && sortModel[0].sort
          ? `${sortModel[0].field}:${sortModel[0].sort}`
          : undefined;

      try {
        const payload = (await getAudits({
          limit: paginationModel.pageSize,
          page: paginationModel.page + 1,
          sort: sortParam,
          signal: controller.signal,
        })) as AuditApiResponse;

        const auditEntries = extractArray(payload);
        const normalized = normalizeRows(auditEntries, paginationModel.page);

        setColumns(prev =>
          normalized.length
            ? deriveColumns(normalized)
            : prev.length
              ? prev
              : FALLBACK_COLUMNS
        );

        setRows(normalized);
        setRowCount(resolveTotal(payload, normalized.length));
      } catch (err) {
        if (controller.signal.aborted) return;
        const message =
          err instanceof Error ? err.message : "Failed to load audits";
        setError(message);
        setRows([]);
        setColumns(prev => (prev.length ? prev : FALLBACK_COLUMNS));
      } finally {
        if (!controller.signal.aborted) {
          setLoading(false);
        }
      }
    };

    fetchAudits();

    return () => controller.abort();
  }, [paginationModel, sortModel]);

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

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

  const pageTitle = useMemo(
    () =>
      sortModel.length && sortModel[0].field
        ? `Audit Logs · sorted by ${toTitle(sortModel[0].field)}`
        : "Audit Logs",
    [sortModel]
  );

  return (
    <div className="audits-page">
      <h1 className="page-title">{pageTitle}</h1>
      {error && (
        <div className="error-alert" role="alert">
          {error}
        </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>
  );
}
