'use client';

import { useState, useMemo, useEffect, ReactNode } from 'react';
import {
	useReactTable,
	getCoreRowModel,
	getSortedRowModel,
	getPaginationRowModel,
	getFilteredRowModel,
	ColumnDef,
	SortingState,
	ColumnFiltersState,
} from '@tanstack/react-table';
import { IconEye, IconDoubleArrowRight, IconArrowRight, IconDoubleArrowLeft, IconArrowLeft, IconArrowUp, IconArrowDown, IconFilter, IconFileDownload, IconShieldExclamation } from '@/app/ui/icons/icons';
import { useTranslations, useLocale } from 'next-intl';
import DropDownList from '@/app/components/DropDownList';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { getUserFilesData, removeUserFile, viewFileInfo } from '@/app/actions/fileEntity';
import ModalWindow from '@/app/components/ModalWindow';
import { toast } from 'sonner';
import { pluralize } from '@/app/lib/pluralize';
import { convertBytes } from '@/app/lib/convertBytes';
import { FileInfoModalWindow } from '@/app/ui/modal-windows/file-info-modal-window';
import { FileTypeIcon } from '@/app/components/FileTypeIcon';

type FileType = 'image' | 'video' | 'audio';

type FileItem = {
	id: string;
	fileName: string;
	fileType: string;
	violations?: number | undefined;
	size?: number | undefined;
	uploadDate?: number;
	status?: string;
	protectStatus: string;
	_original?: ApiFile;
	supportId: number;
};

type ApiFile = {
	id: string;
	originalFileName: string;
	mimeType: string;
	violations: number;
	fileSize: number;
	updatedAt: string;
	status: string;
	protectStatus: string;
	supportId: number;
};

type ApiResponse = {
	files?: ApiFile[];
};

// Форматирование даты из timestamp
const formatDate = (timestamp: number) => {
	const date = new Date(timestamp);
	const day = date.getDate().toString().padStart(2, '0');
	const month = (date.getMonth() + 1).toString().padStart(2, '0');
	const year = date.getFullYear();

	return `${day}.${month}.${year}`;
};

const formatDateTime = (timestamp: number) => {
	const date = new Date(timestamp);
	const hours = date.getHours().toString().padStart(2, '0');
	const minutes = date.getMinutes().toString().padStart(2, '0');

	return `${hours}:${minutes}`;
};

const cutFileName = (fileName: string) => {
	const MAX_FILE_NAME_LENGTH = 26;
	const lastDotIndex = fileName.lastIndexOf('.');

	if (lastDotIndex <= 0) {
		return fileName.length > MAX_FILE_NAME_LENGTH ? fileName.substring(0, MAX_FILE_NAME_LENGTH - 3) + '...' : fileName;
	}

	const nameWithoutExtension = fileName.substring(0, lastDotIndex);
	const extension = fileName.substring(lastDotIndex);

	if (fileName.length <= MAX_FILE_NAME_LENGTH) {
		return fileName;
	}

	const maxNameLength = MAX_FILE_NAME_LENGTH - extension.length - 3;

	if (maxNameLength <= 0) {
		return '...' /* + extension */;
	}

	return nameWithoutExtension.substring(0, maxNameLength) + '...' /* + extension */;
}

const cutFileExtension = (fileName: string) => {
	const lastDotIndex = fileName.lastIndexOf('.');
	const extension = fileName.substring(lastDotIndex + 1);
	return extension;
}

