import type { Kennzahl } from "@/types/kpi";
import EditIcon from "@mui/icons-material/Edit";
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
import SearchIcon from "@mui/icons-material/Search";
import {
	Box,
	Link,
	Paper,
	Table,
	TableBody,
	TableCell,
	TableContainer,
	TableHead,
	TableRow,
	TextField,
	Tooltip,
} from "@mui/material";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useNavigate } from "@tanstack/react-router";
import { useState } from "react";
import type { KeyboardEvent } from "react";
import { fetchPutKPI } from "../util/api";

interface KennzahlenTableProps {
	onPageClick?: (page: number, text: string) => void;
	pdfId: string;
	settings: Kennzahl[];
	data: {
		[key: string]: {
			label: string;
			entity: string;
			page: number;
			status: string;
			source: string;
		}[];
	};
	from?: string;
}

export default function KennzahlenTable({
	onPageClick,
	data,
	pdfId,
	settings,
	from,
}: KennzahlenTableProps) {
	const [editingIndex, setEditingIndex] = useState<string>("");
	const [editValue, setEditValue] = useState("");
	const [editingPageIndex, setEditingPageIndex] = useState<string>("");
	const [editPageValue, setEditPageValue] = useState("");
	const [hoveredPageIndex, setHoveredPageIndex] = useState<string>("");
	const navigate = useNavigate();

	const queryClient = useQueryClient();

	const { mutate } = useMutation({
		mutationFn: (params: { id: string; newValue?: string; newPage?: number }) => {
			const { id, newValue, newPage } = params;
			const key = id.toUpperCase();
			const updatedData = { ...data };

			if (data[key] && data[key].length > 0) {
				updatedData[key] = data[key].map((item) => ({
					...item,
					...(newValue !== undefined && { entity: newValue }),
					...(newPage !== undefined && { page: newPage }),
				}));
			} else {
				updatedData[key] = [{
					label: key,
					entity: newValue || "",
					page: newPage || 0,
					status: "single-source",
					source: "manual"
				}];
			}

			return fetchPutKPI(Number(pdfId), updatedData);
		},
		onMutate: async (params: { id: string; newValue?: string; newPage?: number }) => {
			const { id, newValue, newPage } = params;
			await queryClient.cancelQueries({
				queryKey: ["pitchBookKPI", pdfId],
			});

			const snapshot = queryClient.getQueryData(["pitchBookKPI", pdfId]);

			const key = id.toUpperCase();

			queryClient.setQueryData(["pitchBookKPI", pdfId], () => {
				const updatedData = { ...data };

				if (data[key] && data[key].length > 0) {
					updatedData[key] = data[key].map((item) => ({
						...item,
						...(newValue !== undefined && { entity: newValue }),
						...(newPage !== undefined && { page: newPage }),
					}));
				} else {
					updatedData[key] = [{
						label: key,
						entity: newValue || "",
						page: newPage || 0,
						status: "single-source",
						source: "manual"
					}];
				}

				return updatedData;
			});

			return () => {
				queryClient.setQueryData(["pitchBookKPI", pdfId], snapshot);
			};
		},
		onError: (error, _variables, rollback) => {
			console.log("error", error);
			rollback?.();
		},
		onSettled: () => {
			return queryClient.invalidateQueries({
				queryKey: ["pitchBookKPI", pdfId],
			});
		},
	});

	// Bearbeitung starten
	const startEditing = (value: string, index: string) => {
		setEditingIndex(index);
		setEditValue(value);
	};

	const startPageEditing = (value: number, index: string) => {
		setEditingPageIndex(index);
		setEditPageValue(value.toString());
	};

	// Bearbeitung beenden und Wert speichern
	const handleSave = async (index: string) => {
		mutate({ id: index, newValue: editValue });
		setEditingIndex("");
	};

	const handlePageSave = async (index: string) => {
		const pageNumber = parseInt(editPageValue);
		if (editPageValue === "" || pageNumber === 0) {
			mutate({ id: index, newPage: 0 });
		} else if (!isNaN(pageNumber) && pageNumber > 0) {
			mutate({ id: index, newPage: pageNumber });
		}
		setEditingPageIndex("");
	};

	// Tastatureingaben verarbeiten
	const handleKeyPress = (e: KeyboardEvent<HTMLDivElement>, index: string) => {
		if (e.key === "Enter") {
			handleSave(index);
		} else if (e.key === "Escape") {
			setEditingIndex("");
		}
	};

	const handlePageKeyPress = (e: KeyboardEvent<HTMLDivElement>, index: string) => {
		if (e.key === "Enter") {
			handlePageSave(index);
		} else if (e.key === "Escape") {
			setEditingPageIndex("");
		}
	};

	const handleNavigateToDetail = (settingName: string) => {
		navigate({
			to: "/extractedResult/$pitchBook/$kpi",
			params: {
				pitchBook: pdfId,
				kpi: settingName,
			},
			search: { from: from ?? undefined },
		});
	};

	return (
		<TableContainer component={Paper}>
			<Table>
				<TableHead>
					<TableRow>
						<TableCell width="30%">
							<strong>Kennzahl</strong>
						</TableCell>
						<TableCell width="55%">
							<strong>Wert</strong>
						</TableCell>
						<TableCell align="center" width="15%">
							<Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 1 }}>
								<strong>Seite</strong>
							</Box>
						</TableCell>
					</TableRow>
				</TableHead>

				<TableBody>
					{settings
						.filter((setting) => setting.active)
						.sort((a, b) => a.position - b.position)
						.map((setting) => ({
							setting: setting,
							extractedValues: data[setting.name.toUpperCase()] || [],
						}))
						.map((row) => {
							let borderColor = "transparent";
							const hasMultipleValues = row.extractedValues.length > 1;
							const hasNoValue =
								row.setting.mandatory &&
								(row.extractedValues.length === 0 ||
									row.extractedValues.at(0)?.entity === "");

							if (hasNoValue) {
								borderColor = "red";
							} else if (hasMultipleValues) {
								borderColor = "#f6ed48";
							}

							const currentPage = row.extractedValues.at(0)?.page ?? 0;
							const isPageHovered = hoveredPageIndex === row.setting.name;
							const canEditPage = !hasMultipleValues;

							return (
								<TableRow key={row.setting.name}>
									<TableCell>{row.setting.name}
										{row.setting.mandatory && (
											<span> *</span>
										)}
									</TableCell>
									<TableCell
										onClick={() => {
											// Only allow inline editing for non-multiple value cells
											if (!hasMultipleValues) {
												startEditing(
													row.extractedValues.at(0)?.entity || "",
													row.setting.name,
												);
											} else {
												// Navigate to detail page for multiple values
												handleNavigateToDetail(row.setting.name);
											}
										}}
									>
										{hasMultipleValues ? (
											<Tooltip
												title={
													<>
														<b>Problem</b>
														<br />
														Mehrere Werte für die Kennzahl gefunden.
													</>
												}
												placement="bottom"
												arrow
											>
												<Box
													sx={{
														border: `2px solid ${borderColor}`,
														borderRadius: 1,
														padding: "4px 8px",
														display: "flex",
														alignItems: "center",
														justifyContent: "space-between",
														width: "100%",
														cursor: "pointer",
														"&:hover": {
															backgroundColor: "#f5f5f5",
														},
													}}
												>
													<Box
														sx={{
															display: "flex",
															alignItems: "center",
															gap: 1,
															width: "100%",
														}}
													>
														<span>
															{row.extractedValues.at(0)?.entity || "—"}
														</span>
													</Box>
													<SearchIcon
														fontSize="small"
														sx={{ color: "#f6ed48" }}
													/>
												</Box>
											</Tooltip>
										) : (
											<Tooltip
												title={
													hasNoValue ? (
														<>
															<b>Problem</b>
															<br />
															Es wurden keine Kennzahlen gefunden. Bitte
															ergänzen!
														</>
													) : (
														""
													)
												}
												placement="bottom"
												arrow
											>
												<span>
													<Box
														sx={{
															border: `2px solid ${borderColor}`,
															borderRadius: 1,
															padding: "4px 8px",
															display: "flex",
															alignItems: "center",
															justifyContent: "space-between",
															width: "100%",
															cursor: "text",
														}}
													>
														<Box
															sx={{
																display: "flex",
																alignItems: "center",
																gap: 1,
																width: "100%",
															}}
														>
															{hasNoValue && (
																<ErrorOutlineIcon
																	fontSize="small"
																	color="error"
																/>
															)}
															{editingIndex === row.setting.name ? (
																<TextField
																	value={editValue}
																	onChange={(e) => setEditValue(e.target.value)}
																	onKeyDown={(e) =>
																		handleKeyPress(e, row.setting.name)
																	}
																	onBlur={() => handleSave(row.setting.name)}
																	autoFocus
																	size="small"
																	fullWidth
																	variant="standard"
																	sx={{ margin: "-8px 0" }}
																/>
															) : (
																<span>
																	{row.extractedValues.at(0)?.entity || "—"}
																</span>
															)}
														</Box>
														<EditIcon
															fontSize="small"
															sx={{ color: "#555", cursor: "pointer" }}
															onClick={(e) => {
																e.stopPropagation();
																startEditing(
																	row.extractedValues.at(0)?.entity || "",
																	row.setting.name,
																);
															}}
														/>
													</Box>
												</span>
											</Tooltip>
										)}
									</TableCell>
									<TableCell align="center">
										{editingPageIndex === row.setting.name ? (
											<TextField
												value={editPageValue}
												onChange={(e) => {
													const value = e.target.value;
													if (value === '' || /^\d+$/.test(value)) {
														setEditPageValue(value);
													}
												}}
												onKeyDown={(e) => handlePageKeyPress(e, row.setting.name)}
												onBlur={() => handlePageSave(row.setting.name)}
												autoFocus
												size="small"
												variant="standard"
												sx={{
													width: "60px",
													"& .MuiInput-input": {
														textAlign: "center"
													}
												}}
												inputProps={{
													min: 0,
													style: { textAlign: 'center' }
												}}
											/>
										) : (
											<>
												{currentPage > 0 ? (
													<Box
														sx={{
															display: "flex",
															alignItems: "center",
															justifyContent: "center",
															position: "relative",
															cursor: "pointer",
															borderRadius: "4px",
															minHeight: "32px",
															minWidth: "100px",
														}}
														onClick={() => {
															if (canEditPage) {
																startPageEditing(currentPage, row.setting.name);
															}
														}}
													>
														<Link
															component="button"
															onClick={(e) => {
																e.stopPropagation();
																const extractedValue = row.extractedValues.at(0);
																if (extractedValue?.page && extractedValue.page > 0) {
																	onPageClick?.(Number(extractedValue.page), extractedValue.entity || "");
																}
															}}
															sx={{ cursor: "pointer" }}
														>
															{currentPage}
														</Link>
													</Box>
												) : canEditPage ? (
													<Box
														sx={{
															display: "flex",
															alignItems: "center",
															justifyContent: "center",
															position: "relative",
															cursor: "pointer",
															minHeight: "32px",
															minWidth: "100px",
															borderRadius: "4px",
															backgroundColor: isPageHovered ? "#f8f9fa" : "transparent",
														}}
														onMouseEnter={() => setHoveredPageIndex(row.setting.name)}
														onMouseLeave={() => setHoveredPageIndex("")}
														onClick={() => startPageEditing(0, row.setting.name)}
													>
														<span style={{ color: "#999" }}>...</span>
														<EditIcon
															fontSize="small"
															sx={{
																position: "absolute",
																left: "70px",
																color: "black",
																cursor: "pointer",
																opacity: 0.7,
																transition: "opacity 0.2s ease",
															}}
														/>
													</Box>
												) : (
													""
												)}
											</>
										)}
									</TableCell>
								</TableRow>
							);
						})}
				</TableBody>
			</Table>
		</TableContainer>
	);
}