import { useCallback, useEffect, useState } from "react";
import { useSubscribe } from "react-eventizer";
import { useTranslation } from "react-i18next";

import { Loader } from "@/common/components/Loader";
import { DialogDefaultHeader } from "@/contexts/dialog/ui/DialogDefaultHeader";
import { useNextAlarmScopeStatus } from "@/contracts/alarm-scope-status";
import {
	useGetAlarmScopeById,
	useGetAlarmScopeList,
} from "@/contracts/alarm-scopes";
import {
	getAlarmListByScope,
	useGetAlarmListByScope,
} from "@/contracts/alarms";
import { useGetAreaList } from "@/contracts/areas";
import { getAsset, useGetAsset } from "@/contracts/assets";
import { useGetCameraList } from "@/contracts/cameras";
import {
	AlarmModel,
	AlarmScopeModel,
	AssetModel,
} from "@/contracts/client.schemas";
import { useGetEventList } from "@/contracts/events";
import { useGetResponsiblePersonList } from "@/contracts/responsible-persons";
import { useGetZoneList } from "@/contracts/zones";
import { getAlarmScopeStatus, getStepByStatus } from "@/lib/alarm-scope.helper";
import { DialogContent, DialogTitle } from "@/shared";

import { AlarmDialogContext } from "../lib/AlarmDialogContext";
import { AlarmScopeWithAsset } from "../model/AlarmDialogContextType";
import { Steps } from "../model/Steps";

import { AlarmDialog } from "./AlarmDialog";

// Внутренний компонент с доступом к контексту
export function AlarmDialogProvider({
	initialScope,
	initialStep,
	onNext,
}: {
	initialScope: AlarmScopeModel;
	initialStep: Steps;
	onNext: () => void;
}) {
	const { t } = useTranslation("translation");
	const [currentScopeId, setCurrentScopeId] = useState(initialScope.id);
	const [currentAssetId, setCurrentAssetId] = useState(initialScope.assetId);
	const [responsibleComment, setResponsibleComment] = useState<string>("");
	const [step, setStep] = useState<Steps>(initialStep);

	// Загружаем все активные scopes
	const { data: allScopesList = [] } = useGetAlarmScopeList({
		query: { initialData: [] },
	});

	// Данные для всех scopes с их ассетами
	const [allScopesWithAssets, setAllScopesWithAssets] = useState<
		AlarmScopeWithAsset[]
	>([]);

	// Загружаем ассеты для всех scopes
	useEffect(() => {
		async function loadScopesWithAssets() {
			const scopesWithAssets: AlarmScopeWithAsset[] = await Promise.all(
				allScopesList.map(async (scope) => {
					try {
						const asset = await getAsset(scope.assetId);
						const alarms = await getAlarmListByScope({
							ScopeId: scope.id,
						});
						return {
							scope,
							asset,
							alarmsCount: alarms?.length ?? 0,
						};
					} catch {
						return {
							scope,
							asset: {} as AssetModel,
							alarmsCount: 0,
						};
					}
				}),
			);
			setAllScopesWithAssets(scopesWithAssets);
		}

		if (allScopesList.length > 0) {
			loadScopesWithAssets();
		}
	}, [allScopesList]);

	const switchToScope = useCallback(
		(scopeId: string) => {
			const targetScope = allScopesList.find((s) => s.id === scopeId);
			if (targetScope && scopeId !== currentScopeId) {
				setCurrentScopeId(scopeId);
				setCurrentAssetId(targetScope.assetId);
				setStep("accept"); // Сбрасываем шаг при переключении
				setResponsibleComment(""); // Сбрасываем комментарий
			}
		},
		[allScopesList, currentScopeId],
	);

	const {
		data: scope,
		refetch: refetchScope,
		isLoading: isLoadingScope,
	} = useGetAlarmScopeById(currentScopeId);
	const { data: asset, isLoading: isLoadingAsset } =
		useGetAsset(currentAssetId);
	const {
		data: alarms,
		isLoading: isLoadingAlarms,
		refetch: refetchAlarms,
	} = useGetAlarmListByScope({
		ScopeId: currentScopeId,
	});
	const { data: events, isLoading: isLoadingEvents } = useGetEventList({
		AssetId: currentAssetId,
	});
	const { data: areas, isLoading: isLoadingAreas } = useGetAreaList({
		AssetId: currentAssetId,
	});
	const { data: zones, isLoading: isLoadingZones } = useGetZoneList({
		AssetId: currentAssetId,
	});
	const { data: cameras, isLoading: isLoadingCameras } = useGetCameraList({
		AssetId: currentAssetId,
	});
	const { data: responsiblePersons, isLoading: isLoadingResponsiblePersons } =
		useGetResponsiblePersonList({
			AssetId: currentAssetId,
		});

	const nextMutator = useNextAlarmScopeStatus();

	useSubscribe("ALARMS.CREATED", handleNewAlarmCreated);
	async function handleNewAlarmCreated(alarm: AlarmModel) {
		try {
			if (alarm.scopeId === currentScopeId) {
				refetchAlarms();
				refetchScope();
			}
		} catch (error) {
			console.error("Error handling new alarm:", error);
		}
	}

	useEffect(() => {
		if (scope && scope.id === currentScopeId) {
			const scopeStatus = getAlarmScopeStatus(scope);
			setStep(getStepByStatus(scopeStatus));
		}
	}, [scope, currentScopeId]);

	async function next(isReal?: boolean) {
		try {
			const newStatus = await nextMutator.mutateAsync({
				alarmScopeId: currentScopeId,
				data: {
					isReal: isReal ?? null,
				},
			});

			onNext();
			if (newStatus.status !== "Resolved") {
				await refetchScope();
			} else {
				setStep("completed");
			}
		} catch (error) {
			console.error("Error changing alarm status:", error);
		}
	}

	if (
		!scope ||
		!step ||
		isLoadingScope ||
		isLoadingAsset ||
		isLoadingAlarms ||
		isLoadingEvents ||
		isLoadingAreas ||
		isLoadingZones ||
		isLoadingCameras ||
		isLoadingResponsiblePersons
	) {
		return (
			<DialogContent size="lg">
				<DialogDefaultHeader />
				<DialogTitle>
					<div className="flex items-center justify-center gap-4 text-center text-gray-500">
						<Loader />
						{t("alarmDialog.loadingData")}
					</div>
				</DialogTitle>
			</DialogContent>
		);
	}

	const scopeStatus = getAlarmScopeStatus(scope);

	return (
		<AlarmDialogContext.Provider
			value={{
				asset: asset!,
				alarms: alarms!,
				scope,
				scopeStatus,
				step,
				next,
				events: events!.items,
				responsiblePersons: responsiblePersons!.items,
				areas: areas!.items,
				zones: zones!.items,
				cameras: cameras!.items,
				responsibleComment,
				setResponsibleComment,
				allScopes: allScopesWithAssets,
				switchToScope,
			}}
		>
			<AlarmDialog />
		</AlarmDialogContext.Provider>
	);
}
