import type { SlDialog } from '@shoelace-style/shoelace'
import type { Accessor, Component } from 'solid-js'
import { buf2hex } from '@wovin/utils'
import { Logger } from 'besonders-logger'
import { createMnemonic, encHashedMnemonic, getECDHkeypairFromHashArray, testStats } from 'mnemkey'
import { createEffect, createSignal, For, Show } from 'solid-js'
import { getMnemonicFromIDB } from '../../data/agent/AgentCrypto'
import { useAgent } from '../../data/agent/AgentState'
import { notifyToast } from '../../ui/utils-ui'
import { Iconify } from '../mini-components'

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

const inputStyle = {
	'--sl-input-font-size-small': '11px',
}
const exampleMnem
	= 'basket,chief,toad,chemical,little,analysis,admonish,cupcake,diatribe,obedient,craving,nightcap,hopeful,street,raggedy,stymie,mechanic,papyrus,sorcerer,plushy,rickshaw,taffy,nocturne,unicycle'
export const SingleWord: Component<{
	index: number
	mnemArray: Accessor<string[]>
}> = function SingleWord(props) {
	const [myWord, setMyword] = createSignal(props.mnemArray()[props.index])

	const onInput = (evt: InputEvent) => {
		setMyword((evt.target as HTMLInputElement).value)
	}
	return (
		<sl-input
			placeholder='- - -'
			value={`${props.index}: ${myWord()}`}
			onInput={onInput}
			filled
			font-mono
			size='small'
			w-24
			mb-4
			mx-1
			disabled
			spellcheck={false}
			style={inputStyle}
		/>
	)
}
export const MnemDialog: Component<{
	// mnemDialogRef: any
}> = function MnemDialog() {
	const [storedMnemonic, setStoredMnemonic] = createSignal()
	const [isKeyMatching, setMatching] = createSignal(false)
	const [mnemToTest, setMnem] = createSignal('')
	const [mnemArray, setMnemArr] = createSignal([])
	createEffect(() => {
		const cleanedMnemString = mnemToTest().replaceAll(' ', ',').replaceAll(',,,', ',').replaceAll(',,', ',')
		setMnemArr(cleanedMnemString.split(','))
		VERBOSE('cleaned array', mnemArray())
	})
	const onInput = (evt: InputEvent) => {
		setMnem((evt.target as HTMLInputElement).value)
	}
	const compareDerivedKeys = async () => {
		const { publicKey } = await getECDHkeypairFromHashArray(encHashedMnemonic(mnemArray()))
		DEBUG({ publicKey }, mnemArray())
		const isMatching = await comparePubDerivationKey(buf2hex(await globalThis.crypto.subtle.exportKey('raw', publicKey)))
		if (isMatching) {
			setMatching(true)
			notifyToast(`Looking good, your public key in IDB matches the one derived from the mnemonic you entered`, 'success', 10000)
		} else {
			notifyToast(`UhOh, your pubkey DOES NOT MATCH the one derived from the mnemonic`, 'danger', 10000)
		}
	}
	const comparePubDerivationKey = async (hexPubKey, newMnemArr?: string[]) => {
		const agent = useAgent()

		const { publicKey } = await agent.getDerivationKeypair(newMnemArr)
		const exportedPubKeyHex = buf2hex(await globalThis.crypto.subtle.exportKey('raw', publicKey))
		const isMatching = !!(hexPubKey === exportedPubKeyHex)
		DEBUG({ isMatching, hexPubKey, exportedPubKeyHex })
		return isMatching
	}
	const afterhide = async (hideargs) => {
		DEBUG({ hideargs })
	}
	const dealWithStoredMnem = async () => {
		const mnemFromIDB = await getMnemonicFromIDB(useAgent())
		DEBUG({ mnemFromIDB })
		setStoredMnemonic(mnemFromIDB)
		setMnem(mnemFromIDB)
		notifyToast('You should really save the mnemonic so we can delete it from IDB (even if it is encrypted)')
	}

	const importDerivationKey = async (newMnemArr?: string[]) => {
		const { publicKey } = await useAgent().getDerivationKeypair(newMnemArr)
		const exportedPubKeyHex = buf2hex(await globalThis.crypto.subtle.exportKey('raw', publicKey))
		DEBUG({ exportedPubKeyHex })
	}

	let mnemDialogRef: SlDialog
	return (
		<>
			<sl-button
				max-w-fit
				// variant='primary'
				onClick={() => mnemDialogRef?.show()}
				size='small'
			>
				<div flex='~ items-center' gap-1>
					<Iconify slot='prefix' name='gear' size={4} />
					Mnemonic Key
				</div>
			</sl-button>
			<sl-dialog
				ref={mnemDialogRef}
				onsl-after-hide={afterhide}
				class='mnemDialog'
				w='90%'
			>
				<style>
					{`
					.mnemDialog::part(title) {
						padding: 0px;
					}
					.mnemDialog::part(panel) {
						width: 80%;
					}
					.mnemDialog::part(header) {
						padding: 1em 1em 0.5em 1em ;
					}
					.mnemDialog::part(body) {
						padding:  0.5em 1em 1em 1em;
					}
				`}
				</style>
				<h4 slot='label' py-1 px-2 m-0>
					Enter a valid 24 word mnemonic:
				</h4>
				<sl-input
					placeholder='list of words like foo,bar,baz (separated by single commas or single spaces)'
					value={mnemToTest()}
					onInput={onInput}
					filled
					font-mono
					size='small'
					max-w-full
					min-w-fit
					mb-4
					spellcheck={false}
					style={inputStyle}
				/>
				<Show when={mnemArray().length > 1}>
					<div flex='~ wrap justify-between'>
						<For
							each={mnemArray().reduce((result, value, index, array) => {
								if (index % 2 === 0) {
									result.push(array.slice(index, index + 2))
								}
								return result
							}, [])}
						>
							{(_item, eachIndex) => {
								return (
									<div flex='~ row wrap-none'>
										<SingleWord index={eachIndex() * 2} mnemArray={mnemArray} />
										<SingleWord index={eachIndex() * 2 + 1} mnemArray={mnemArray} />
									</div>
								)
							}}
						</For>
					</div>
				</Show>
				<div>
					<sl-button
						max-w-fit
						variant={isKeyMatching() ? 'success' : 'default'}
						onClick={compareDerivedKeys}
						size='small'
					>
						<div flex='~ items-center' gap-1>
							<Iconify size={4} slot='prefix' name={isKeyMatching() ? 'check-circle' : 'question'} />
							Check
						</div>
					</sl-button>
					<sl-button
						max-w-fit
						ml-4
						variant='primary'
						onClick={async () => {
							setMnem(createMnemonic(24).join(','))
							testStats(256, 10)
						}}
						size='small'
					>
						<div flex='~ items-center' gap-1>
							<Iconify size={4} slot='prefix' name='plus-circle' />
							New
						</div>
					</sl-button>
					<sl-button
						max-w-fit
						ml-4
						variant='primary'
						onClick={async () => {
							importDerivationKey(mnemArray())
							testStats(256, 10)
						}}
						size='small'
					>
						<div flex='~ items-center' gap-1>
							<Iconify slot='prefix' size='4' name='shield-plus' />
							Import
						</div>
					</sl-button>
					<sl-button
						max-w-fit
						ml-4
						variant='danger'
						onClick={dealWithStoredMnem}
						size='small'
					>
						<div flex='~ items-center' gap-1>
							<Iconify slot='prefix' size='4' name='shield-warning' />
							Export
						</div>
					</sl-button>
				</div>
			</sl-dialog>
		</>
	)
}
