<script setup lang="ts">
import { formatDate, Icon, Loading } from '@bagelink/vue'
import { computed, ref, onMounted, onUnmounted } from 'vue'

interface SecondaryValue {
	label: string
	value: number
	currency?: boolean
	prefix?: string
	suffix?: string
}

interface DataPoint {
	date: string
	value: number
	secondaryValues?: SecondaryValue[]
	label?: string
}

interface Props {
	title: string
	data: DataPoint[]
	icon?: string
	color?: string
	percentageChange?: number
	prefix?: string
	suffix?: string
	currency?: boolean
	maxBars?: number
	loading?: boolean
	rtl?: boolean
	animated?: boolean
	animationDuration?: number
	animationStartDelay?: number
}

const props = withDefaults(defineProps<Props>(), {
	icon: 'trending_up',
	color: 'var(--bgl-primary)',
	percentageChange: 0,
	prefix: '',
	suffix: '',
	currency: false,
	maxBars: 30,
	loading: false,
	rtl: false,
	animated: true,
	animationDuration: 1500,
	animationStartDelay: 0,
})

// Animation state
const animatedProgress = ref(0)
const isAnimating = ref(false)
const isInView = ref(false)
const observer = ref<IntersectionObserver | null>(null)
const chartRef = ref<HTMLElement | null>(null)

const chartData = computed(() => {
	if (!props.data || props.data.length === 0) { return [] }

	// Use all data without limiting to maxBars
	const maxValue = Math.max(...props.data.map(d => d.value), 1)
	return props.data.map(item => ({
		...item,
		height: Math.max((item.value / maxValue) * 100, 2), // Minimum height of 2%
		displayLabel: formatDate(item.date, 'MMM')
	}))
})

// Animation computed properties
const getBarOpacity = computed(() => {
	return (index: number) => {
		if (!props.animated) { return 1 }
		if (!isInView.value) { return 0 }

		const totalBars = chartData.value.length

		// Each bar appears with a delay based on its index
		const barDelay = index / totalBars
		const progress = Math.max(0, Math.min(1, (animatedProgress.value - barDelay) * totalBars))

		return progress
	}
})

// Animation functions
function easeOutCubic(t: number): number {
	return 1 - (1 - t) ** 3
}

function startAnimation() {
	if (isAnimating.value || !props.animated) { return }

	console.log(`🎯 TrendChart: Starting animation with ${props.animationDuration}ms duration`)
	isAnimating.value = true
	animatedProgress.value = 0

	const startTime = performance.now()

	function animate(currentTime: number) {
		const elapsed = currentTime - startTime
		const progress = Math.min(elapsed / props.animationDuration, 1)
		const easedProgress = easeOutCubic(progress)

		animatedProgress.value = easedProgress

		if (progress < 1) {
			requestAnimationFrame(animate)
		} else {
			isAnimating.value = false
			console.log(`✅ TrendChart: Animation completed`)
		}
	}

	requestAnimationFrame(animate)
}

function setupIntersectionObserver() {
	if (!chartRef.value || observer.value) { return }

	observer.value = new IntersectionObserver(
		(entries) => {
			entries.forEach((entry) => {
				if (entry.isIntersecting && !isInView.value) {
					console.log(`👀 TrendChart: Entered viewport, starting animation in ${props.animationStartDelay}ms`)
					isInView.value = true
					setTimeout(() => {
						startAnimation()
					}, props.animationStartDelay)
				}
			})
		},
		{
			threshold: 0.3,
			rootMargin: '50px'
		}
	)

	observer.value.observe(chartRef.value)
}

onMounted(() => {
	if (props.animated) {
		setupIntersectionObserver()
	} else {
		// If not animated, show all bars immediately
		isInView.value = true
		animatedProgress.value = 1
	}
})

onUnmounted(() => {
	if (observer.value) {
		observer.value.disconnect()
	}
})

function formatValue(value: number, isCurrency: boolean = false): string {
	if (isCurrency) {
		return new Intl.NumberFormat('he-IL', {
			style: 'currency',
			currency: 'ILS',
			minimumFractionDigits: 0
		}).format(value)
	}
	return value.toLocaleString()
}

function formatTooltip(item: any): string {
	const primaryValue = formatValue(item.value, props.currency)
	const primaryText = `${props.prefix}${primaryValue}${props.suffix}`
	const tooltipLines = [`${item.displayLabel}`, `<b>${primaryText}</b>`]

	if (item.secondaryValues && Array.isArray(item.secondaryValues)) {
		item.secondaryValues.forEach((secondary: SecondaryValue) => {
			const formattedSecondaryValue = formatValue(secondary.value, secondary.currency || false)
			const secondaryText = `${secondary.prefix || ''}${formattedSecondaryValue}${secondary.suffix || ''}`
			tooltipLines.push(`${secondary.label}: <b>${secondaryText}</b>`)
		})
	}

	return `<div class="trendTooltip">${tooltipLines.join('<p>')}</div>`
}
</script>

<template>
	<div ref="chartRef" class="h-100p flex column flex-stretch">
		<div class="flex space-between  pb-1">
			<div class="flex align-center gap-05">
				<Icon :name="icon" size="1.2" :color="color" class="line-height-0" />
				<p class="white-space light m_txt14">
					{{ title }}
				</p>
			</div>
			<div v-if="percentageChange !== 0" class="flex align-center gap-025">
				<Icon
					:name="percentageChange > 0 ? 'trending_up' : 'trending_down'" size="1"
					:class="percentageChange > 0 ? 'color-success' : 'color-danger'"
				/>
				<span class="txt12 bold" :class="percentageChange > 0 ? 'color-success' : 'color-danger'">
					{{ Math.abs(percentageChange) }}%
				</span>
			</div>
		</div>
		<div
			class="flex w-100p align-items-end mt-auto gap-075 overflow justify-content-start"
			:class="[rtl ? 'rtl' : 'ltr']"
		>
			<div
				v-for="(bar, index) in chartData" :key="index" v-tooltip="{ content: formatTooltip(bar), html: true }"
				class="flex-grow txt-center hover transition-400 relative barWrap mb-1" :style="{
					width: `max(2rem, ${100 / chartData.length}%)`,
					opacity: getBarOpacity(index),
					transition: animated ? 'opacity 0.3s ease-out' : 'none',
				}"
			>
				<div
					class="bar radius-05 transition-400 " :style="{
						height: `${bar.height * 1.8}px`,
						background: `linear-gradient(180deg, ${color}60, ${color}30)`,
						minHeight: '4px',
					}"
				/>
				<span
					v-if="chartData.length <= 15 || index % Math.ceil(chartData.length / 8) === 0"
					class="txt-9 block line-height-1 -bottom-075 white-space color-gray absolute"
					:class="rtl ? 'rtl' : 'ltr'"
				>
					{{ bar.displayLabel }}
				</span>
			</div>
		</div>
		<div v-if="loading" class="absolute inset flex justify-content-center rounded">
			<Loading v-if="loading" />
		</div>
	</div>
</template>

<style>
.trendTooltip p {
	font-weight: 300 !important;
	font-size: 12px;
}

.trendTooltip {
	font-weight: 700 !important;
}

.v-popper--theme-tooltip .v-popper__inner:has(.trendTooltip) {
	background-color: var(--bgl-black) !important;
	color: var(--bgl-white) !important;
	border-radius: 0.5rem !important;
	padding: 0.25rem 0.5rem !important;
}

.bar {
	min-width: 2rem;
}
</style>
