<script setup lang="ts">
import { ref, watch, onMounted } from 'vue'
import VueApexCharts from 'vue3-apexcharts'
import { ChartType } from "@/Types/types"

const props = defineProps<{
    type: ChartType
    title: string
    height: number | string
    series: { name: string; data: number[] }[]
    categories: unknown[]
    options?: object
}>()

const chartRef = ref()
const isUpdating = ref(false)
const ready = ref(false)
let rafId: number | null = null

const staticOptions = {
    chart: {
        type: 'bar',
        stacked: true,
        toolbar: { show: false },
        background: 'transparent',
        fontFamily: 'inherit',
        animations: { enabled: false },
    },
    theme: { mode: 'dark' },
    plotOptions: {
        bar: {
            borderRadius: 3,
            borderRadiusWhenStacked: 'last',
            columnWidth: '55%',
        },
    },
    colors: ['#4da6ff', '#ffc107'],
    dataLabels: { enabled: false },
    grid: {
        borderColor: 'rgba(255,255,255,0.05)',
        yaxis: { lines: { show: true } },
        xaxis: { lines: { show: false } },
    },
    yaxis: {
        labels: { style: { colors: '#445566', fontSize: '12px' } },
    },
    legend: {
        position: 'top',
        horizontalAlign: 'right',
        labels: { colors: '#778899' },
        markers: { width: 8, height: 8, radius: 2 },
        itemMargin: { horizontal: 12 },
    },
    tooltip: { theme: 'dark', shared: true, intersect: false },
    states: {
        hover: { filter: { type: 'lighten', value: 0.1 } },
        active: { filter: { type: 'none' } },
    },
}

const initialOptions = {
    ...staticOptions,
    xaxis: {
        categories: props.categories,
        axisBorder: { show: false },
        axisTicks: { show: false },
        labels: { style: { colors: '#445566', fontSize: '12px' } },
    },
}

onMounted(() => { ready.value = true })

watch(
    [() => props.categories, () => props.series],
    ([cats, series]) => {
        if (!ready.value) return

        // Show skeleton immediately, defer the ApexCharts work
        isUpdating.value = true

        if (rafId !== null) cancelAnimationFrame(rafId)
        rafId = requestAnimationFrame(() => {
            chartRef.value?.updateOptions(
                { xaxis: { categories: cats } },
                false,
                false,
            )
            chartRef.value?.updateSeries(series, false)
            isUpdating.value = false
            rafId = null
        })
    },
    { deep: false }
)
</script>

<template>
    <div class="chart-wrap">
        <div class="chart-title">{{ title }}</div>
        <div class="chart-area" :style="{ height: typeof height === 'number' ? height + 'px' : height }">
            <VueApexCharts
                ref="chartRef"
                :type="type"
                :height="height"
                :options="options ?? initialOptions"
                :series="series"
                :style="{ opacity: isUpdating ? 0 : 1 }"
                class="apex-chart"
            />
            <div v-if="isUpdating" class="chart-skeleton" />
        </div>
    </div>
</template>

<style scoped>
.chart-wrap {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.chart-title {
    font-size: 13px;
    font-weight: 500;
    color: #556677;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.chart-area {
    position: relative;
}

.apex-chart {
    transition: opacity 0.15s ease;
}

.chart-skeleton {
    position: absolute;
    inset: 0;
    border-radius: 6px;
    background: linear-gradient(
        90deg,
        rgba(255, 255, 255, 0.03) 25%,
        rgba(255, 255, 255, 0.07) 50%,
        rgba(255, 255, 255, 0.03) 75%
    );
    background-size: 200% 100%;
    animation: shimmer 1.2s ease-in-out infinite;
}

@keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

:deep(svg) {
    outline: none;
}
</style>
