import {
	createColumnHelper,
	getCoreRowModel,
	getFilteredRowModel,
	getPaginationRowModel,
	useReactTable,
} from "@tanstack/react-table";
import { useMemo } from "react";
import type { AuditLog } from "src/api/backend";
import { EventFormatter, GravatarFormatter } from "src/components";
import { TableLayout } from "src/components/Table/TableLayout";
import { intl, T } from "src/locale";

interface Props {
	data: AuditLog[];
	isFetching?: boolean;
	onSelectItem?: (id: number) => void;
	globalFilter?: string;
}

/**
 * Export filtered rows to CSV and trigger browser download.
 */
function exportCSV(rows: AuditLog[]) {
	const headers = ["ID", "Date", "User", "Object Type", "Action", "Object ID"];
	const escape = (v: string) => `"${String(v ?? "").replace(/"/g, '""')}"`;
	const lines = [
		headers.join(","),
		...rows.map((r) =>
			[
				r.id,
				r.createdOn,
				r.user?.name ?? r.userId,
				r.objectType,
				r.action,
				r.objectId,
			]
				.map(String)
				.map(escape)
				.join(","),
		),
	];
	const blob = new Blob([lines.join("\r\n")], { type: "text/csv;charset=utf-8;" });
	const url = URL.createObjectURL(blob);
	const a = document.createElement("a");
	a.href = url;
	a.download = `audit-log-${new Date().toISOString().slice(0, 10)}.csv`;
	a.click();
	URL.revokeObjectURL(url);
}

export default function Table({ data, isFetching, onSelectItem, globalFilter }: Props) {
	const columnHelper = createColumnHelper<AuditLog>();
	const columns = useMemo(
		() => [
			columnHelper.accessor((row: AuditLog) => row.user, {
				id: "user.avatar",
				cell: (info: any) => {
					const value = info.getValue();
					return <GravatarFormatter url={value ? value.avatar : ""} name={value ? value.name : ""} />;
				},
				meta: { className: "w-1" },
			}),
			columnHelper.accessor((row: AuditLog) => row, {
				id: "objectType",
				header: intl.formatMessage({ id: "column.event" }),
				cell: (info: any) => <EventFormatter row={info.getValue()} />,
				filterFn: (row, _columnId, filterValue: string) => {
					const r = row.original;
					const haystack = [
						r.user?.name ?? "",
						r.objectType,
						r.action,
						r.createdOn,
						String(r.objectId),
					]
						.join(" ")
						.toLowerCase();
					return haystack.includes(filterValue.toLowerCase());
				},
			}),
			columnHelper.display({
				id: "id",
				cell: (info: any) => (
					<button
						type="button"
						className="btn btn-action btn-sm px-1"
						onClick={(e) => {
							e.preventDefault();
							onSelectItem?.(info.row.original.id);
						}}
					>
						<T id="action.view-details" />
					</button>
				),
				meta: { className: "text-end w-1" },
			}),
		],
		[columnHelper, onSelectItem],
	);

	const tableInstance = useReactTable<AuditLog>({
		columns,
		data,
		state: {
			globalFilter,
		},
		globalFilterFn: (row, _columnId, filterValue: string) => {
			if (!filterValue) return true;
			const r = row.original;
			const haystack = [
				r.user?.name ?? "",
				r.objectType,
				r.action,
				r.createdOn,
				String(r.objectId),
			]
				.join(" ")
				.toLowerCase();
			return haystack.includes(filterValue.toLowerCase());
		},
		getCoreRowModel: getCoreRowModel(),
		getFilteredRowModel: getFilteredRowModel(),
		getPaginationRowModel: getPaginationRowModel(),
		initialState: {
			pagination: { pageSize: 10 },
		},
		rowCount: data.length,
		meta: { isFetching },
		enableSortingRemoval: false,
	});

	const { pageIndex, pageSize } = tableInstance.getState().pagination;
	const filteredRows = tableInstance.getFilteredRowModel().rows.map((r) => r.original);
	const totalRows = filteredRows.length;
	const pageCount = tableInstance.getPageCount();
	const from = totalRows === 0 ? 0 : pageIndex * pageSize + 1;
	const to = Math.min((pageIndex + 1) * pageSize, totalRows);

	return (
		<>
			<TableLayout tableInstance={tableInstance} />
			{(totalRows > pageSize || pageCount > 1) && (
				<div className="card-footer d-flex align-items-center justify-content-between py-2 px-3 flex-wrap gap-2">
					{/* Record count */}
					<small className="text-muted">
						{from}–{to} / {totalRows}
					</small>

					{/* Prev / Page / Next */}
					<div className="d-flex gap-1">
						<button
							type="button"
							className="btn btn-sm btn-outline-secondary"
							onClick={() => tableInstance.previousPage()}
							disabled={!tableInstance.getCanPreviousPage()}
						>
							‹ Trước
						</button>
						<span className="btn btn-sm disabled text-muted px-2">
							{pageIndex + 1} / {pageCount}
						</span>
						<button
							type="button"
							className="btn btn-sm btn-outline-secondary"
							onClick={() => tableInstance.nextPage()}
							disabled={!tableInstance.getCanNextPage()}
						>
							Tiếp ›
						</button>
					</div>

					{/* Page size */}
					<div className="d-flex align-items-center gap-2">
						<small className="text-muted text-nowrap">Mỗi trang:</small>
						<select
							className="form-select form-select-sm w-auto"
							value={pageSize}
							onChange={(e) => tableInstance.setPageSize(Number(e.target.value))}
						>
							{[10, 25, 50, 100].map((size) => (
								<option key={size} value={size}>
									{size}
								</option>
							))}
						</select>
					</div>

					{/* Export */}
					<button
						type="button"
						className="btn btn-sm btn-outline-success"
						onClick={() => exportCSV(filteredRows)}
						title="Export CSV"
					>
						⬇ CSV
					</button>
				</div>
			)}
		</>
	);
}
