import { resolve } from 'path'
import type { ReactNode } from 'react'
import Link from './Link.js'
import Text from './Text.js'

export type Editor = 'vscode' | 'vscode-insiders' | 'cursor' | 'windsurf'

export type FileLinkProps = {
	/** Absolute or relative file path. Relative paths are resolved against cwd. */
	readonly path: string
	/** 1-based line number */
	readonly line?: number
	/** 1-based column number */
	readonly column?: number
	/** Editor to open with (default: 'vscode') */
	readonly editor?: Editor
	/** Custom display content. Defaults to "path:line:col" */
	readonly children?: ReactNode
}

const SCHEME: Record<Editor, string> = {
	vscode: 'vscode',
	'vscode-insiders': 'vscode-insiders',
	cursor: 'cursor',
	windsurf: 'windsurf',
}

/**
 * Build a URI that opens a file at a specific location in an editor.
 *
 * VS Code URI format: vscode://file/{absolute_path}:{line}:{column}
 */
export function buildEditorUri(
	path: string,
	line?: number,
	column?: number,
	editor: Editor = 'vscode',
): string {
	const abs = resolve(path)
	const scheme = SCHEME[editor]
	let uri = `${scheme}://file/${abs}`
	if (line != null) {
		uri += `:${line}`
		if (column != null) {
			uri += `:${column}`
		}
	}
	return uri
}

/**
 * Clickable terminal hyperlink that opens a file in VS Code (or compatible editor).
 *
 * Uses OSC 8 hyperlinks with `vscode://file/` URIs. In terminals that support
 * hyperlinks (iTerm2, Windows Terminal, Hyper, kitty, etc.), clicking the link
 * opens the file at the specified line/column in VS Code.
 *
 * Usage:
 * ```tsx
 * <FileLink path="src/index.ts" line={42} />
 * <FileLink path="/abs/path/file.ts" line={10} column={5} editor="cursor">
 *   <Text color="ansi:blueBright" underline>open file</Text>
 * </FileLink>
 * ```
 */
export default function FileLink({ path, line, column, editor = 'vscode', children }: FileLinkProps) {
	const url = buildEditorUri(path, line, column, editor)

	const defaultLabel = line != null
		? column != null
			? `${path}:${line}:${column}`
			: `${path}:${line}`
		: path

	return (
		<Link
			url={url}
			fallback={<Text color="ansi:blueBright">{defaultLabel}</Text>}
		>
			{children ?? <Text color="ansi:blueBright" underline>{defaultLabel}</Text>}
		</Link>
	)
}
