<template>
  <div class="custom-echarts">
    <div>
      <div class="echarts-header">
        <div class="echarts-header-title">
          <span>FiEE, Inc. Stock Price History</span>
        </div>
        <div class="echarts-search-area">
          <div class="echarts-search-byRange">
            <text style="font-size: 0.9rem; font-weight: 400; color: #666666;">
              Range
            </text>
            <div class="search-range-list">
              <div
                class="search-range-list-each"
                v-for="(item, index) in state.searchRange"
                :key="index"
                @click="changeSearchRange(item)"
              >
                <span>{{ item }}</span>
              </div>
            </div>
          </div>
          <div class="echarts-search-byDate">
            <n-date-picker
              v-model:value="state.selectHistoricStartDate"
              type="date"
              :is-date-disabled="disableAfterDate"
              @update:value="changeSearchRangeStartDate"
              input-readonly
            />
            <!-- <n-icon size="16">
                <ArrowForwardOutline />
              </n-icon> -->
            <span>to</span>
            <n-date-picker
              v-model:value="state.selectHistoricEndDate"
              type="date"
              :is-date-disabled="disablePreviousDate"
              @update:value="changeSearchRangeEndDate"
              input-readonly
            />
          </div>
        </div>
      </div>
    </div>
    <div id="myEcharts" class="myChart"></div>
  </div>
</template>
<script setup>
import { onMounted, watch, reactive } from 'vue'
import * as echarts from 'echarts'
import markPointerIcon from '@/assets/image/icon/echarts_markPointer.png'
import axios from 'axios'
import { NDatePicker, NIcon } from 'naive-ui'
import { ArrowForwardOutline } from '@vicons/ionicons5'

const state = reactive({
  searchRange: ['1m', '3m', 'YTD', '1Y', '5Y', '10Y', 'Max'],
  selectHistoricStartDate: '2009-10-07',
  selectHistoricEndDate: new Date(),
})

let myCharts = null
let historicData = []
let xAxisData = []

