export interface WordData {
	text: string
	start: number
	end: number
}

export interface EditorSegment {
	startTime: string
	endTime: string
	text: string
	words?: WordData[]
}

export function secondsToTimecode(sec: number): string {
	const mins = Math.floor(sec / 60)
	const secs = sec % 60
	const whole = Math.floor(secs)
	const ms = Math.round((secs - whole) * 1000)
	return `${String(mins).padStart(2, "0")}:${String(whole).padStart(2, "0")}.${String(ms).padStart(3, "0")}`
}

export function timecodeToSeconds(tc: string): number {
	const [minPart, secPart] = tc.split(":")
	if (!minPart || !secPart) return 0
	const mins = parseInt(minPart, 10) || 0
	const secs = parseFloat(secPart) || 0
	return mins * 60 + secs
}

export function documentToSegments(doc: unknown): EditorSegment[] {
	const d = doc as {
		segments?: Array<{
			time?: { start?: number; end?: number }
			text?: string
			lines?: Array<{
				words?: Array<{ text?: string; time?: { start?: number; end?: number } }>
			}>
		}>
	}
	if (!d?.segments) return []
	return d.segments.map((seg) => {
		const words: WordData[] = []
		if (seg.lines) {
			for (const line of seg.lines) {
				if (line.words) {
					for (const w of line.words) {
						if (w.text) {
							words.push({
								text: w.text,
								start: w.time?.start ?? 0,
								end: w.time?.end ?? 0,
							})
						}
					}
				}
			}
		}
		const segStart = seg.time?.start ?? 0
		const segEnd = seg.time?.end ?? 0
		const segText = seg.text ?? ""
		return {
			startTime: secondsToTimecode(segStart),
			endTime: secondsToTimecode(segEnd),
			text: segText,
			words:
				words.length > 0
					? words
					: estimateWordTimings(segText, segStart, segEnd),
		}
	})
}

export function segmentsToDocument(
	segments: EditorSegment[],
): Record<string, unknown> {
	return {
		segments: segments.map((seg) => {
			const start = timecodeToSeconds(seg.startTime)
			const end = timecodeToSeconds(seg.endTime)
			const wordNodes = seg.words
				? seg.words.map((w) => ({
						text: w.text,
						semantic_tags: [],
						structure_tags: [],
						time: { start: w.start, end: w.end },
					}))
				: []

			return {
				text: seg.text,
				semantic_tags: [],
				structure_tags: [],
				time: { start, end },
				lines: [
					{
						text: seg.text,
						semantic_tags: [],
						structure_tags: [],
						time: { start, end },
						words: wordNodes,
					},
				],
			}
		}),
	}
}

export function estimateWordTimings(
	text: string,
	start: number,
	end: number,
): WordData[] {
	const tokens = text.split(/\s+/).filter(Boolean)
	if (tokens.length === 0) return []
	const totalChars = tokens.reduce((sum, t) => sum + t.length, 0)
	const duration = end - start
	let cursor = start
	return tokens.map((token) => {
		const ratio = token.length / totalChars
		const wordDuration = duration * ratio
		const wordStart = Math.round(cursor * 1000) / 1000
		cursor += wordDuration
		const wordEnd = Math.round(cursor * 1000) / 1000
		return { text: token, start: wordStart, end: wordEnd }
	})
}

export function splitSegmentAtMarkers(
	segment: EditorSegment,
	markerIndices: number[],
): EditorSegment[] {
	if (!segment.words || segment.words.length < 2) return [segment]
	if (markerIndices.length === 0) return [segment]

	const sorted = [...markerIndices].sort((a, b) => a - b)
	const groups: WordData[][] = []
	let start = 0

	for (const markerIdx of sorted) {
		if (markerIdx >= start && markerIdx < segment.words.length) {
			groups.push(segment.words.slice(start, markerIdx))
			start = markerIdx
		}
	}
	groups.push(segment.words.slice(start))

	return groups
		.filter((g) => g.length > 0)
		.map((words) => ({
			startTime: secondsToTimecode(words[0].start),
			endTime: secondsToTimecode(words[words.length - 1].end),
			text: words.map((w) => w.text).join(" "),
			words,
		}))
}
