import { useQueryClient } from "@tanstack/react-query";
import { FC, useState } from "react";
import { useTranslation } from "react-i18next";

import { useGetAsset } from "@/contracts/assets";
import { useGetAssetGroup } from "@/contracts/assets-groups";
import {
	getGetCallListQueryKey,
	useCreateCall,
	useGetCallList,
} from "@/contracts/calls";
import { CallResult } from "@/contracts/client.schemas";
import { formatDateTime } from "@/services/time.service";
import { Button, ConfirmDialog } from "@/shared";

import { useAlarmDialogContext } from "../../lib/useAlarmDialogContext";
import { AssetAsPersonId, ResponsibleCall } from "../ResponsibleCall";

export const ResponsibleCallsStep: FC = () => {
	const { responsiblePersons, next, scope, setResponsibleComment } =
		useAlarmDialogContext();
	const [currentPersonId, setCurrentPersonId] = useState<string | null>(null);
	const [callNote, setCallNote] = useState("");
	const [showConfirmDialog, setShowConfirmDialog] = useState(false);
	const [showNextStepConfirmDialog, setShowNextStepConfirmDialog] =
		useState(false);
	const [pendingResult, setPendingResult] = useState<CallResult | null>(null);
	const {
		data: { items: calls },
		refetch: refetchGetCalls,
		isLoading: isLoadingCalls,
	} = useGetCallList(
		{
			AlarmScopeId: scope.id,
		},
		{
			query: {
				initialData: {
					items: [],
					total: 0,
				},
			},
		},
	);
	const createCall = useCreateCall({
		mutation: {
			onSuccess: () => {
				return refetchGetCalls();
			},
		},
	});
	const { t } = useTranslation("translation");
	const { data: asset } = useGetAsset(scope.assetId);
	const { data: assetGroup } = useGetAssetGroup(asset?.groupIds?.[0] || "", {
		query: {
			enabled: !!asset?.groupIds?.[0],
		},
	});
	const queryClient = useQueryClient();

	const processCallEnd = async (result: CallResult, isConfirmed: boolean) => {
		if (!currentPersonId) return;

		try {
			await createCall.mutateAsync({
				data: {
					alarmScopeId: scope.id,
					responsiblePersonId: currentPersonId,
					commentary: callNote || "-",
					isConfirmedRealAlarm: isConfirmed,
					result,
				},
			});

			await queryClient.invalidateQueries({
				queryKey: getGetCallListQueryKey(),
			});
		} catch (error) {
			console.error("Ошибка при фиксации звонка:", error);
		}

		setCurrentPersonId(null);
		setCallNote("");
	};

	const handleConfirmAlarm = async () => {
		setShowConfirmDialog(false);
		if (pendingResult) {
			await processCallEnd(pendingResult, true);
			setPendingResult(null);
		}
	};

	const handleCancelAlarm = async () => {
		setShowConfirmDialog(false);
		if (pendingResult) {
			await processCallEnd(pendingResult, false);
			setPendingResult(null);
		}
	};

	const handleConfirmNextStep = async (confirmed: boolean) => {
		setShowNextStepConfirmDialog(false);
		if (confirmed) {
			await processContinue();
		}
	};

	const processContinue = async () => {
		const existingSummary =
			calls.map((call) => {
				const person = responsiblePersons.find(
					(p) => p.id === call.responsiblePersonId,
				);
				const personInfo = person
					? `${person.name}${person.note ? ` (${person.note})` : ""}`
					: t("unknown");
				const resultText = call.isConfirmedRealAlarm
					? t("confirmedAlarm")
					: t("looksFalse");
				return {
					date: new Date(call.startedAt),
					text: `${formatDateTime(new Date(call.startedAt))}: ${personInfo} - ${resultText}${call.commentary ? ` - ${call.commentary}` : ""}`,
				};
			}) || [];

		const allCalls = [...existingSummary].sort(
			(a, b) => b.date.getTime() - a.date.getTime(),
		);
		const summary = allCalls.map((call) => call.text).join("\n");

		setResponsibleComment(summary);

		// Сбрасываем кэш звонков перед переходом, чтобы следующий шаг получил свежие данные
		await queryClient.resetQueries({
			queryKey: getGetCallListQueryKey({ AlarmScopeId: scope.id }),
		});

		await next();
	};

	const handleContinueClick = () => {
		setShowNextStepConfirmDialog(true);
	};

	const handleStartCall = (personId: string) => {
		setCurrentPersonId(personId);
	};

	const handleEndCall = async (_personId: string, result: CallResult) => {
		if (!currentPersonId) return;

		if (result === "Answered") {
			setPendingResult(result);
			setShowConfirmDialog(true);
		} else {
			await processCallEnd(result, false);
		}
	};

	return (
		<div className="flex h-full w-full flex-col space-y-4 overflow-hidden p-6">
			<div className="flex-shrink-0 space-y-2 text-center">
				<h2 className="text-2xl font-bold text-gray-800">
					{t("responsibleCallsTitle")}
				</h2>
				<p className="text-gray-600">
					{t("responsibleCallsDescription")}
				</p>
			</div>

			<div className="flex-1 space-y-3 overflow-y-auto pr-2">
				{asset && (asset.ownerPhone1 || asset.ownerPhone2) && (
					<ResponsibleCall
						name={t("mainResponsiblePerson")}
						phone1={asset.ownerPhone1}
						phone2={asset.ownerPhone2}
						personId={AssetAsPersonId}
						calls={calls}
						handleStartCall={handleStartCall}
						handleEndCall={handleEndCall}
						currentPersonId={currentPersonId}
						hasPBX={assetGroup?.hasPBX === true}
					/>
				)}

				{responsiblePersons.map((person) => (
					<ResponsibleCall
						key={person.id}
						name={person.name}
						note={person.note}
						phone1={person.phone1}
						phone2={person.phone2}
						personId={person.id}
						calls={calls}
						handleStartCall={handleStartCall}
						handleEndCall={handleEndCall}
						currentPersonId={currentPersonId}
						hasPBX={assetGroup?.hasPBX === true}
					/>
				))}

				{isLoadingCalls && (
					<div className="rounded-lg border border-gray-200 bg-gray-50 p-4">
						<p className="text-sm text-gray-500">
							{t("loadingData")}
						</p>
					</div>
				)}

				{calls.length > 0 ? (
					<div className="mt-4 space-y-3">
						<p className="font-medium text-gray-900">
							{t("callHistory")}
						</p>
						<div className="space-y-2">
							{(() => {
								const existingItems =
									calls?.map((call) => ({
										type: "existing" as const,
										data: call,
										date: new Date(call.startedAt),
										result: call.result,
									})) || [];
								const combined = [...existingItems].sort(
									(a, b) =>
										b.date.getTime() - a.date.getTime(),
								);

								return combined.map((item) => {
									if (item.type === "existing") {
										const call = item.data;
										const person = responsiblePersons.find(
											(p) =>
												p.id ===
												call.responsiblePersonId,
										);
										return (
											<div
												key={call.id}
												className="rounded-lg border border-gray-200 bg-white p-3"
											>
												<div className="flex flex-col gap-1 text-sm">
													<div className="flex items-center gap-2">
														<span className="text-gray-500">
															{formatDateTime(
																new Date(
																	call.startedAt,
																),
															)}
														</span>
														<span>-</span>
														<span className="font-medium text-gray-900">
															{person?.name ||
																t("unknown")}
														</span>
														{person?.note && (
															<span className="text-xs text-gray-500">
																({person.note})
															</span>
														)}
													</div>
													<div className="flex items-center gap-2">
														<span className="text-gray-600">
															{t("result")}:
														</span>
														<span className="font-medium">
															{call.result ===
															"Answered"
																? call.isConfirmedRealAlarm
																	? t(
																			"confirmedAlarm",
																		)
																	: t(
																			"looksFalse",
																		)
																: call.result ===
																	  "NoAnswer"
																	? t(
																			"noAnswer",
																		)
																	: call.result ===
																		  "Busy"
																		? t(
																				"busy",
																			)
																		: ""}
														</span>
													</div>
												</div>
												{call.commentary && (
													<div className="mt-2 border-t pt-2 text-xs text-gray-600">
														{call.commentary}
													</div>
												)}
											</div>
										);
									} else {
										const log = item.data;
										const person = responsiblePersons.find(
											(p) =>
												p.id ===
												log.responsiblePersonId,
										);
										return (
											<div
												key={`local-${item.date}`}
												className="rounded-lg border border-gray-200 bg-white p-3"
											>
												<div className="flex flex-col gap-1 text-sm">
													<div className="flex items-center gap-2">
														<span className="text-gray-500">
															{formatDateTime(
																new Date(
																	log.startedAt,
																),
															)}
														</span>
														<span>-</span>
														<span className="font-medium text-gray-900">
															{person?.name}
														</span>
														{person?.note && (
															<span className="text-xs text-gray-500">
																({person.note})
															</span>
														)}
													</div>
													<div className="flex items-center gap-2">
														<span className="text-gray-600">
															{t("result")}:
														</span>
														<span className="font-medium">
															{log.isConfirmedRealAlarm
																? t(
																		"confirmedAlarm",
																	)
																: t(
																		"looksFalse",
																	)}
														</span>
													</div>
												</div>
												{log.commentary && (
													<div className="mt-2 border-t pt-2 text-xs text-gray-600">
														{log.commentary}
													</div>
												)}
											</div>
										);
									}
								});
							})()}
						</div>
					</div>
				) : null}
			</div>

			<div className="flex flex-shrink-0 justify-center border-t pt-4">
				<Button
					size="lg"
					onClick={handleContinueClick}
					className="mt-4 px-8"
					disabled={
						calls.length === 0 && (!calls || calls.length === 0)
					}
				>
					{t("continue")} ({calls.length} {t("calls")})
				</Button>
			</div>

			<ConfirmDialog
				open={showNextStepConfirmDialog}
				onOpenChange={setShowNextStepConfirmDialog}
				onConfirm={() => handleConfirmNextStep(true)}
			/>

			<ConfirmDialog
				open={showConfirmDialog}
				onOpenChange={(open) => {
					if (!open && pendingResult) {
						handleCancelAlarm();
					} else {
						setShowConfirmDialog(open);
					}
				}}
				onConfirm={handleConfirmAlarm}
				onCancel={handleCancelAlarm}
				title={t("alarmConfirmation")}
				description={t("responsibleConfirmedAlarm")}
			/>
		</div>
	);
};
