import * as React from 'react'
import apiFetch from '@wordpress/api-fetch'

import {
	addQueryArgs,
} from '@wordpress/url'

import {
	__experimentalSanitizeBlockAttributes as sanitizeBlockAttributes,
	// @ts-expect-error
} from '@wordpress/blocks'

import {
	QueryClient,
	defaultShouldDehydrateQuery,
} from '@tanstack/react-query'

import {
	PersistQueryClientProvider,
} from '@tanstack/react-query-persist-client'

import {
	createAsyncStoragePersister,
} from '@tanstack/query-async-storage-persister'

import localforage from 'localforage'

import type {
	APIResponse,
	tBlockAttributes,
} from '@ska/shared'

import {
	debugWarn,
} from '@ska/utils'

export const queryClient = new QueryClient({
	defaultOptions: {
		queries: {
			refetchOnWindowFocus: false,
			staleTime: Infinity, // Fetch once and then keep using it.
			gcTime: Infinity, // Don't remove from cache (by default after 5min) once the component using it unmounts.
			meta: {
				persist: false,
			},
		},
	},
})

const asyncStoragePersister = createAsyncStoragePersister({
	storage: localforage,
	key: 'ska-blocks',
})

export const QueryClientProvider: React.FC<React.PropsWithChildren> = ({children}) => {
	return (
		<PersistQueryClientProvider
			client={queryClient}
			persistOptions={{
				persister: asyncStoragePersister,
				dehydrateOptions: {
					shouldDehydrateQuery: query => {
						const persist = !!query?.meta?.persist
						return defaultShouldDehydrateQuery(query) && persist !== false
					},
				},
			}}
		>
			{children}
		</PersistQueryClientProvider>
	)
}

export const fetchIconCollections = async () => {

	const response = await apiFetch<APIResponse>({path: `/ska-blocks/v1/icons`})

	if(response.success) {
		return response.value as string[]
	}

	throw new Error(response.message)
}

export const fetchIcons = async (collection?: string) => {

	const response = await apiFetch<APIResponse>({path: `/ska-blocks/v1/icons/${collection}`})

	if(response.success) {
		return response.value as string[]
	}

	throw new Error(response.message)
}

export const fetchIcon = async (collection: string, icon: string) => {

	const response = await apiFetch<APIResponse>({path: addQueryArgs(`/ska-blocks/v1/icons/${collection}/svg`, {icon})})

	if(response.success) {
		return response.value as string
	}

	throw new Error(response.message)
}

export const fetchFonts = async (path: string) => {

	const response = await apiFetch<APIResponse>({path: `/ska-blocks/v1/fonts/${path}`})

	if(response.success) {
		return response.value as any[]
	}

	throw new Error(response.message)
}

export const renderBlock = async (args: {
	blockName: string
	attributes: Partial<tBlockAttributes>
	signal?: AbortSignal
}) => {

	const {
		blockName = '',
		attributes = {},
		signal,
	} = args

	let sanitizedAttributes = {}
	try {
		// Throws when block type is not registered
		sanitizedAttributes = sanitizeBlockAttributes(blockName, attributes)
	} catch(e) {
		debugWarn('Failed sanitizing block attributes', {blockName, attributes, e})
	}

	const response = await apiFetch<{rendered: string}>({
		method: 'POST',
		path: addQueryArgs(`/wp/v2/block-renderer/${blockName}`, {
			context: 'edit',
		}),
		data: {
			attributes: sanitizedAttributes,
		},
		signal,
	})

	if(response.rendered) {
		return response.rendered
	}

	throw new Error('Failed rendering block.')
}
