export interface GoogleMapsLocationConfig {
	enabled?: boolean | null;
	region?: string | null;
	publicEnabled?: boolean | null;
	serverApiKey?: string | null;
}

export interface GoogleMapsLocationCapability {
	enabled: boolean;
	reason: "configured" | "missing_server_api_key" | "disabled";
	region: string;
}

export interface GoogleMapsPlaceLabelSource {
	displayName?: string | { text?: string | null } | null;
	formattedAddress?: string | null;
	name?: string | null;
	predictionText?: string | null;
}

export interface GoogleMapsSuggestion {
	formattedAddress?: string;
	placeId?: string;
	text: string;
}

const DEFAULT_GOOGLE_MAPS_REGION = "us";

const normalizeConfigValue = (value?: string | null) => {
	const trimmedValue = value?.trim();
	return trimmedValue ? trimmedValue : null;
};

const getDisplayNameText = (
	displayName?: string | { text?: string | null } | null,
) => {
	if (typeof displayName === "string") {
		return normalizeConfigValue(displayName);
	}

	return normalizeConfigValue(displayName?.text);
};

const parseEnabledValue = (value?: string | null) => {
	const normalizedValue = normalizeConfigValue(value)?.toLowerCase();

	if (!normalizedValue) {
		return true;
	}

	return !["0", "false", "no", "off"].includes(normalizedValue);
};

export const getGoogleMapsLocationCapability = (
	config: GoogleMapsLocationConfig = {},
): GoogleMapsLocationCapability => {
	const enabled =
		typeof config.enabled === "boolean"
			? config.enabled
			: typeof config.publicEnabled === "boolean"
				? config.publicEnabled
				: parseEnabledValue(
						process.env.NEXT_PUBLIC_GOOGLE_MAPS_AUTOCOMPLETE_ENABLED,
					);
	const serverApiKey = normalizeConfigValue(
		config.serverApiKey ?? process.env.GOOGLE_MAPS_API_KEY,
	);
	const region =
		normalizeConfigValue(config.region ?? process.env.GOOGLE_MAPS_REGION) ??
		DEFAULT_GOOGLE_MAPS_REGION;

	if (!enabled) {
		return {
			enabled: false,
			reason: "disabled",
			region,
		};
	}

	if (typeof window !== "undefined") {
		return {
			enabled: true,
			reason: "configured",
			region,
		};
	}

	if (!serverApiKey) {
		return {
			enabled: false,
			reason: "missing_server_api_key",
			region,
		};
	}

	return {
		enabled: true,
		reason: "configured",
		region,
	};
};

export const getGoogleMapsServerApiKey = () =>
	normalizeConfigValue(process.env.GOOGLE_MAPS_API_KEY);

export const getGoogleMapsPlaceLabel = (source: GoogleMapsPlaceLabelSource) => {
	return (
		normalizeConfigValue(source.predictionText) ??
		getDisplayNameText(source.displayName) ??
		normalizeConfigValue(source.formattedAddress) ??
		normalizeConfigValue(source.name) ??
		""
	);
};

export const getLocationAutocompletePlaceholder = (
	capability: GoogleMapsLocationCapability,
) => {
	return capability.enabled
		? "Search Google Maps or type a location"
		: "Location";
};

interface GooglePlacesAutocompleteResponse {
	suggestions?: Array<{
		placePrediction?: {
			place?: string;
			placeId?: string;
			text?: { text?: string | null };
			structuredFormat?: {
				mainText?: { text?: string | null };
				secondaryText?: { text?: string | null };
			};
		};
	}>;
}

export const mapGooglePlacesSuggestions = (
	payload: GooglePlacesAutocompleteResponse,
): GoogleMapsSuggestion[] => {
	const suggestions: GoogleMapsSuggestion[] = [];

	for (const suggestion of payload.suggestions ?? []) {
		const placePrediction = suggestion.placePrediction;
		const text =
			normalizeConfigValue(placePrediction?.text?.text) ??
			normalizeConfigValue(placePrediction?.structuredFormat?.mainText?.text) ??
			"";

		if (!text) {
			continue;
		}

		suggestions.push({
			formattedAddress:
				normalizeConfigValue(
					placePrediction?.structuredFormat?.secondaryText?.text,
				) ?? undefined,
			placeId:
				normalizeConfigValue(placePrediction?.placeId) ??
				normalizeConfigValue(
					placePrediction?.place?.replace(/^places\//, ""),
				) ??
				undefined,
			text,
		});
	}

	return suggestions;
};
