import type { SlDialog } from '@shoelace-style/shoelace'
import type { EntityID } from '@wovin/core'
import type { Accessor, Component } from 'solid-js'
import { ThreadInMemory } from '@wovin/core'
import { action, observable, untracked } from '@wovin/core/mobx'
import { Logger } from 'besonders-logger'
import { compareAsc } from 'date-fns'
import { createRenderEffect, createSignal, For } from 'solid-js'
import { useAgent } from '../data/agent/AgentState'
import { tiptapToPlaintext } from '../data/note3-utils-nodeps'
import { utcMsTs } from '../data/utils-data'
import { useBlk } from '../data/VMs/BlockVM'
import { DBContext, useRawThread } from '../ui/reactive'
import { BlockTree } from './BlockTree'
import { AgentButton } from './mini-components'

const { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.VERBOSE) // eslint-disable-line unused-imports/no-unused-vars

const inputStyle = {
	'--sl-input-font-size-small': '11px',
}
export const BlockInTime: Component<{
	en: EntityID
	asof: Accessor<number>
}> = function BlockInTime(props) {
	// TODO some fancy asof magic
	return <BlockTree blockID={props.en} />
}
export const HistoryPanel: Component<{
	refHolder?: { ref: SlDialog }
	onHide?: (CustomEvent) => null
	open?: boolean
	blockID: EntityID
}> = function HistoryDialog(props) {
	const blkVM = useBlk(props.blockID)
	// const lastTs = '2024-11-28T12:37:18'
	const lastTs = untracked(() => blkVM.thread.latestLog.ts)
	const [asofTs, setAsof] = createSignal(lastTs)
	const knownAgentMap = useAgent().getKnownAgents()

	DEBUG({ asof: lastTs })
	const onInput = (evt: InputEvent) => {
		setAsof((evt.target as HTMLInputElement).value)
	}
	const rawThread = useRawThread()

	const filteredLogsObservable = observable.array()
	const asofThread = ThreadInMemory.fromReadOnlyArray(filteredLogsObservable, `${rawThread.nameAndSizeUntracked} | asofThread`)
	if (VERBOSE.isEnabled) VERBOSE({ filteredLogsObservable, asofThread })

	const asofApplogs = () => {
		const asof = asofTs() // mobxAsof.get()
		DEBUG('FILTER asof change', asof)
		const ts = utcMsTs()
		const filteredLogs = rawThread.applogs.filter(l => compareAsc(l.ts, asof) < 1) // TODO consider optimization via truncate or find/split
		VERBOSE({ filterTook: utcMsTs() - ts }) // < 50 ms
		if (VERBOSE.isEnabled) VERBOSE({ filteredLogs })
		return filteredLogs
	}
	createRenderEffect(action(() => {
		const ts = utcMsTs()
		const replacedLogs = filteredLogsObservable.replace(asofApplogs())
		VERBOSE({ replaceTook: utcMsTs() - ts }) // 200-400ms
		asofThread.notifySubscribers({ init: replacedLogs })
		return replacedLogs
	}))
	return (
		<div>
			<sl-input
				placeholder='msTs to go back to'
				value={asofTs()}
				onInput={onInput}
				filled
				font-mono
				size='small'
				max-w-full
				min-w-fit
				mb-4
				spellcheck={false}
				style={inputStyle}
			/>
			<DBContext.Provider value={() => asofThread}>
				<BlockTree blockID={props.blockID} />
			</DBContext.Provider>
			<ul>
				<For each={blkVM.historicContentLogs}>
					{(item, _index) => {
						const eachAgent = knownAgentMap.get().get(item.ag)
						const buttonData = {
							text: eachAgent?.agString.split('.')[0] ?? 'unknown',
							title: `${item.ag}=>${eachAgent?.agString ?? 'unknown'}`,
						}
						const plaintext = !item.vl ? '' : tiptapToPlaintext(JSON.parse(item.vl as string))
						return (
							<li>
								<AgentButton buttonData={buttonData} />
								<a onClick={() => setAsof(item.ts)} cursor-pointer underline>
									<sl-relative-time date={item.ts} />
									{' '}
									@
									{item.ts.split('T')[1]}
								</a>
								{' - '}
								{plaintext}
							</li>
						)
					}}
				</For>
			</ul>
		</div>
	)
}
export const HistoryDialog: Component<{
	refHolder?: { ref: SlDialog }
	onHide?: (CustomEvent) => null
	open?: boolean
	blockID: EntityID
}> = function HistoryDialog(props) {
	const afterhide = async (hideargs) => {
		DEBUG({ hideargs })
	}
	let localref
	return (
		<>
			<sl-dialog
				ref={props.refHolder?.ref ?? localref}
				open={props.open ?? false}
				attr:onsl-after-hide={afterhide}
				class='historyDialog'
				w='90%'
			>
				<style>
					{`
					.historyDialog::part(title) {
						padding: 0px;
					}
					.historyDialog::part(panel) {
						width: 80%;
					}
					.historyDialog::part(header) {
						padding: 1em 1em 0.5em 1em ;
					}
					.historyDialog::part(body) {
						padding:  0.5em 1em 1em 1em;
					}
				`}
				</style>
				<h4 slot='label' py-1 px-2 m-0>
					Explore Block History:
				</h4>
				<HistoryPanel blockID={props.blockID} />
			</sl-dialog>
		</>
	)
}