export default function TanstakFilesTable({ fileType }: { fileType: string }) {
	const {
		data: tableData,
		isLoading,
		isError,
		error,
	} = useQuery<ApiResponse, Error, FileItem[], ['userFilesData', number, number]>({
		queryKey: ['userFilesData', 1, 10000],
		queryFn: () => getUserFilesData(1, 10000),

		select: (data: ApiResponse): FileItem[] => {
			if (!data?.files) return [];

			return data.files.map((item: ApiFile) => {
				const newDate = new Date(item.updatedAt).getTime();

				return {
					id: item.id,
					fileName: item.originalFileName,
					fileType: item.mimeType.toLocaleLowerCase(),
					violations: item.violations,
					size: item.fileSize,
					uploadDate: newDate,
					status: item.status,
					protectStatus: item.protectStatus,
					supportId: item.supportId,
					_original: item
				};
			});
		},
	});

	const queryClient = useQueryClient();

	// Состояния
	const [sorting, setSorting] = useState<SortingState>([]);
	const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
	const [dateFilter, setDateFilter] = useState<string>('all');
	const [typeFilter, setTypeFilter] = useState<string>(fileType);
	const [pagination, setPagination] = useState({
		pageIndex: 0,
		pageSize: 10,
	});
	const [openWindow, setOpenWindow] = useState<boolean>(false);
	const [openWindowChildren, setOpenWindowChildren] = useState<ReactNode>(null);

	const [isFileLoading, setIsFileLoading] = useState(false);

	const t = useTranslations("Global");
	const locale = useLocale();

	// Определение колонок
	const columns = useMemo<ColumnDef<FileItem>[]>(
		() => [
			{
				accessorKey: 'id',
				header: ({ column }) => (
					<div className="column">
						<span>
							ID
						</span>
						<button
							onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
							className="sort-button"
						>
							{
								column.getIsSorted() === 'asc' ?
									<span>
										<IconArrowUp />
									</span>
									: column.getIsSorted() === 'desc' ?
										<span>
											<IconArrowDown />
										</span>
										: <span>
											<IconFilter />
										</span>
							}
						</button>
					</div>
				),
				cell: ({ row }) => {
					return (
						<div className="text-center table-item table-item-id">
							{row.original.supportId ? row.original.supportId : '-'}
						</div>
					)
				},
			},
			{
				accessorKey: 'fileName',
				header: ({ column }) => (
					<div className="column start">
						<span>
							{t('file')}
						</span>
						<button
							onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
							className="sort-button"
						>
							{
								column.getIsSorted() === 'asc' ?
									<span>
										<IconArrowUp />
									</span>
									: column.getIsSorted() === 'desc' ?
										<span>
											<IconArrowDown />
										</span>
										: <span>
											<IconFilter />
										</span>
							}
						</button>
					</div>
				),
				cell: ({ row }) => (
					<div className="flex items-center space-x-2 table-item">
						<FileTypeIcon type={row.original.fileType} />
						<div>
							<div className="font-medium w-full truncate" title={row.original.fileName}>
								<span className="font-semibold">
									{cutFileName(row.original.fileName)}
								</span>
								<br />
								<span className="table-item-extension">{cutFileExtension(row.original.fileName)}</span> <span className="table-item-protected">
									{row.original?.protectStatus ? t(row.original?.protectStatus) : t('error')}
								</span>
							</div>
						</div>
					</div>
				),
				enableColumnFilter: false,
			},
			/* 			{
							accessorKey: 'violations',
							header: ({ column }) => (
								<div className="column">
									<span>
										{t('violations')}
									</span>
									<button
										onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
										className="sort-button"
									>
										{
											column.getIsSorted() === 'asc' ?
												<span>
													<IconArrowUp />
												</span>
												: column.getIsSorted() === 'desc' ?
													<span>
														<IconArrowDown />
													</span>
													: <span>
														<IconFilter />
													</span>
										}
									</button>
								</div>
							),
							cell: ({ row }) => {
								let classCollor = () => {
									let result = ''
									if (row.original.violations !== undefined) {
										result = row.original.violations > 0 ? 'text-red-600' : 'text-green-600'
									}
									return result;
								}
								return (
									<div className={`text-center font-semibold ${classCollor()}`}>
										{row.original.violations !== undefined ? row.original.violations : '-'}
									</div>
								)
							},
						}, */
			{
				accessorKey: 'size',
				header: ({ column }) => (
					<div className="column">
						<span>
							{t('size')}
						</span>
						<button
							onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
							className="sort-button"
						>
							{
								column.getIsSorted() === 'asc' ?
									<span>
										<IconArrowUp />
									</span>
									: column.getIsSorted() === 'desc' ?
										<span>
											<IconArrowDown />
										</span>
										: <span>
											<IconFilter />
										</span>
							}
						</button>
					</div>
				),
				cell: ({ row }) => (
					<div className="text-center table-item">
						{row.original.size !== undefined ? convertBytes(row.original.size) : '-'}
					</div>
				),
			},
			{
				accessorKey: 'uploadDate',
				header: ({ column }) => (
					<div className="column">
						<span>
							{t('upload-date')}
						</span>
						<button
							onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
							className="sort-button"
						>
							{
								column.getIsSorted() === 'asc' ?
									<span>
										<IconArrowUp />
									</span>
									: column.getIsSorted() === 'desc' ?
										<span>
											<IconArrowDown />
										</span>
										: <span>
											<IconFilter />
										</span>
							}
						</button>
					</div>
				),
				cell: ({ row }) => {
					return (
						<div className="text-center table-item">
							{row.original.uploadDate ? (
								<>
									{formatDate(row.original.uploadDate)}
									<br />
									{formatDateTime(row.original.uploadDate)}
								</>
							) : (
								<div>-</div>
							)}
						</div>
					)
				},
				enableColumnFilter: false,
			},
			{
				accessorKey: 'status',
				header: ({ column }) => (
					<div className="column">
						<span>
							{t('status')}
						</span>
						<button
							onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
							className="sort-button"
						>
							{
								column.getIsSorted() === 'asc' ?
									<span>
										<IconArrowUp />
									</span>
									: column.getIsSorted() === 'desc' ?
										<span>
											<IconArrowDown />
										</span>
										: <span>
											<IconFilter />
										</span>
							}
						</button>
					</div>
				),
				cell: ({ row }) => {
					return (
						<div className="text-center font-semibold table-item">
							<span className="table-item-status">
								{row.original.status}
							</span>
						</div>
					)
				},
			},
			{
				id: 'actions',
				header: () => {
					return (
						<div className="column">
							{t('actions')}
						</div>
					)
				},
				cell: ({ row }) => (
					<div className="actions">
						<div className="actions-group" style={{ display: "none" }}>
							<button
								onClick={() => handleProtect(row.original)}
								className="bg-violet-500 hover:bg-violet-600"
							>
								<IconShieldExclamation />
							</button>
							{/* <button
								onClick={() => handleOpenWindowForRemove(row.original)}
								className="table-action-delete"
							>
								<IconDelete />
								<span>
									{t('delete')}
								</span>
							</button> */}
						</div>
						<div className="actions-group">
							{row.original.protectStatus === 'PROTECTED' && (
								<button
									onClick={() => handleDownload(row.original)}
									disabled={isFileLoading}
									className="table-action-download"
								>
									<IconFileDownload />
									<span>
										{t('download')}
									</span>
								</button>
							)}
							<button
								onClick={() => {
									handleView(row.original)
								}}
								className="table-action-view"
							>
								<IconEye />
								<span>
									{t('make-check')}
								</span>
							</button>
						</div>

					</div>
				),
				enableSorting: false,
				enableColumnFilter: false,
			},
		],
		[]
	);

	const handleView = async (file: FileItem) => {
		console.log(`Просмотр файла: ${file.fileName}`);
		console.log(file);

		const fileInfo = await viewFileInfo(file.id);
		console.log(fileInfo);

		setOpenWindowChildren(() => {
			return (
				<FileInfoModalWindow fileInfo={fileInfo} setWindowClose={setOpenWindow} setWindowChildren={setOpenWindowChildren} />
			)
		})
		setOpenWindow(true);
	};

	const handleDownload = async (file: FileItem) => {
		setIsFileLoading(true);

		try {
			const response = await fetch(`/api/download/${file.id}`);

			if (!response.ok) {
				throw new Error(`error: ${response.status}`);
			}

			const blob = await response.blob();
			const url = window.URL.createObjectURL(blob);
			const a = document.createElement('a');
			a.href = url;
			a.download = file.fileName || `file-${file.id}`;
			document.body.appendChild(a);
			a.click();
			window.URL.revokeObjectURL(url);
			document.body.removeChild(a);
			toast.success(`${t('file-is-downloading')} - ${file.fileName}`);
		} catch (error) {
			toast.error(t('failed-to-download-file'))
		} finally {
			setIsFileLoading(false);
		}
	};

	const handleProtect = (file: FileItem) => {
		console.log(`Щиток: ${file.fileName}`);
	};

	const handleOpenWindowForRemove = async (file: FileItem) => {

		setOpenWindowChildren(() => {
			return (
				<div>
					<h3 className="text-2xl">
						{t('you-sure-you-want-to-delete')}
					</h3>
					<div className="mt-2 mb-8 text-center">{file.fileName}</div>
					<div className="flex justify-center gap-4">
						<button className="btn-primary btn-modal"
							onClick={() => {
								deleteMutation.mutate({
									fileId: file.id,
									removeParam: 1,
								})
							}}
							disabled={deleteMutation.isPending}
						>
							{deleteMutation.isPending ? '...' : t('yes')}
						</button>
						<button className="btn-primary btn-modal"
							onClick={() => {
								setOpenWindow(false);
								setOpenWindowChildren(null);
							}}
						>
							{t('no')}
						</button>
					</div>
				</div>
			)
		})
		setOpenWindow(true);
	};

	const deleteMutation = useMutation({
		mutationFn: ({ fileId, removeParam }: { fileId: string; removeParam: number }) =>
			removeUserFile(fileId, removeParam),

		onMutate: async ({ fileId, removeParam }: { fileId: string; removeParam: number }) => {
			await queryClient.cancelQueries({ queryKey: ['userFilesData'] });

			queryClient.setQueryData<ApiResponse>(['userFilesData'], (old) => {
				if (!old?.files) return old;
				return {
					...old,
					files: old.files.filter(file => file.id !== fileId)
				};
			});
		},

		onError: () => {
			queryClient.invalidateQueries({ queryKey: ['userFilesData'] });
			toast.error(t('error'));
		},

		onSuccess: (response, { fileId }) => {
			if (response === fileId) {
				queryClient.invalidateQueries({
					queryKey: ['userFilesData'],
					refetchType: 'active'
				});

				queryClient.invalidateQueries({
					queryKey: ['userFilesInfo']
				});

				setOpenWindow(false);
				setOpenWindowChildren(null);
				toast.success(t('file-has-been-deleted'));
			}
		},
	});

	// Фильтрация по типу файла и дате
	const filteredData = useMemo(() => {
		let result = tableData;
		if (!result) {
			return [];
		}

		// Фильтр по типу файла
		if (typeFilter !== 'all') {
			result = result.filter(item => item.fileType === typeFilter);
		}

		// Фильтр по дате
		if (dateFilter !== 'all') {
			const now = Date.now();
			const oneDay = 24 * 60 * 60 * 1000;
			const sevenDays = 7 * oneDay;
			const thirtyDays = 30 * oneDay;

			switch (dateFilter) {
				case 'today':
					const todayStart = new Date().setHours(0, 0, 0, 0);
					result = result.filter(item => {
						if (item.uploadDate) {
							return item.uploadDate >= todayStart
						} else {
							return 0
						}
					});
					break;
				case 'week':
					const weekAgo = now - sevenDays;
					result = result.filter(item => {
						if (item.uploadDate) {
							return item.uploadDate >= weekAgo;
						}
					});
					break;
				case 'month':
					const monthAgo = now - thirtyDays;
					result = result.filter(item => {
						if (item.uploadDate) {
							return item.uploadDate >= monthAgo;
						}
					});
					break;
				case 'older':
					const monthAgo2 = now - thirtyDays;
					result = result.filter(item => {
						if (item.uploadDate) {
							return item.uploadDate < monthAgo2;
						}
					});
					break;
			}
		}

		return result;
	}, [tableData, typeFilter, dateFilter]);

	useEffect(() => {
		const currentPageRows = table.getRowModel().rows;
		const pageCount = table.getPageCount();

		if (currentPageRows.length === 0 && pagination.pageIndex > 0 && pageCount > 0) {
			table.setPageIndex(pagination.pageIndex - 1);
		}
	}, [filteredData, pagination.pageIndex]);

	// Создание таблицы
	const table = useReactTable({
		data: filteredData,
		columns,
		state: {
			sorting,
			columnFilters,
			pagination
		},
		autoResetPageIndex: false,
		onPaginationChange: setPagination,
		onSortingChange: setSorting,
		onColumnFiltersChange: setColumnFilters,
		getCoreRowModel: getCoreRowModel(),
		getSortedRowModel: getSortedRowModel(),
		getPaginationRowModel: getPaginationRowModel(),
		getFilteredRowModel: getFilteredRowModel(),
		initialState: {
			pagination: {
				pageSize: 10,
			},
		},
	});

	const pluralizeFiles = (number: number) => {
		const translate = [t('file'), t('files-few'), t('files')];
		return pluralize(number, translate[0], translate[1], translate[2], locale);
	};

	return (
		<div className="tanstak-table-wrapper">
			<h3
				className="tanstak-table-title"
			>
				{(() => {
					switch (fileType) {
						case 'image':
							return t('protected-image')
						case 'video':
							return t('protected-video')
						case 'audio':
							return t('protected-audio')
						default:
							return t('table-description')
					}
				})()}
			</h3>
			<ModalWindow children={openWindowChildren} state={openWindow} callBack={setOpenWindow} />
			{/* Фильтры */}
			<div className="tanstak-table-filtres" style={{ display: "none" }}>
				<div className="table-filtres-wrapper">
					<div className="table-filtres-item">
						<div className="table-filtres-label">{t('date-filter')}:</div>
						<DropDownList
							value={dateFilter}
							translatedValue={(() => {
								switch (dateFilter) {
									case 'all':
										return t('all-dates')
									case 'week':
										return t('for-a-week')
									case 'month':
										return t('for-a-month')
									case 'older':
										return t('older-than-a-month')
									default:
										return t('today')
								}
							})()}
							callBack={setDateFilter}
						>
							<li value="all">
								{t('all-dates')}
							</li>
							<li value="today">
								{t('today')}
							</li>
							<li value="week">
								{t('for-a-week')}
							</li>
							<li value="month">
								{t('for-a-month')}
							</li>
							<li value="older">
								{t('older-than-a-month')}
							</li>
						</DropDownList>
					</div>

					{fileType === "all" && (
						<div className="table-filtres-item">
							<div className="table-filtres-label">{t('type-filter')}:</div>
							<DropDownList
								value={typeFilter}
								translatedValue={
									(() => {
										switch (typeFilter) {
											case 'image':
												return t('images')
											case 'video':
												return t('videos')
											case 'audio':
												return t('audios')
											default:
												return t('all-types')
										}
									})()
								}
								callBack={setTypeFilter}
							>
								<li value="all">
									{t('all-types')}
								</li>
								<li value="image">
									{t('images-few')}
								</li>
								<li value="video">
									{t('videos')}
								</li>
								<li value="audio">
									{t('audios')}
								</li>
							</DropDownList>
						</div>
					)}
				</div>

				<div className="table-filtres-item">
					<div className="table-filtres-label">{t('items-per-page')}:</div>
					<DropDownList
						value={table.getState().pagination.pageSize}
						//@ts-ignore сделал так потому что для table.setPageSize нужна цифра
						callBack={table.setPageSize}
					>
						{[5, 10, 20, 50, 100].map(pageSize => (
							<li key={pageSize} value={pageSize}>
								{t('show')} {pageSize}
							</li>
						))}
					</DropDownList>
				</div>
			</div>

			{/* Таблица */}
			<div className="tanstak-table-block">
				<table className="tanstak-table">
					<thead className="tanstak-table-head">
						{table.getHeaderGroups().map(headerGroup => (
							<tr key={headerGroup.id}>
								{headerGroup.headers.map(header => (
									<th
										key={header.id}
									>
										{header.isPlaceholder
											? null
											: typeof header.column.columnDef.header === 'function'
												? header.column.columnDef.header(header.getContext())
												: header.column.columnDef.header as string}
									</th>
								))}
							</tr>
						))}
					</thead>
					<tbody className="tanstak-table-body">
						{table.getRowModel().rows.length > 0 ? (
							table.getRowModel().rows.map(row => (
								<tr key={row.id}>
									{row.getVisibleCells().map(cell => (
										<td key={cell.id}>
											{typeof cell.column.columnDef.cell === 'function'
												? cell.column.columnDef.cell(cell.getContext())
												: cell.getValue() as string}
										</td>
									))}
								</tr>
							))
						) : (
							<tr>
								<td colSpan={columns.length} className="text-center">
									{t('no-data-for-selected-filters')}
								</td>
							</tr>
						)}
					</tbody>
				</table>
			</div>

			{/* Пагинация */}
			<div className="tanstak-table-pagination">
				<div className="pagination-info">
					<span className="pagination-info-pages">
						{t('page')}{' '}
						<strong>
							{table.getState().pagination.pageIndex + 1} {t('out-of')} {table.getPageCount() ? table.getPageCount() : 1}
						</strong>
					</span>
					<span className="pagination-info-files">
						| {t('shown')} {table.getRowModel().rows.length} {t('out-of')} {filteredData.length} {pluralizeFiles(filteredData.length || 0)}
					</span>
				</div>

				<div className="pagination-controls">
					{table.getCanPreviousPage() && (
						<button
							className="arrow"
							onClick={() => table.firstPage()}
							disabled={!table.getCanPreviousPage()}
						>
							<IconDoubleArrowLeft />
						</button>
					)}
					{table.getCanPreviousPage() && (
						<button
							className="arrow"
							onClick={() => table.previousPage()}
							disabled={!table.getCanPreviousPage()}
						>
							<IconArrowLeft />
						</button>
					)}

					<div className="pagination-controls-pages">
						{Array.from({ length: Math.min(5, table.getPageCount()) }, (_, i) => {
							const pageIndex = Math.max(
								0,
								Math.min(
									table.getPageCount() - 5,
									table.getState().pagination.pageIndex - 2
								)
							) + i;

							if (pageIndex < table.getPageCount()) {
								return (
									<button
										key={pageIndex}
										className={`${table.getState().pagination.pageIndex === pageIndex
											? 'current'
											: 'other'
											}`}
										onClick={() => table.setPageIndex(pageIndex)}
									>
										{pageIndex + 1}
									</button>
								);
							}
							return null;
						})}
					</div>

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