import React from 'react';
import { __ } from '@wordpress/i18n';
import Icon from '../icons/Icon';
import { Skeleton } from './display';

/**
 * Data table with sortable headers, optional row selection and a responsive
 * card layout below 768px.
 *
 * columns: [{ key, header, render?(row), sortable?, align?, primary?, width?, className? }]
 * sort:    { key, dir: 'asc'|'desc' }
 */
export default function DataTable({
	columns,
	rows,
	rowKey = (r) => r.id,
	sort,
	onSortChange,
	selectable = false,
	selected = [],
	onSelectedChange,
	onRowClick,
	loading = false,
	skeletonRows = 6,
	empty = null,
	caption,
	stickyHeader = true,
}) {
	const allKeys = rows.map(rowKey);
	const allSelected = selectable && rows.length > 0 && allKeys.every((k) => selected.includes(k));
	const someSelected = selectable && !allSelected && allKeys.some((k) => selected.includes(k));

	const toggleAll = () => {
		if (!onSelectedChange) return;
		onSelectedChange(allSelected ? selected.filter((k) => !allKeys.includes(k)) : Array.from(new Set([...selected, ...allKeys])));
	};
	const toggleOne = (k) => {
		if (!onSelectedChange) return;
		onSelectedChange(selected.includes(k) ? selected.filter((x) => x !== k) : [...selected, k]);
	};

	const headerCell = (col) => {
		const isSorted = sort && sort.key === col.key;
		const ariaSort = isSorted ? (sort.dir === 'asc' ? 'ascending' : 'descending') : col.sortable ? 'none' : undefined;
		const cls = [col.align === 'end' ? 'bp-col-num' : '', col.className || ''].filter(Boolean).join(' ') || undefined;
		return (
			<th key={col.key} scope="col" aria-sort={ariaSort} className={cls} style={col.width ? { width: col.width } : undefined}>
				{col.sortable && onSortChange ? (
					<button
						type="button"
						className="bp-sort"
						onClick={() => onSortChange({ key: col.key, dir: isSorted && sort.dir === 'asc' ? 'desc' : 'asc' })}
					>
						{col.header}
						<Icon name={isSorted ? (sort.dir === 'asc' ? 'chevron-up' : 'chevron-down') : 'chevrons-up-down'} />
					</button>
				) : (
					col.header
				)}
			</th>
		);
	};

	return (
		<div className="bp-table-wrap" style={stickyHeader ? undefined : { overflow: 'visible' }}>
			<table className="bp-table bp-table--responsive">
				{caption ? <caption className="bp-visually-hidden">{caption}</caption> : null}
				<thead>
					<tr>
						{selectable ? (
							<th scope="col" className="bp-col-check">
								<input
									type="checkbox"
									className="bp-check__input"
									aria-label={__('Select all', 'pointly-booking')}
									checked={allSelected}
									ref={(el) => {
										if (el) el.indeterminate = someSelected;
									}}
									onChange={toggleAll}
								/>
							</th>
						) : null}
						{columns.map(headerCell)}
					</tr>
				</thead>
				<tbody aria-busy={loading ? 'true' : undefined}>
					{loading
						? Array.from({ length: skeletonRows }).map((_, i) => (
								<tr key={`sk-${i}`} aria-hidden="true">
									{selectable ? (
										<td className="bp-col-check">
											<Skeleton width={16} height={16} />
										</td>
									) : null}
									{columns.map((c, ci) => (
										<td key={c.key} data-label="">
											<Skeleton width={ci === 0 ? '70%' : `${40 + ((i + ci) % 4) * 12}%`} />
										</td>
									))}
								</tr>
						  ))
						: rows.map((row) => {
								const k = rowKey(row);
								const isSel = selected.includes(k);
								return (
									<tr
										key={k}
										className={[isSel ? 'is-selected' : '', onRowClick ? 'is-clickable' : ''].filter(Boolean).join(' ') || undefined}
										onClick={
											onRowClick
												? (e) => {
														if (e.target.closest('button, a, input, label, select, [role="menu"]')) return;
														onRowClick(row);
												  }
												: undefined
										}
									>
										{selectable ? (
											<td className="bp-col-check">
												<input
													type="checkbox"
													className="bp-check__input"
													aria-label={__('Select row', 'pointly-booking')}
													checked={isSel}
													onChange={() => toggleOne(k)}
												/>
											</td>
										) : null}
										{columns.map((c) => (
											<td
												key={c.key}
												data-label={c.primary || c.hideLabel || c.key === 'actions' ? '' : typeof c.header === 'string' ? c.header : ''}
												className={[
													c.primary ? 'bp-col-primary' : '',
													c.key === 'actions' ? 'bp-col-actions' : '',
													c.align === 'end' ? 'bp-col-num' : '',
													c.className || '',
												]
													.filter(Boolean)
													.join(' ') || undefined}
											>
												{c.render ? c.render(row) : row[c.key]}
											</td>
										))}
									</tr>
								);
						  })}
				</tbody>
			</table>
			{!loading && rows.length === 0 ? empty : null}
		</div>
	);
}
