import {
	createDashboard,
	getDashboards,
	updateDashboard,
} from '@/api/dashboards'
import { createDashboardContent } from '@/utils/createDashboardContent'
import { parseDashboard } from '@/utils/parseDashboard'
import { useEffect, useMemo, useState } from 'preact/hooks'
import { useQuery, useQueryClient } from 'react-query'
import { DashboardGrid } from './components/DashboardGrid'
import { DashboardHeader } from './components/DashboardHeader'
import { GRID_H_SNAP, GRID_WIDTH } from './constants'
import { DashboardContextProvider } from './contexts/DashboardContext'
import { BoxDefinition } from './types'

export const NewDashboardPage = () => {
	const queryClient = useQueryClient()
	const dashboards = useQuery(['/dashboards'], getDashboards)
	const dashboard = dashboards.data?.find((i) => i.id === 'default')

	const dashboardContent = useMemo(
		() => (dashboard ? parseDashboard(dashboard.contents) : undefined),
		[dashboard]
	)

	const [boxes, setBoxes] = useState(dashboardContent?.boxes ?? [])

	const handleChange = (cb: (boxes: BoxDefinition[]) => BoxDefinition[]) => {
		const newBoxes = cb(boxes)

		setBoxes(newBoxes)

		if (dashboard && dashboardContent) {
			updateDashboard({
				id: dashboard?.id,
				contents: {
					...dashboardContent,
					boxes: newBoxes,
				},
			})
		}
	}

	const handleRefresh = () => {
		queryClient.invalidateQueries(['/sensor/values'])
		queryClient.invalidateQueries(['/sensor/values/latest'])
	}

	const handleNewBox = () => {
		const box = {
			id: new Date().getTime().toString(),
			x: 0,
			y: 0,
			w: GRID_WIDTH,
			h: GRID_H_SNAP * 20,
		}

		const otherBoxes = boxes.map((b) => {
			b.y += 200

			return b
		})

		handleChange(() => [box, ...otherBoxes])
	}

	// Terrible code - ensure there's default dashboard
	useEffect(() => {
		if (dashboards.data && !dashboard) {
			createDashboard({
				id: 'default',
				contents: createDashboardContent(),
			}).then(() => {
				dashboards.refetch()
			})
		}
	}, [dashboards.data, dashboard])

	useEffect(() => {
		setBoxes(dashboardContent?.boxes ?? [])
	}, [dashboardContent])

	return (
		<DashboardContextProvider>
			<div className="dashboard">
				<DashboardHeader onRefresh={handleRefresh} onNewBox={handleNewBox} />
				<DashboardGrid boxes={boxes} onChange={handleChange} />
			</div>
		</DashboardContextProvider>
	)
}
