import { ReactNode, useMemo, useState } from 'react';
import { Card } from '@heroui/react';
import { ChevronUpIcon, ChevronDownIcon } from '@heroicons/react/24/solid';

export interface Column<T> {
    header: string;
    cell: (row: T) => ReactNode;
    sortKey?: (row: T) => string | number | null;
}

interface DataTableProps<T> {
    columns: Column<T>[];
    rows: T[];
    rowKey: (row: T) => string | number;
    isLoading?: boolean;
    emptyText?: string;
    onRowClick?: (row: T) => void;
    className?: string;
    dense?: boolean;
}

// ponytail: plain <table> instead of HeroUI's react-aria dynamic Table -
// avoids per-entity collection boilerplate across 8 tables; sorting is
// client-side over the already-fetched rows.
export function DataTable<T>({ columns, rows, rowKey, isLoading, emptyText = 'Tidak ada data', onRowClick, className = '', dense = false }: DataTableProps<T>) {
    const [sort, setSort] = useState<{ header: string; dir: 'asc' | 'desc' } | null>(null);

    const sortedRows = useMemo(() => {
        if (!sort) return rows;
        const col = columns.find((c) => c.header === sort.header);
        if (!col?.sortKey) return rows;

        return [...rows].sort((a, b) => {
            const av = col.sortKey!(a);
            const bv = col.sortKey!(b);
            if (av == null && bv == null) return 0;
            if (av == null) return 1;
            if (bv == null) return -1;
            const cmp = typeof av === 'number' && typeof bv === 'number' ? av - bv : String(av).localeCompare(String(bv));
            return sort.dir === 'asc' ? cmp : -cmp;
        });
    }, [rows, sort, columns]);

    function toggleSort(col: Column<T>) {
        if (!col.sortKey) return;
        setSort((s) => {
            if (s?.header !== col.header) return { header: col.header, dir: 'asc' };
            if (s.dir === 'asc') return { header: col.header, dir: 'desc' };
            return null;
        });
    }

    if (isLoading) {
        return (
            <div className={`rounded-xl border border-gray-200 bg-white px-4 py-8 text-center text-sm text-gray-400 ${className}`}>
                Memuat...
            </div>
        );
    }

    if (sortedRows.length === 0) {
        return (
            <div className={`rounded-xl border border-gray-200 bg-white px-4 py-8 text-center text-sm text-gray-400 ${className}`}>
                {emptyText}
            </div>
        );
    }

    // ponytail: two renderings of the same rows (cards below sm, table from sm up) -
    // simplest way to avoid a horizontally-scrolling table on phones.
    return (
        <>
            <div className={`flex flex-col gap-2 sm:hidden ${className}`}>
                {sortedRows.map((row) => {
                    const actionCol = columns.find((c) => c.header === 'Aksi');
                    const infoCols = columns.filter((c) => c.header !== 'Aksi');
                    return (
                        <Card
                            key={rowKey(row)}
                            onClick={() => onRowClick?.(row)}
                            className={`p-3 ${onRowClick ? 'cursor-pointer active:bg-gray-50' : ''}`}
                        >
                            <div className="flex flex-col gap-1.5">
                                {infoCols.map((col) => (
                                    <div key={col.header} className="flex items-start justify-between gap-3 text-sm">
                                        <span className="shrink-0 text-xs font-medium uppercase tracking-wide text-gray-400 pt-0.5">{col.header}</span>
                                        <span className="text-right text-gray-700">{col.cell(row)}</span>
                                    </div>
                                ))}
                            </div>
                            {actionCol && (
                                <div onClick={(e) => e.stopPropagation()} className="mt-2 flex justify-end border-t border-gray-100 pt-2">
                                    {actionCol.cell(row)}
                                </div>
                            )}
                        </Card>
                    );
                })}
            </div>

            <div className="hidden sm:block overflow-x-auto rounded-xl border border-gray-200 bg-white">
                <table className="w-full text-sm">
                    <thead>
                        <tr className="bg-gray-50 border-b border-gray-200">
                            {columns.map((col) => (
                                <th
                                    key={col.header}
                                    onClick={() => toggleSort(col)}
                                    className={`text-left ${dense ? 'px-2 py-2 text-[11px]' : 'px-3 py-2 text-xs'} font-medium text-gray-500 uppercase tracking-wider whitespace-nowrap ${col.sortKey ? 'cursor-pointer select-none hover:text-gray-700' : ''}`}
                                >
                                    <span className="inline-flex items-center gap-1">
                                        {col.header}
                                        {col.sortKey && sort?.header === col.header && (
                                            sort.dir === 'asc' ? <ChevronUpIcon className="w-3 h-3" /> : <ChevronDownIcon className="w-3 h-3" />
                                        )}
                                    </span>
                                </th>
                            ))}
                        </tr>
                    </thead>
                    <tbody>
                        {sortedRows.map((row) => (
                            <tr
                                key={rowKey(row)}
                                onClick={() => onRowClick?.(row)}
                                className={`border-b border-gray-100 last:border-0 hover:bg-gray-50 ${onRowClick ? 'cursor-pointer' : ''}`}
                            >
                                {columns.map((col) => (
                                    <td
                                        key={col.header}
                                        onClick={col.header === 'Aksi' ? (e) => e.stopPropagation() : undefined}
                                        className={`${dense ? 'px-2 py-1.5 text-xs' : 'px-3 py-2 text-sm'} text-gray-700 whitespace-nowrap`}
                                    >
                                        {col.cell(row)}
                                    </td>
                                ))}
                            </tr>
                        ))}
                    </tbody>
                </table>
            </div>
        </>
    );
}