//初始化eCharts
const initEcharts = (data) => {
  historicData = data
  xAxisData = data.map((item) => {
    return new Date(item.date).toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
  })
  const yAxisData = data.map((item) => item.price)
  // console.error(xAxisData, yAxisData)
  // 基于准备好的dom，初始化echarts实例
  myCharts = echarts.init(document.getElementById('myEcharts'), null, {
    renderer: 'canvas',
    useDirtyRect: true
  })
  // 绘制图表
  myCharts.setOption({
    animation: false,
    progressive: 500,
    progressiveThreshold: 3000,
    // title: {
    //   text: 'FiEE, Inc. Stock Price History',
    // },
    grid: {
      left: '8%', // 或 '2%'，根据实际情况调整
      right: '12%', // 给右侧y轴留空间，数值可根据y轴label宽度调整
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'line',
        label: {
          backgroundColor: '#6a7985',
        },
      },
      formatter: function (params) {
        const p = params[0]
        return `<span style="font-size: 1.1rem; font-weight: 600;">${p.axisValue}</span><br/><span style="font-size: 0.9rem; font-weight: 400;">Price: ${p.data}</span>`
      },
      triggerOn: 'mousemove',
      confine: true,
      hideDelay: 1500
    },
    xAxis: {
      data: xAxisData,
      type: 'category',
      boundaryGap: false,
      inverse: true,
      axisLine: {
        lineStyle: {
          color: '#CCD6EB',
        },
      },
      axisLabel: {
        color: '#323232',
        fontWeight: 'bold',
        interval: 'auto',
        hideOverlap: true
      },
    },
    yAxis: {
      type: 'value',
      position: 'right',
      interval: 25,
      //   max: 75.0,
      show: true,
      axisLabel: {
        color: '#323232',
        fontWeight: 'bold',
        formatter: function (value) {
          return value > 0 ? value.toFixed(2) : value
        },
      },
    },
    series: [
      {
        data: yAxisData,
        type: 'line',
        sampling: 'lttb',
        symbol: 'none',
        lineStyle: {
          color: '#2c6288',
        },
        areaStyle: {
          color: {
            type: 'linear',
            x: 0,
            y: 0,
            x2: 0,
            y2: 1,
            colorStops: [
              {
                offset: 0,
                color: '#2c6288',
              },
              {
                offset: 1,
                color: '#F4F6F8',
              },
            ],
          },
        },
        markPoint: {
          symbol: 'image://' + markPointerIcon,
          symbolSize: 24,
          data: [],
        },
        progressive: 500,
        progressiveThreshold: 3000,
        large: true,
        largeThreshold: 2000
      },
    ],

    dataZoom: [
      {
        type: 'inside',
      },
      {
        type: 'slider',
        show: true,
        dataBackground: {
          lineStyle: {
            color: '#2C6288',
          },
          areaStyle: {
            color: {
              type: 'linear',
              x: 0,
              y: 0,
              x2: 0,
              y2: 1,
              colorStops: [
                { offset: 1, color: '#2c6288' },
                { offset: 0, color: '#F4F6F8' },
              ],
            },
          },
        },
        selectedDataBackground: {
          lineStyle: {
            color: '#2C6288',
          },
          areaStyle: {
            color: {
              type: 'linear',
              x: 0,
              y: 0,
              x2: 0,
              y2: 1,
              colorStops: [
                { offset: 1, color: '#2c6288' },
                { offset: 0, color: '#F4F6F8' },
              ],
            },
          },
        },
        fillerColor: 'rgba(44, 98, 136, 0.3)',
        realtime: false,
      },
    ],
  })

  // 监听 showTip 事件，动态显示 markPoint
  myCharts.on('showTip', function (params) {
    if (params) {
      const dataIndex = params.dataIndex
      const x = myCharts.getOption().xAxis[0].data[dataIndex]
      const y = myCharts.getOption().series[0].data[dataIndex]
      myCharts.setOption({
        series: [
          {
            markPoint: {
              symbol: 'image://' + markPointerIcon,
              symbolSize: 24,
              data: [{ coord: [x, y] }],
            },
          },
        ],
      })
    }
  })
  // 鼠标移出时，清除 markPoint
  myCharts.on('globalout', function () {
    myCharts.setOption({
      series: [
        {
          markPoint: {
            symbol: 'image://' + markPointerIcon,
            symbolSize: 24,
            data: [],
          },
        },
      ],
    })
  })
  myCharts.on('dataZoom', function (params) {
    // 获取当前 dataZoom 范围
    const option = myCharts.getOption()
    const xAxisData = option.xAxis[0].data
    const dataZoom = option.dataZoom[1] || option.dataZoom[0]

    // 获取 dataZoom 的 startValue 和 endValue
    let startValue = dataZoom.endValue
    let endValue = dataZoom.startValue

    // 如果是索引，转为日期
    if (typeof startValue === 'number') {
      startValue = xAxisData[startValue]
    }
    if (typeof endValue === 'number') {
      endValue = xAxisData[endValue]
    }

    // 更新日期选择器
    state.selectHistoricStartDate = new Date(startValue)
    state.selectHistoricEndDate = new Date(endValue)
  })
}

onMounted(() => {
  getHistoricalData()
})

//获取历史数据
const getHistoricalData = async () => {
  let now = new Date()
  let toDate =
    now.getFullYear() +
    '-' +
    String(now.getMonth() + 1).padStart(2, '0') +
    '-' +
    String(now.getDate()).padStart(2, '0')
  let url =
    'https://common.szjixun.cn/api/stock/history/base/list?from=2009-10-07&to=' +
    toDate
  const res = await axios.get(url)
  if (res.status === 200) {
    if (res.data.status === 0) {
      initEcharts(res.data.data)
    }
  }
}

// 适配倒序数据，返回大于等于目标日期的最近一天索引
function findClosestDateIndex(data, targetDateStr) {
  let left = 0,
    right = data.length - 1
  const target = new Date(targetDateStr).getTime()
  let res = data.length - 1 // 默认返回最后一个
  while (left <= right) {
    const mid = Math.floor((left + right) / 2)
    const midTime = new Date(data[mid].date).getTime()
    if (midTime > target) {
      left = mid + 1
    } else {
      res = mid
      right = mid - 1
    }
  }
  return res
}

// 适配倒序数据，返回小于等于目标日期的最近一天索引
function findClosestDateIndexDescLeft(data, targetDateStr) {
  let left = 0,
    right = data.length - 1
  const target = new Date(targetDateStr).getTime()
  let res = -1
  while (left <= right) {
    const mid = Math.floor((left + right) / 2)
    const midTime = new Date(data[mid].date).getTime()
    if (midTime > target) {
      left = mid + 1 // mid 比目标新，往更旧的方向找
    } else {
      res = mid     // mid <= target，记录下来，继续往更新的方向找
      right = mid - 1
    }
  }
  return res
}

