import * as React from 'react'
import {__, _x} from '@wordpress/i18n'
import cx from 'classnames'

import {
	useMemo,
} from '@wordpress/element'

import {
	ToggleControl,
	__experimentalVStack as VStack,
} from '@wordpress/components'

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

import Fuse from 'fuse.js'

import {
	Search,
	SearchResult,
} from '@ska/components'

import {
	usePluginPreference,
} from '@ska/plugin'

import {
	fetchModels,
} from '../../api'

import type {
	OpenRouterModel,
} from '../../types'

import './style.scss'

export interface ModelPickerProps {
	value?: string
	onChange: (nextValue: string) => void
	showFilters?: boolean
	/** `@tanstack/react-query` query client provider. */
	QueryClientProvider: React.FC<React.PropsWithChildren>
}

const NO_MODELS: OpenRouterModel[] = []

const ModelPicker: React.FC<Omit<ModelPickerProps, 'QueryClientProvider'>> = ({
	value,
	onChange,
	showFilters = false,
}) => {

	const [filters = {}, setFilters] = usePluginPreference('aiModelFilters')

	const {
		free = true,
	} = filters

	const {
		isLoading,
		isFetched,
		data = NO_MODELS,
	} = useQuery({
		queryKey: ['models'],
		queryFn: ({signal}) => fetchModels({signal}),
		retry: 3,
		gcTime: 1000 * 60 * 30,
	})

	const fuse = useMemo(() => {

		const models = data.filter(model => {

			const {
				architecture,
			} = model

			const {
				input_modalities = [],
				output_modalities = [],
			} = architecture || {}

			return input_modalities.includes('text') && output_modalities.includes('text')
		})

		return new Fuse(models, {
			keys: ['id', 'name', 'description'],
		})
	}, [data])

	const getResults = (searchTerm: string) => {
		return fuse
			.search(searchTerm)
			.map(r => r.item)
			.filter(model => {
				return free ? !Object.values(model.pricing).some(price => price !== '0') : true
			})
			.map(model => {

				const {
					id,
					name,
					canonical_slug,
				} = model

				return {
					id,
					title: name,
					content: canonical_slug,
				} as SearchResult
			})
	}

	const onSelect = async (result: SearchResult) => {
		const {id = ''} = result
		onChange(id.toString())
	}

	return (
		<VStack
			className={cx('ska-model-picker', {
				'ska-model-picker--has-value': !!value,
			})}
		>
			{showFilters && <>
				<ToggleControl
					label={__('Only show free models', 'ska-blocks')}
					checked={free}
					onChange={() => setFilters({...filters, free: !free})}
					__nextHasNoMarginBottom
				/>
			</>}
			<Search
				key={`search-${isFetched ? '1' : '0'}-${free ? '1' : '0'}`}
				getResults={getResults}
				getResultIcon={() => null}
				onSelect={onSelect}
				actionInputProps={{
					label: __('Search for a model', 'ska-blocks'),
					placeholder: value || __('Search models…', 'ska-blocks'),
					actionLabel: __('Search', 'ska-blocks'),
					loading: isLoading,
				}}
			/>
		</VStack>
	)
}

export {ModelPicker}

const ModelPickerComponent: React.FC<ModelPickerProps> = ({QueryClientProvider, ...props}) => {
	return (
		<QueryClientProvider>
			<ModelPicker {...props} />
		</QueryClientProvider>
	)
}

export default ModelPickerComponent
