import React, { forwardRef, useState, useMemo } from "react";
import { BaseComponentProps } from "../../types";
import { Button } from "../ui/Button";
import { Input } from "../ui/Input";

export interface TableColumn<T = Record<string, unknown>> {
  key: string;
  label: string;
  sortable?: boolean;
  filterable?: boolean;
  render?: (value: unknown, row: T) => React.ReactNode;
  width?: string;
}

export interface DataTableProps<T = Record<string, unknown>>
  extends BaseComponentProps {
  data: T[];
  columns: TableColumn<T>[];
  loading?: boolean;
  pagination?: {
    page: number;
    pageSize: number;
    total: number;
    onPageChange: (page: number) => void;
    onPageSizeChange: (pageSize: number) => void;
  };
  searchable?: boolean;
  onSearch?: (query: string) => void;
  emptyMessage?: string;
  variant?: "default" | "striped";
}

export const DataTable = forwardRef<HTMLDivElement, DataTableProps>(
  (
    {
      className = "",
      data,
      columns,
      loading = false,
      pagination,
      searchable = false,
      onSearch,
      emptyMessage = "No data available",
      variant = "default",
      ...props
    },
    ref
  ) => {
    const [sortConfig, setSortConfig] = useState<{
      key: string;
      direction: "asc" | "desc";
    } | null>(null);
    const [searchQuery, setSearchQuery] = useState("");

    const sortedData = useMemo(() => {
      if (!sortConfig) return data;

      return [...data].sort((a, b) => {
        const aValue = (a as Record<string, unknown>)[sortConfig.key];
        const bValue = (b as Record<string, unknown>)[sortConfig.key];

        // Safe comparison for unknown types
        const aStr = aValue?.toString() ?? "";
        const bStr = bValue?.toString() ?? "";

        if (aStr < bStr) {
          return sortConfig.direction === "asc" ? -1 : 1;
        }
        if (aStr > bStr) {
          return sortConfig.direction === "asc" ? 1 : -1;
        }
        return 0;
      });
    }, [data, sortConfig]);

    const handleSort = (columnKey: string) => {
      const column = columns.find((col) => col.key === columnKey);
      if (!column?.sortable) return;

      setSortConfig((current) => {
        if (current?.key === columnKey) {
          return current.direction === "asc"
            ? { key: columnKey, direction: "desc" }
            : null;
        }
        return { key: columnKey, direction: "asc" };
      });
    };

    const handleSearch = (query: string) => {
      setSearchQuery(query);
      onSearch?.(query);
    };

    const getSortIcon = (columnKey: string) => {
      if (sortConfig?.key !== columnKey) {
        return (
          <svg
            className="w-4 h-4 text-gray-400"
            fill="none"
            stroke="currentColor"
            viewBox="0 0 24 24"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4"
            />
          </svg>
        );
      }

      return sortConfig.direction === "asc" ? (
        <svg
          className="w-4 h-4 text-primary-600"
          fill="none"
          stroke="currentColor"
          viewBox="0 0 24 24"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M5 15l7-7 7 7"
          />
        </svg>
      ) : (
        <svg
          className="w-4 h-4 text-primary-600"
          fill="none"
          stroke="currentColor"
          viewBox="0 0 24 24"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M19 9l-7 7-7-7"
          />
        </svg>
      );
    };

    const renderLoadingSkeleton = () => (
      <div className="animate-pulse">
        {Array.from({ length: 5 }).map((_, index) => (
          <tr
            key={index}
            className="border-b border-gray-200 dark:border-gray-700"
          >
            {columns.map((column) => (
              <td key={column.key} className="px-6 py-4">
                <div className="h-4 bg-gray-200 rounded"></div>
              </td>
            ))}
          </tr>
        ))}
      </div>
    );

    return (
      <div
        ref={ref}
        className={`bg-white dark:bg-gray-800 shadow-sm rounded-lg border border-gray-200 dark:border-gray-700 ${className}`}
        {...props}
      >
        {/* Search */}
        {searchable && (
          <div className="p-4 border-b border-gray-200 dark:border-gray-700">
            <Input
              placeholder="Search..."
              value={searchQuery}
              onChange={(e) => handleSearch(e.target.value)}
              className="max-w-sm"
            />
          </div>
        )}

        {/* Table */}
        <div className="overflow-x-auto">
          <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
            <thead className="bg-gray-50 dark:bg-gray-700">
              <tr>
                {columns.map((column) => (
                  <th
                    key={column.key}
                    className={`px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider ${
                      column.sortable
                        ? "cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-600"
                        : ""
                    }`}
                    style={{ width: column.width }}
                    onClick={() => handleSort(column.key)}
                  >
                    <div className="flex items-center space-x-1">
                      <span>{column.label}</span>
                      {column.sortable && getSortIcon(column.key)}
                    </div>
                  </th>
                ))}
              </tr>
            </thead>
            <tbody
              className={`bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700 ${
                variant === "striped" ? "divide-y-0" : ""
              }`}
            >
              {loading && renderLoadingSkeleton()}

              {!loading && sortedData.length === 0 && (
                <tr>
                  <td
                    colSpan={columns.length}
                    className="px-6 py-12 text-center text-gray-500 dark:text-gray-400"
                  >
                    {emptyMessage}
                  </td>
                </tr>
              )}

              {!loading &&
                sortedData.map((row, rowIndex) => (
                  <tr
                    key={rowIndex}
                    className={
                      variant === "striped"
                        ? rowIndex % 2 === 0
                          ? "bg-white dark:bg-gray-800"
                          : "bg-gray-50 dark:bg-gray-700"
                        : "hover:bg-gray-50 dark:hover:bg-gray-700"
                    }
                  >
                    {columns.map((column) => (
                      <td
                        key={column.key}
                        className="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-gray-100"
                      >
                        {column.render
                          ? column.render(
                              (row as Record<string, unknown>)[column.key],
                              row
                            )
                          : String(
                              (row as Record<string, unknown>)[column.key] ?? ""
                            )}
                      </td>
                    ))}
                  </tr>
                ))}
            </tbody>
          </table>
        </div>

        {/* Pagination */}
        {pagination && (
          <div className="px-6 py-3 bg-gray-50 dark:bg-gray-700 border-t border-gray-200 dark:border-gray-600 flex items-center justify-between">
            <div className="flex items-center space-x-2">
              <span className="text-sm text-gray-700 dark:text-gray-300">
                Showing {(pagination.page - 1) * pagination.pageSize + 1} to{" "}
                {Math.min(
                  pagination.page * pagination.pageSize,
                  pagination.total
                )}{" "}
                of {pagination.total} results
              </span>
            </div>

            <div className="flex items-center space-x-2">
              <Button
                variant="outline"
                size="sm"
                disabled={pagination.page <= 1}
                onClick={() => pagination.onPageChange(pagination.page - 1)}
              >
                Previous
              </Button>

              <span className="text-sm text-gray-700 dark:text-gray-300">
                Page {pagination.page} of{" "}
                {Math.ceil(pagination.total / pagination.pageSize)}
              </span>

              <Button
                variant="outline"
                size="sm"
                disabled={
                  pagination.page >=
                  Math.ceil(pagination.total / pagination.pageSize)
                }
                onClick={() => pagination.onPageChange(pagination.page + 1)}
              >
                Next
              </Button>
            </div>
          </div>
        )}
      </div>
    );
  }
);

DataTable.displayName = "DataTable";