//点击切换搜索区间
const changeSearchRange = (range, dateTime) => {
  const now = new Date()
  let startDate = ''
  let endDate = ''
  if (range === '1m') {
    const last = new Date(now)
    last.setMonth(now.getMonth() - 1)
    startDate = last.toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
    endDate = new Date(new Date()).toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
  } else if (range === '3m') {
    const last = new Date(now)
    last.setMonth(now.getMonth() - 3)
    startDate = last.toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
    endDate = new Date(new Date()).toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
  } else if (range === 'YTD') {
    startDate = new Date(now.getFullYear(), 0, 1).toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
    endDate = new Date(new Date()).toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
  } else if (range === '1Y') {
    const last = new Date(now)
    last.setFullYear(now.getFullYear() - 1)
    startDate = last.toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
    endDate = new Date(new Date()).toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
  } else if (range === '5Y') {
    const last = new Date(now)
    last.setFullYear(now.getFullYear() - 5)
    startDate = last.toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
    endDate = new Date(new Date()).toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
  } else if (range === '10Y') {
    const last = new Date(now)
    last.setFullYear(now.getFullYear() - 10)
    startDate = last.toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
    endDate = new Date(new Date()).toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
  } else if (range === 'Max') {
    startDate = ''
    endDate = ''
  } else if (range === 'startDateTime') {
    startDate = dateTime
    endDate = ''
  } else if (range === 'endDateTime') {
    startDate = ''
    endDate = dateTime
  }
  if (startDate || endDate) {
    // historicData 和 xAxisData 需在 initEcharts 作用域可用
    if (
      typeof historicData !== 'undefined' &&
      typeof xAxisData !== 'undefined'
    ) {
      let startValue = xAxisData[0]
      if (startDate) {
        const idx = findClosestDateIndex(historicData, startDate)
        // 用 historicData[idx].date 格式化为 xAxisData 的格式
        startValue = new Date(historicData[idx].date).toLocaleDateString(
          'en-US',
          {
            month: 'short',
            day: 'numeric',
            year: 'numeric',
          },
        )
      }
      let endValue = endDate
      if (endDate) {
        // console.warn(endDate)
        const idx = findClosestDateIndexDescLeft(historicData, endDate)
        // console.warn(idx)
        // 用 historicData[idx].date 格式化为 xAxisData 的格式
        endValue = new Date(historicData[idx].date).toLocaleDateString(
          'en-US',
          {
            month: 'short',
            day: 'numeric',
            year: 'numeric',
          },
        )
        // console.warn(endValue)
      }

      if (startDate) {
        myCharts.setOption({
          dataZoom: {
            endValue: startValue,
          },
        })
        state.selectHistoricStartDate = new Date(startValue)
      }
      if (endDate) {
        myCharts.setOption({
          dataZoom: {
            startValue: endValue,
          },
        })
        state.selectHistoricEndDate = new Date(endValue)
      }
    }
  } else {
    myCharts.setOption({
      dataZoom: {
        startValue: '',
        endValue: '',
      },
    })

    state.selectHistoricStartDate = new Date('2009-10-07')
    state.selectHistoricEndDate = new Date()
  }
}

// 禁用2009-10-07之后的日期
const disableAfterDate = (date) => {
  return date < new Date('2009-10-06') || date > new Date()
}

// 禁用过去的日期
const disablePreviousDate = (date) => {
  return date < new Date(state.selectHistoricStartDate) || date > new Date()
}

// 切换搜索区间开始日期
const changeSearchRangeStartDate = (date) => {
  // console.error(date)
  changeSearchRange(
    'startDateTime',
    new Date(date).toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    }),
  )
}

// 切换搜索区间结束日期
const changeSearchRangeEndDate = (date) => {
  // console.error(date)
  changeSearchRange(
    'endDateTime',
    new Date(date).toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    }),
  )
}
</script>
<style lang="scss" scoped>
.custom-echarts {
  .myChart {
    width: 100%;
    height: 25rem;
  }

  .echarts-header {
    .echarts-header-title {
      span {
        font-size: 2rem;
        font-weight: 600;
        color: #323232;
      }
    }
    .echarts-search-area {
      padding: 2rem 0 0;
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: space-between;

      .echarts-search-byRange {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
        gap: 10px;
        .search-range-list {
          display: flex;
          flex-direction: row;
          align-items: center;
          justify-content: flex-start;
          gap: 10px;
          .search-range-list-each {
            padding: 5px 10px;
            border-radius: 5px;
            background-color: #f3f4f6;
            cursor: pointer;
            span {
              font-weight: 600;
              font-size: 0.9rem;
            }
          }
        }
      }

      .echarts-search-byDate {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
        gap: 0.4rem;
      }
    }
  }
}
</style>
