<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted } from 'vue'
import { createChart, AreaSeries, type IChartApi, type ISeriesApi, type UTCTimestamp } from 'lightweight-charts'
import type { WsKlineBar } from '@/composables/useMarketWs'

type ChartRange = '24h' | '1w' | '1m' | '1y'

const props = defineProps<{
  currentPrice:   number
  priceChange:    number
  priceChangePct: number
  bars:    WsKlineBar[]
  liveBar: WsKlineBar | null
  chartRange: ChartRange
}>()

const emit = defineEmits<{
  'range-change': [range: ChartRange]
}>()

const ranges: { label: string; value: ChartRange }[] = [
  { label: '24h',  value: '24h' },
  { label: '一周', value: '1w'  },
  { label: '一月', value: '1m'  },
  { label: '一年', value: '1y'  },
]

const chartEl = ref<HTMLDivElement | null>(null)
let chart:  IChartApi | null = null
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let series: ISeriesApi<'Area', any> | null = null

function initChart() {
  if (!chartEl.value) return
  chart = createChart(chartEl.value, {
    layout: {
      background: { color: 'transparent' },
      textColor: '#8a8a8a',
    },
    grid: {
      vertLines: { color: 'rgba(255,255,255,0.04)' },
      horzLines: { color: 'rgba(255,255,255,0.04)' },
    },
    crosshair: {
      vertLine: { color: '#F0B90B', width: 1, style: 2, labelBackgroundColor: '#F0B90B' },
      horzLine: { color: '#F0B90B', width: 1, style: 2, labelBackgroundColor: '#F0B90B' },
    },
    rightPriceScale: {
      borderColor: 'rgba(255,255,255,0.08)',
      textColor: '#6b6b6b',
    },
    timeScale: {
      borderColor: 'rgba(255,255,255,0.08)',
      timeVisible: true,
      secondsVisible: false,
    },
    handleScroll: true,
    handleScale: true,
  })

  series = chart.addSeries(AreaSeries, {
    lineColor: '#F0B90B',
    topColor: 'rgba(240,185,11,0.22)',
    bottomColor: 'rgba(240,185,11,0)',
    lineWidth: 2,
    priceLineVisible: false,
    lastValueVisible: true,
  })
}

function setChartData() {
  if (!series || !props.bars.length) return
  // Deduplicate by second timestamp, keep last occurrence
  const seen = new Map<number, number>()
  for (const b of props.bars) seen.set(Math.floor(b.timestamp / 1000), b.close)
  const data = Array.from(seen.entries())
    .map(([t, v]) => ({ time: t as UTCTimestamp, value: v }))
    .sort((a, b) => a.time - b.time)
  series.setData(data)
  chart?.timeScale().fitContent()
}

function updateLiveBar() {
  if (!series || !props.liveBar) return
  series.update({
    time: Math.floor(props.liveBar.timestamp / 1000) as UTCTimestamp,
    value: props.liveBar.close,
  })
}

onMounted(initChart)
onUnmounted(() => { chart?.remove(); chart = null })

// Use non-deep watch so array replacement triggers correctly
watch(() => props.bars, setChartData)
watch(() => props.liveBar, updateLiveBar)
</script>

<template>
  <div class="price-chart dark-card">
    <!-- 价格 + 涨跌幅 + 时间范围 -->
    <div class="chart-header">
      <div class="price-block">
        <div
          class="current-price num"
          :class="priceChangePct >= 0 ? 'text-up' : 'text-down'"
        >
          {{ currentPrice > 0
              ? currentPrice.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
              : '—' }}
        </div>
        <div
          class="price-change num"
          :class="priceChange >= 0 ? 'text-up' : 'text-down'"
        >
          {{ priceChange >= 0 ? '+' : '' }}{{ priceChange.toLocaleString('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1 }) }}
          ({{ priceChangePct >= 0 ? '+' : '' }}{{ priceChangePct.toFixed(2) }}%)
        </div>
      </div>

      <div class="range-tabs">
        <button
          v-for="r in ranges"
          :key="r.value"
          class="range-tab"
          :class="{ 'is-active': chartRange === r.value }"
          @click="emit('range-change', r.value)"
        >
          {{ r.label }}
        </button>
      </div>
    </div>

    <!-- 图表区域 -->
    <div ref="chartEl" class="chart-body" />
  </div>
</template>

<style scoped>
.price-chart { padding: var(--space-6); }

.chart-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: var(--space-5);
  gap: var(--space-4);
  flex-wrap: wrap;
}

.current-price {
  font-size: 38px;
  font-weight: var(--fw-bold);
  line-height: 1.15;
  color: var(--color-text-primary);
}

.price-change {
  font-size: var(--text-small);
  margin-top: 4px;
}

.range-tabs {
  display: flex;
  gap: 4px;
  align-items: center;
}
.range-tab {
  padding: 5px 14px;
  font-size: 13px;
  color: var(--color-text-secondary);
  border-radius: var(--radius-md);
  transition: background var(--transition), color var(--transition);
}
.range-tab:hover { color: var(--color-text-primary); }
.range-tab.is-active {
  background: var(--color-primary);
  color: #000;
  font-weight: var(--fw-semibold);
}

.chart-body { height: 280px; }

@media (max-width: 560px) {
  .current-price { font-size: 28px; }
  .chart-body    { height: 220px; }
}
</style>
