import { useState, useCallback, useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';
import { graphqlClient } from '@/api/client';
import type { SorterResult, TablePaginationConfig } from 'antd/es/table/interface';
import type { FilterValue } from 'antd/es/table/interface';

interface UseDataTableOptions {
  queryKey: string[];
  query: string;
  variables?: Record<string, unknown>;
  dataPath: string;
  totalPath: string;
  pageSize?: number;
  enabled?: boolean;
}

interface UseDataTableReturn<T> {
  data: T[];
  total: number;
  isLoading: boolean;
  isError: boolean;
  error: Error | null;
  pagination: TablePaginationConfig;
  handleTableChange: (
    pagination: TablePaginationConfig,
    filters: Record<string, FilterValue | null>,
    sorter: SorterResult<T> | SorterResult<T>[]
  ) => void;
  refetch: () => void;
  currentPage: number;
  currentPageSize: number;
  sortField: string | undefined;
  sortOrder: 'asc' | 'desc' | undefined;
  filters: Record<string, unknown>;
  setFilters: (filters: Record<string, unknown>) => void;
}

function getNestedValue(obj: unknown, path: string): unknown {
  return path.split('.').reduce((acc: unknown, part: string) => {
    if (acc && typeof acc === 'object' && part in acc) {
      return (acc as Record<string, unknown>)[part];
    }
    return undefined;
  }, obj);
}

export function useDataTable<T extends { id: string }>({
  queryKey,
  query,
  variables = {},
  dataPath,
  totalPath,
  pageSize = 20,
  enabled = true,
}: UseDataTableOptions): UseDataTableReturn<T> {
  const [currentPage, setCurrentPage] = useState(1);
  const [currentPageSize, setCurrentPageSize] = useState(pageSize);
  const [sortField, setSortField] = useState<string | undefined>();
  const [sortOrder, setSortOrder] = useState<'asc' | 'desc' | undefined>();
  const [filters, setFilters] = useState<Record<string, unknown>>({});

  // Build query variables with pagination, sorting, and filtering
  const queryVariables = useMemo(() => {
    const vars: Record<string, unknown> = {
      ...variables,
      first: currentPageSize,
      after: currentPage > 1 ? String((currentPage - 1) * currentPageSize) : undefined,
    };

    if (sortField && sortOrder) {
      vars.sort = {
        field: sortField,
        direction: sortOrder.toUpperCase(),
      };
    }

    if (Object.keys(filters).length > 0) {
      vars.filter = filters;
    }

    return vars;
  }, [variables, currentPage, currentPageSize, sortField, sortOrder, filters]);

  // Execute GraphQL query
  const { data: response, isLoading, isError, error, refetch } = useQuery({
    queryKey: [...queryKey, queryVariables],
    queryFn: async () => {
      return graphqlClient.request(query, queryVariables);
    },
    enabled,
  });

  // Extract data and total from response
  const data = useMemo(() => {
    if (!response) return [];
    const items = getNestedValue(response, dataPath);
    return Array.isArray(items) ? items : [];
  }, [response, dataPath]) as T[];

  const total = useMemo(() => {
    if (!response) return 0;
    const count = getNestedValue(response, totalPath);
    return typeof count === 'number' ? count : 0;
  }, [response, totalPath]);

  // Pagination config for Ant Design Table
  const pagination: TablePaginationConfig = useMemo(
    () => ({
      current: currentPage,
      pageSize: currentPageSize,
      total,
      showSizeChanger: true,
      showQuickJumper: true,
      pageSizeOptions: ['10', '20', '50', '100'],
      showTotal: (total, range) =>
        `${range[0]}-${range[1]} af ${total} poster`,
    }),
    [currentPage, currentPageSize, total]
  );

  // Handle table changes (pagination, sorting, filtering)
  const handleTableChange = useCallback(
    (
      newPagination: TablePaginationConfig,
      tableFilters: Record<string, FilterValue | null>,
      sorter: SorterResult<T> | SorterResult<T>[]
    ) => {
      // Handle pagination
      if (newPagination.current !== currentPage) {
        setCurrentPage(newPagination.current || 1);
      }
      if (newPagination.pageSize !== currentPageSize) {
        setCurrentPageSize(newPagination.pageSize || pageSize);
        setCurrentPage(1); // Reset to first page on page size change
      }

      // Handle sorting
      const singleSorter = Array.isArray(sorter) ? sorter[0] : sorter;
      if (singleSorter.field && singleSorter.order) {
        setSortField(String(singleSorter.field));
        setSortOrder(singleSorter.order === 'ascend' ? 'asc' : 'desc');
      } else {
        setSortField(undefined);
        setSortOrder(undefined);
      }

      // Handle filters from table columns
      const newFilters: Record<string, unknown> = {};
      Object.entries(tableFilters).forEach(([key, value]) => {
        if (value !== null && value.length > 0) {
          newFilters[key] = value.length === 1 ? value[0] : value;
        }
      });
      // Merge with existing external filters
      setFilters((prev) => ({ ...prev, ...newFilters }));
    },
    [currentPage, currentPageSize, pageSize]
  );

  return {
    data,
    total,
    isLoading,
    isError,
    error: error as Error | null,
    pagination,
    handleTableChange,
    refetch,
    currentPage,
    currentPageSize,
    sortField,
    sortOrder,
    filters,
    setFilters,
  };
}
