import React, { useState, useEffect, useRef } from "react";
import { DataTable } from "primereact/datatable";
import { InputText } from "primereact/inputtext";
import { Button } from "primereact/button";
import axios from "axios";

/**
 * Reusable Server-Side DataTable Component with Pagination and Search
 * 
 * @param {Object} props
 * @param {string} props.fetchUrl - API endpoint URL for fetching data
 * @param {React.ReactNode} props.children - Column components to render
 * @param {string} props.emptyMessage - Message to show when no data
 * @param {Function} props.headerActions - Optional function to render custom header actions (receives { search, setSearch, fetchData })
 * @param {string} props.dataKey - Unique key for each row (default: "id")
 * @param {number} props.defaultRows - Default rows per page (default: 10)
 * @param {string} props.className - Additional CSS classes for DataTable
 * @param {Object} props.extraParams - Additional parameters to send with fetch request
 * @param {Function} props.onDataChange - Callback when data changes (receives data array)
 */
function ServerSideDataTable({
  fetchUrl,
  children,
  emptyMessage = "No records found.",
  headerActions,
  dataKey = "id",
  defaultRows = 10,
  className = "defulattable",
  extraParams = {},
  onDataChange,
}) {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);
  const [search, setSearch] = useState("");
  const [lazyParams, setLazyParams] = useState({
    first: 0,
    rows: defaultRows,
    // We keep `page` as 1-based for the API.
    page: 1,
    search: "",
  });
  const [totalRecords, setTotalRecords] = useState(0);
  const searchTimeoutRef = useRef(null);

  const fetchData = (params = lazyParams) => {
    setLoading(true);
    axios
      .get(fetchUrl, {
        params: {
          // `page` here is already 1-based (we normalize in onPage / search).
          page: params.page,
          perPage: params.rows,
          search: params.search,
          ...extraParams,
        },
      })
      .then((response) => {
        // Handle different response structures
        const responseData = response.data;
        let items = [];
        let total = 0;

        // Check if response has pagination structure (Laravel paginate)
        // Handle quotation response structure: { quotation: { data: [], total: 100 } }
        if (responseData.quotation) {
          if (responseData.quotation.data && Array.isArray(responseData.quotation.data)) {
            items = responseData.quotation.data;
            total = responseData.quotation.total || 0;
          } else if (Array.isArray(responseData.quotation)) {
            items = responseData.quotation;
            total = responseData.quotation.length;
          }
        }
        // Handle requisition response structure: { requsition: { data: [], total: 100 } }
        else if (responseData.requsition) {
          if (responseData.requsition.data && Array.isArray(responseData.requsition.data)) {
            items = responseData.requsition.data;
            total = responseData.requsition.total || 0;
          } else if (Array.isArray(responseData.requsition)) {
            items = responseData.requsition;
            total = responseData.requsition.length;
          }
        }
        // Handle workOrder response structure: { workOrder: { data: [], total: 100 } }
        else if (responseData.workOrder) {
          if (responseData.workOrder.data && Array.isArray(responseData.workOrder.data)) {
            items = responseData.workOrder.data;
            total = responseData.workOrder.total || 0;
          } else if (Array.isArray(responseData.workOrder)) {
            items = responseData.workOrder;
            total = responseData.workOrder.length;
          }
        }
        // Handle adjustments response structure: { adjustments: { data: [], total: 100 } }
        else if (responseData.adjustments) {
          if (responseData.adjustments.data && Array.isArray(responseData.adjustments.data)) {
            items = responseData.adjustments.data;
            total = responseData.adjustments.total || 0;
          } else if (Array.isArray(responseData.adjustments)) {
            items = responseData.adjustments;
            total = responseData.adjustments.length;
          }
        }
        // Handle usedProducts response structure: { usedProducts: { data: [], total: 100 } }
        else if (responseData.usedProducts) {
          if (responseData.usedProducts.data && Array.isArray(responseData.usedProducts.data)) {
            items = responseData.usedProducts.data;
            total = responseData.usedProducts.total || 0;
          } else if (Array.isArray(responseData.usedProducts)) {
            items = responseData.usedProducts;
            total = responseData.usedProducts.length;
          }
        }
        // Handle purchases response structure: { purchases: { data: [], total: 100 } }
        else if (responseData.purchases) {
          if (responseData.purchases.data && Array.isArray(responseData.purchases.data)) {
            items = responseData.purchases.data;
            total = responseData.purchases.total || 0;
          } else if (Array.isArray(responseData.purchases)) {
            items = responseData.purchases;
            total = responseData.purchases.length;
          }
        }
        // Handle mergeList response structure: { mergeList: { data: [], total: 100 } }
        else if (responseData.mergeList) {
          if (responseData.mergeList.data && Array.isArray(responseData.mergeList.data)) {
            items = responseData.mergeList.data;
            total = responseData.mergeList.total || 0;
          } else if (Array.isArray(responseData.mergeList)) {
            items = responseData.mergeList;
            total = responseData.mergeList.length;
          }
        }
        // Standard Laravel pagination: { data: [], total: 100 }
        else if (responseData.data && Array.isArray(responseData.data)) {
          items = responseData.data;
          total = responseData.total || responseData.totalRecords || 0;
        }
        // Direct array response
        else if (Array.isArray(responseData)) {
          items = responseData;
          total = responseData.length;
        }
        // Try to find common data keys
        else {
          const dataKey = Object.keys(responseData).find(
            (key) => Array.isArray(responseData[key])
          );
          if (dataKey) {
            const dataArray = responseData[dataKey];
            if (Array.isArray(dataArray)) {
              items = dataArray;
              // Try to find total in parent or sibling keys
              total = responseData.total || responseData.totalRecords ||
                (responseData[dataKey] && responseData[dataKey].total) ||
                items.length;
            }
          }
        }

        setData(items);
        setTotalRecords(total);
        setLoading(false);

        // Call onDataChange callback if provided
        if (onDataChange) {
          onDataChange(items);
        }
      })
      .catch((error) => {
        console.error("Error fetching data:", error);
        console.error("Error response:", error.response);
        setData([]);
        setTotalRecords(0);
        setLoading(false);
      });
  };

  useEffect(() => {
    fetchData(lazyParams);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Handle page change and sorting
  const onPage = (event) => {
    // PrimeReact's `event.page` is 0-based; convert to 1-based for the API.
    const updatedParams = {
      ...lazyParams,
      ...event,
      page: (event.page ?? 0) + 1,
    };
    setLazyParams(updatedParams);
    fetchData(updatedParams);
  };

  // Handle search with debounce
  const handleSearchChange = (value) => {
    setSearch(value);

    // Clear existing timeout
    if (searchTimeoutRef.current) {
      clearTimeout(searchTimeoutRef.current);
    }

    // Debounce search to avoid too many requests
    searchTimeoutRef.current = setTimeout(() => {
      const params = {
        ...lazyParams,
        search: value,
        page: 1,
        first: 0,
      };
      setLazyParams(params);
      fetchData(params);
    }, 500);
  };

  // Default header with search
  const defaultHeader = () => {
    return (
      <div className="w-100% flex justify-between">
        {headerActions ? (
          headerActions({ search, setSearch: handleSearchChange, fetchData: () => fetchData(lazyParams) })
        ) : (
          <span className="p-input-icon-left h-10">
            <i className="pi pi-search" />
            <InputText
              className="h-[41px] w-48"
              placeholder="Search"
              value={search}
              onChange={(e) => handleSearchChange(e.target.value)}
            />
          </span>
        )}
      </div>
    );
  };

  return (
    <DataTable
      className={className}
      value={data}
      lazy
      paginator
      first={lazyParams.first}
      rows={lazyParams.rows}
      totalRecords={totalRecords}
      onPage={onPage}
      loading={loading}
      showGridlines
      dataKey={dataKey}
      header={defaultHeader}
      emptyMessage={emptyMessage}
      paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
      rowsPerPageOptions={[10, 25, 50, 100]}
    >
      {children}
    </DataTable>
  );
}

export default ServerSideDataTable;

