import { useCustom, useShow, useApiUrl } from "@refinedev/core";
import { useParams } from "react-router";
import { createContext, ReactNode, useContext, useEffect, useMemo, useState } from "react";
import { RouteData, SightData, StationData, StationPatchData } from "./types";
import { axiosInstance } from "../../providers/data";



const MapDataContext = createContext<{
    originalRouteData?: RouteData,
    originalStationData?: StationData[],
    originalSightData?: SightData[],
    routeData?: RouteData,
    stationData?: StationData[],
    sightData?: SightData[],

	isRouteLoading: boolean,
	isStationLoading: boolean,
	isSightLoading: boolean,
	setScaleRange: (min: number, max: number) => void,
	setMapRotation: (rotation: number) => void,
	setMapCenter: (x: number, y: number) => void,
	setStationOffset: (stationId: number, x: number, y: number) => void,
	saveChanges: () => void,
}>({
    originalRouteData: undefined,
    originalStationData: undefined,
    originalSightData: undefined,
    routeData: undefined,
    stationData: undefined,
    sightData: undefined,

	isRouteLoading: true,
	isStationLoading: true,
	isSightLoading: true,
	setScaleRange: () => {},
	setMapRotation: () => {},
	setMapCenter: () => {},
	setStationOffset: () => {},
	saveChanges: () => {},
});

export function MapDataProvider({ children }: Readonly<{ children: ReactNode }>) {
	const { id: routeId } = useParams<{ id: string }>();
	const apiUrl = useApiUrl();

	const [originalRouteData, setOriginalRouteData] = useState<RouteData>();
	const [originalStationData, setOriginalStationData] = useState<StationData[]>();
	const [originalSightData, setOriginalSightData] = useState<SightData[]>();

	const [routeData, setRouteData] = useState<RouteData>();
	const [stationData, setStationData] = useState<StationData[]>();
	const [sightData, setSightData] = useState<SightData[]>();

	const [routeChanges, setRouteChanges] = useState<RouteData>({} as RouteData);
	const [stationChanges, setStationChanges] = useState<StationPatchData[]>([]);
	const [sightChanges, setSightChanges] = useState<SightData[]>([]);
	

	const { data: routeQuery, isLoading: isRouteLoading } = useCustom({
	  url: `${apiUrl}/route/${routeId}`,
	  method: 'get',
	});
	const { data: stationQuery, isLoading: isStationLoading } = useCustom({
	  url: `${apiUrl}/route/${routeId}/station`,
	  method: 'get',
	});
	const { data: sightQuery, isLoading: isSightLoading } = useCustom({
	  url: `${apiUrl}/route/${routeId}/sight`,
	  method: 'get',
	});
	useEffect(() => {
		// if not undefined, set original data 
		if(routeQuery?.data) setOriginalRouteData(routeQuery.data as RouteData);
		if(stationQuery?.data) setOriginalStationData(stationQuery.data as StationData[]);
		if(sightQuery?.data) setOriginalSightData(sightQuery.data as SightData[]);
		console.log("queries", routeQuery, stationQuery, sightQuery);
	}, [routeQuery, stationQuery, sightQuery]);

	useEffect(() => {
		// combine changes with original data
		if(originalRouteData) setRouteData({...originalRouteData, ...routeChanges});
		if(originalStationData) setStationData(originalStationData);
		if(originalSightData) setSightData(originalSightData);
	}, [
		originalRouteData, originalStationData, originalSightData,
		routeChanges, stationChanges, sightChanges
	]);

	useEffect(() => {
		console.log("data", routeData, stationData, sightData);
	}, [routeData, stationData, sightData]);

	function setScaleRange(min: number, max: number) {
		setRouteChanges((prev) => {
			return {...prev, scale_min: min, scale_max: max};
		});
	}

	function setMapRotation(rotation: number) {
		setRouteChanges((prev) => {
			return {...prev, rotate: rotation};
		});
	}

	function setMapCenter(x: number, y: number) {
		setRouteChanges((prev) => {
			return {...prev, center_latitude: x, center_longitude: y}
		});
	}

	async function saveChanges() {
		console.log("saveChanges", routeData);
		const response = await axiosInstance.patch(`/route/${routeId}`, routeData);
		saveStationChanges();
	}

	async function saveStationChanges() {
		console.log("saveStationChanges", stationChanges);
		for(const station of stationChanges) {
			const response = await axiosInstance.patch(`/route/${routeId}/station`, station);
			console.log("response", response);
		}
	}

	function setStationOffset(stationId: number, x: number, y: number) {
		setStationChanges((prev) => {
			let found = prev.find((station) => station.station_id === stationId);
			if(found) {
				found.offset_x = x;
				found.offset_y = y;

				return prev.map((station) => {
					if(station.station_id === stationId) {
						return found;
					}
					return station;
				});
			} else {
				const foundStation = stationData?.find((station) => station.id === stationId);
				if(foundStation) {
					return [...prev, {
						station_id: stationId,
						offset_x: x, offset_y: y,
						transfers: foundStation.transfers
					}];
				}
				return prev;
			}
		});
	}

	useEffect(() => {
		console.log("stationChanges", stationChanges);
	}, [stationChanges]);

	const value = useMemo(() => ({
		originalRouteData: originalRouteData,
		originalStationData: originalStationData,
		originalSightData: originalSightData,
		routeData: routeData,
		stationData: stationData,
		sightData: sightData,
		isRouteLoading,
		isStationLoading,
		isSightLoading,
		setScaleRange,
		setMapRotation,
		setMapCenter,
		saveChanges,
		setStationOffset,
	}), [originalRouteData, originalStationData, originalSightData, routeData, stationData, sightData, isRouteLoading, isStationLoading, isSightLoading]);
	
	return (
        <MapDataContext.Provider value={value}>
            {children}
        </MapDataContext.Provider>
    );
}

export const useMapData = () => {
    const context = useContext(MapDataContext);
    if (!context) {
        throw new Error('useMapData must be used within a MapDataProvider');
    }
    return context;
};