import { spinner } from '@clack/prompts'
import pc from 'picocolors'

export { pc }

export function formatBytes(bytes: number): string {
	if (bytes === 0) return '0 B'
	const k = 1024
	const sizes = ['B', 'KB', 'MB', 'GB']
	const i = Math.floor(Math.log(bytes) / Math.log(k))
	return `${parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i] ?? 'TB'}`
}

// Adapter to provide ora-like interface using clack spinner
export interface SpinnerLike {
	text: string
	start(): SpinnerLike
	succeed(text?: string): SpinnerLike
	fail(text?: string): SpinnerLike
}

export function createSpinner(text: string): SpinnerLike {
	// when no tty is attached, or a headless env var is set, return a silent spinner
	if (!process.stdout.isTTY || process.env.WISPCTL_NO_PROGRESS === '1' || process.env.CI === 'true') {
		let currentText = text
		return {
			get text() {
				return currentText
			},
			set text(newText: string) {
				currentText = newText
			},
			start() {
				return this
			},
			succeed(message?: string) {
				console.log(`✓ ${message ?? currentText}`)
				return this
			},
			fail(message?: string) {
				console.error(`✗ ${message ?? currentText}`)
				return this
			},
		}
	}

	const s = spinner()
	let currentText = text
	let started = false

	return {
		get text() {
			return currentText
		},
		set text(newText: string) {
			currentText = newText
			if (started) {
				s.message(newText)
			}
		},
		start() {
			started = true
			s.start(currentText)
			return this
		},
		succeed(message?: string) {
			s.stop(pc.green('✓ ') + (message ?? currentText))
			started = false
			return this
		},
		fail(message?: string) {
			s.stop(pc.red('✗ ') + (message ?? currentText))
			started = false
			return this
		},
	}
}
