'use client'

import { useTranslations } from 'next-intl';
import { IconCheck, IconArrowLeft, IconArrowRight, IconDoubleArrowLeft, IconDoubleArrowRight } from '@/app/ui/icons/icons';
import { useEffect, useState } from 'react';
import { useAllNotifications } from '@/app/hooks/react-query/useAllNotificationsList';
import { notificationsMarkAsRead, notificationsDelete, NotificationBody } from '@/app/actions/notificationActions';
import { useQueryClient } from '@tanstack/react-query';
import { formatDate, formatDateTime } from '@/app/lib/formatDate';

import {
	useReactTable,
	getCoreRowModel,
	getPaginationRowModel,
	flexRender,
	createColumnHelper,
	RowSelectionState,
} from '@tanstack/react-table';
import { NotificationTextHandler } from '@/app/components/NotificationTextHandler';

export function NotificationsList() {
	const t = useTranslations('Global');
	const norificationTranslate = useTranslations('Notifications');
	const queryClient = useQueryClient();

	const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
	const [loadingIds, setLoadingIds] = useState<Set<number>>(new Set());
	const [error, setError] = useState<string | null>(null);
	const [pagination, setPagination] = useState({
		pageIndex: 0,
		pageSize: 10,
	});

	const { data: allNotifications, isLoading } = useAllNotifications(
		pagination.pageIndex,
		pagination.pageSize
	);

	const totalPages = allNotifications?.totalPages || 0;
	const totalRecords = allNotifications?.totalElements || 0;

	const columnHelper = createColumnHelper<NotificationBody>();

	const columns = [
		columnHelper.display({
			id: 'select',
			header: ({ table }) => {
				const currentPageRows = table.getCoreRowModel().rows;
				const unreadRowsOnPage = currentPageRows.filter(row => row.original.status !== 'READIED');
				const allNotificationSelectedOnPage = currentPageRows.every(row => rowSelection[row.original.id]);

				const unreadIdsSet = new Set(unreadRowsOnPage.map(row => row.original.id));
				const selectedUnreadIds = Object.keys(rowSelection)
					.map(Number)
					.filter(id => unreadIdsSet.has(id));

				return (
					<div className="select-all-header">
						{selectedUnreadIds.length > 0 && (
							<button
								className="btn btn-primary"
								onClick={() => {
									const selectedIds = Object.keys(rowSelection).map(Number);
									notificationActionHandler(selectedUnreadIds, 'mark-as-read');
								}}
							>
								{t('mark-as-read')} ({selectedUnreadIds.length})
							</button>
						)}
						{Object.keys(rowSelection).length > 0 && (
							<>
								<button
									className="btn btn-primary"
									onClick={() => {
										const selectedIds = Object.keys(rowSelection).map(Number);
										notificationActionHandler(selectedIds, 'remove');
									}}
								>
									{t('remove')} ({Object.keys(rowSelection).length})
								</button>
							</>
						)}

						{allNotifications?.notifications.length !== 0 && (
							<button
								className="btn btn-primary"
								onClick={() => {
									if (allNotificationSelectedOnPage) {

										const newSelection = { ...rowSelection };
										currentPageRows.forEach(row => {
											delete newSelection[row.original.id];
										});
										setRowSelection(newSelection);
									} else {

										const newSelection = { ...rowSelection };
										currentPageRows.forEach(row => {
											newSelection[row.original.id] = true;
										});
										setRowSelection(newSelection);
									}
								}}
							>
								{allNotificationSelectedOnPage ? t('deselect') : t('select-all')}
							</button>
						)}
					</div>
				);
			},
			cell: ({ row }) => {
				const isReadied = row.original.status === 'READIED';
				const isSelected = !!rowSelection[row.original.id];

				return (
					<div className="notification-check">
						<button
							onClick={() => {
								setRowSelection((prev) => {
									const newSelection = { ...prev };

									if (newSelection[row.original.id]) {
										delete newSelection[row.original.id];
									} else {
										newSelection[row.original.id] = true;
									}

									return newSelection;
								});
							}}
						>
							{isSelected && <IconCheck />}
						</button>
					</div>
				);
			},
		}),
		columnHelper.accessor('message', {
			id: 'message',
			header: () => null,
			cell: ({ row }) => {
				const item = row.original;
				return (
					<div className="notification-body">
						<div className="notification-header">
							<div
								className="notification-title"
							>
								{norificationTranslate.has(item.message)
									? norificationTranslate(item.message)
									: item.message} ({item.id})
							</div>
						</div>
						<div className="notification-text">
							<NotificationTextHandler notificationType={item.type} notificationMessage={item.message} notificationContext={item.context} />
						</div>
						<div className="notification-footer">
							<div className="notification-date">
								{item.createdAt
									? `${formatDate(item.createdAt)}: ${formatDateTime(item.createdAt)}`
									: '---'}
							</div>
							<button
								className="btn btn-remove"
								onClick={() => {
									notificationActionHandler([item.id], 'remove');
								}}
								disabled={loadingIds.has(item.id)}
							>
								{t('remove')}
							</button>
						</div>
					</div>
				);
			},
		}),
	];

	const table = useReactTable({
		data: allNotifications?.notifications || [],
		columns,
		state: {
			rowSelection,
			pagination,
		},
		enableRowSelection: true,
		onRowSelectionChange: setRowSelection,
		onPaginationChange: setPagination,
		getCoreRowModel: getCoreRowModel(),
		getPaginationRowModel: getPaginationRowModel(),
		manualPagination: true,
		pageCount: totalPages,
	});

	async function notificationActionHandler(ids: number[], action: 'remove' | 'mark-as-read') {
		setLoadingIds(prev => {
			const newSet = new Set(prev);
			ids.forEach(id => newSet.add(id));
			return newSet;
		});

		try {
			let response;

			if (action === 'mark-as-read') {
				response = await notificationsMarkAsRead(ids);
			} else if (action === 'remove') {
				response = await notificationsDelete(ids);
			}

			if (response?.success) {
				setRowSelection({});
				await queryClient.invalidateQueries({ queryKey: ['activeNotifications'] });
				await queryClient.invalidateQueries({ queryKey: ['allNotifications'] });
			}
		} catch (error) {
			const errorMessage = action === 'mark-as-read' ? 'Failed to mark as read' : 'Failed to remove';
			setError(errorMessage);
		} finally {
			setLoadingIds(prev => {
				const newSet = new Set(prev);
				ids.forEach(id => newSet.delete(id));
				return newSet;
			});
		}
	}

	const getPageNumbers = (): (number | string)[] => {
		const delta: number = 2;
		const currentPageNum = pagination.pageIndex;
		const range: number[] = [];
		const rangeWithDots: (number | string)[] = [];
		let l: number | undefined;

		for (let i = 0; i < totalPages; i++) {
			if (i === 0 || i === totalPages - 1 || (i >= currentPageNum - delta && i <= currentPageNum + delta)) {
				range.push(i);
			}
		}

		range.forEach((i: number) => {
			if (l !== undefined) {
				if (i - l === 2) {
					rangeWithDots.push(l + 1);
				} else if (i - l !== 1) {
					rangeWithDots.push('...');
				}
			}
			rangeWithDots.push(i);
			l = i;
		});

		return rangeWithDots;
	};

	return (
		<div className="notifications-list-wrapper">
			<div className="notifications-list-header">
				<h4>{t('all-notifications')}</h4>
				<div className="notifications-table-header">
					{table.getHeaderGroups().map((headerGroup) => (
						<div key={headerGroup.id} className="table-row n-header">
							{headerGroup.headers.map((header) => (
								<div key={header.id} className="table-cell">
									{flexRender(
										header.column.columnDef.header,
										header.getContext()
									)}
								</div>
							))}
						</div>
					))}
				</div>
				{/* 				<div
					className="notifications-list-action"
				>
					{(selectedFiles.size !== 0) && (
						<>
							<button
								className="btn btn-primary"
								onClick={() => {
									clearHandler();
								}}
							>
								{t('deselect')}
							</button>

							<button
								className="btn btn-primary"
								onClick={() => {
									const array = Array.from(selectedFiles);
									notificationActionHandler(array, 'mark-as-read');
								}}
							>
								{t('mark-as-read')}
							</button>
						</>
					)}
					<button
						className="btn btn-primary"
						onClick={() => {
							selectAllHandler();
						}}
					>
						{t('select-all')}
					</button>
				</div> */}
			</div>

			<div className="notifications-list-body">
				{allNotifications?.notifications.length !== 0 ? (
					<div className="notifications-table">
						<div className="notifications-table-body">
							{table.getRowModel().rows.map((row) => (
								<div
									key={row.id}
									className={`table-row ${loadingIds.has(row.original.id) ? 'loading' : ''} ${row.original.status}`}
								>
									{row.getVisibleCells().map((cell) => (
										<div key={cell.id} className="table-cell">
											{flexRender(
												cell.column.columnDef.cell,
												cell.getContext()
											)}
										</div>
									))}
								</div>
							))}
						</div>
					</div>
				) : (
					<div className="no-notifications">{t('no-notifications')}</div>
				)}
			</div>

			<div className="notifications-list-footer">
				{totalPages > 0 && (
					<div className="pagination-controls">
						<button
							className="arrow"
							onClick={() => {
								setRowSelection({});
								table.firstPage();
							}}
							disabled={!table.getCanPreviousPage()}
						>
							<IconDoubleArrowLeft />
						</button>
						<button
							onClick={() => {
								setRowSelection({});
								table.previousPage()
							}}
							className="arrow"
							disabled={!table.getCanPreviousPage()}
						>
							<IconArrowLeft />
						</button>

						<div className="pagination-controls-pages">
							{getPageNumbers().map((pageNum, index) => (
								<button
									key={index}
									onClick={() => {
										setRowSelection({});
										typeof pageNum === 'number' && table.setPageIndex(pageNum);
									}}
									className={pagination.pageIndex === pageNum ? 'current' : 'other'}
									disabled={pageNum === '...'}
								>
									{pageNum === '...' ? '...' : (pageNum as number) + 1}
								</button>
							))}
						</div>

						<button
							onClick={() => {
								setRowSelection({});
								table.nextPage();
							}}
							className="arrow"
							disabled={!table.getCanNextPage()}
						>
							<IconArrowRight />
						</button>
						<button
							className="arrow"
							onClick={() => {
								setRowSelection({});
								table.lastPage();
							}}
							disabled={!table.getCanNextPage()}
						>
							<IconDoubleArrowRight />
						</button>
					</div>
				)}
			</div>

			{error && <div className="error-message">{error}</div>}
		</div>
	);
}