'use client';
import {
  useEffect,
  useState,
  useCallback,
  Ref,
  useImperativeHandle,
} from 'react';
import SortableTable, { Pagination, SortableTableProps } from './Table';
import { PrismaClient } from '@repo/db';
import { getData } from './pagiantedTableActions';

export interface PaginatedTableRef {
  refresh: () => void;
}

interface PaginatedTableProps<TData>
  extends Omit<SortableTableProps<TData>, 'data'> {
  prismaModel: keyof PrismaClient;
  filter?: Record<string, any>;
  rowsPerPage?: number;
  showEditButton?: boolean;
  searchFields?: string[];
  include?: Record<string, boolean>;
  leftOfSearch?: React.ReactNode;
  rightOfSearch?: React.ReactNode;
  ref?: Ref<PaginatedTableRef>;
}

export function PaginatedTable<TData>({
  prismaModel,
  rowsPerPage = 10,
  showEditButton = false,
  searchFields = [],
  filter,
  include,
  ref,
  leftOfSearch,
  rightOfSearch,
  ...restProps
}: PaginatedTableProps<TData>) {
  const [data, setData] = useState<TData[]>([]);
  const [page, setPage] = useState(0);
  const [total, setTotal] = useState(0);
  const [searchTerm, setSearchTerm] = useState('');
  const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(searchTerm);

  const RefreshTableData = async () => {
    getData(
      prismaModel,
      rowsPerPage,
      page * rowsPerPage,
      debouncedSearchTerm,
      searchFields,
      filter,
      include
    ).then((result) => {
      if (result) {
        setData(result.data);
        setTotal(result.total);
      }
    });
  };

  useImperativeHandle(ref, () => ({
    refresh: () => {
      console.log('refresh');
      RefreshTableData();
    },
  }));

  const debounce = (func: Function, delay: number) => {
    let timer: NodeJS.Timeout;
    return (...args: any[]) => {
      clearTimeout(timer);
      timer = setTimeout(() => func(...args), delay);
    };
  };

  const handleSearchChange = useCallback(
    debounce((value: string) => {
      setDebouncedSearchTerm(value);
    }, 500),
    []
  );

  useEffect(() => {
    RefreshTableData();
  }, [page, debouncedSearchTerm]);

  return (
    <div className="space-y-4 m-4">
      <div className="flex items-center  gap-2">
        <div className="flex-1">{leftOfSearch}</div>
        {searchFields.length > 0 && (
          <input
            type="text"
            placeholder="Suchen..."
            value={searchTerm}
            onChange={(e) => {
              setSearchTerm(e.target.value);
              handleSearchChange(e.target.value);
            }}
            className="input input-bordered w-full max-w-xs justify-end"
          />
        )}
        <div className="flex justify-center">{rightOfSearch}</div>
      </div>
      <SortableTable
        data={data}
        prismaModel={prismaModel}
        showEditButton={showEditButton}
        {...restProps}
      />
      <Pagination
        totalPages={Math.ceil(total / rowsPerPage)}
        page={page}
        setPage={setPage}
      />
    </div>
  );
}
