<script setup lang="ts">
import { $font_color } from '@/styles/variate'
import Chart from 'chart.js/auto'

const props = defineProps<{
  data: anyObj
  learned: anyObj[]
}>()

const chartRef: Ref<HTMLCanvasElement | null> = ref(null)
const chart: Ref<Chart | null> = shallowRef(null)

const visibleLegends = ref(['increase', 'decrease'])

const updateChart = () => {
  if (!chart.value) return

  const { knowCount, unfamiliarCount, graspCount } = props.data

  const filteredData = [unfamiliarCount, knowCount, graspCount]
    .filter(
      v =>
        (visibleLegends.value.includes('increase') && v >= 0) ||
        (visibleLegends.value.includes('decrease') && v < 0),
    )
    .map(v => Math.abs(v))

  const filteredLabels = [unfamiliarCount, knowCount, graspCount]
    .map((v, i) => {
      const label = ['陌生数', '熟悉数', '掌握数'][i]
      return (visibleLegends.value.includes('increase') && v >= 0) ||
        (visibleLegends.value.includes('decrease') && v < 0)
        ? label
        : ''
    })
    .filter(Boolean)

  const backgroundColors = [unfamiliarCount, knowCount, graspCount]
    .filter(
      v =>
        (visibleLegends.value.includes('increase') && v >= 0) ||
        (visibleLegends.value.includes('decrease') && v < 0),
    )
    .map(v => (v < 0 ? '#F94A55' : '#3FD15F'))

  chart.value.data.datasets[0].data = filteredData
  chart.value.data.datasets[0].backgroundColor = backgroundColors
  chart.value.data.labels = filteredLabels
  chart.value.update('none')
}

const handleToggleLegend = (type: 'increase' | 'decrease') => {
  const index = visibleLegends.value.indexOf(type)
  if (index === -1) {
    visibleLegends.value.push(type)
  } else {
    visibleLegends.value.splice(index, 1)
  }

  updateChart()
}

onMounted(() => {
  const { knowCount, unfamiliarCount, graspCount } = props.data
  ;[unfamiliarCount, knowCount, graspCount]
    .filter(v => {
      return visibleLegends.value.includes('increase')
        ? v >= 0
        : visibleLegends.value.includes('decrease')
          ? v < 0
          : false
    })
    .map(v => Math.abs(v))
  if (chartRef.value !== null) {
    chart.value = new Chart(chartRef.value, {
      type: 'bar',
      data: {
        labels: ['陌生数', '熟悉数', '掌握数'],
        datasets: [
          {
            data: [unfamiliarCount, knowCount, graspCount]
              .filter(
                v =>
                  (visibleLegends.value.includes('increase') && v >= 0) ||
                  (visibleLegends.value.includes('decrease') && v < 0),
              )
              .map(v => Math.abs(v)),
            backgroundColor: [unfamiliarCount, knowCount, graspCount].map(v =>
              v < 0 ? '#F94A55' : '#3FD15F',
            ),
            borderColor: 'transparent',
          },
        ],
      },
      options: {
        maxBarThickness: 128,
        scales: {
          y: {
            beginAtZero: true,
            border: {
              dash: ({ index }) => {
                if (index === 0) {
                  return []
                }
                return [8, 10]
              },
              color: 'rgba(138, 148, 253, 0.25)',
            },
            ticks: {
              padding: 16,
              color: '#666',
              font: {
                size: 28,
                lineHeight: '42px',
              },
            },
            grid: {
              display: true,
              lineWidth: 2,
              color: 'rgba(138, 148, 253, 0.25)',
              drawTicks: false,
            },
          },
          x: {
            border: {
              width: 2,
              color: 'rgba(138, 148, 253, 0.65)',
            },
            ticks: {
              padding: 16,
              color: '#666',
              font: {
                size: 28,
                lineHeight: '42px',
              },
            },
            grid: {
              display: false,
              drawTicks: false,
            },
          },
        },
        plugins: {
          tooltip: {
            enabled: false,
          },
          legend: {
            display: false,
          },
        },
        events: [],
        animation: {
          onComplete() {
            const chartInstance = chart.value
            if (!chartInstance) {
              return
            }
            const ctx = chartInstance.ctx

            ctx.textAlign = 'center'
            ctx.font = '32px Arial'
            ctx.fillStyle = $font_color

            this.data.datasets.forEach((dataset, i) => {
              const meta = chartInstance.getDatasetMeta(i)
              meta.data.forEach((bar, index) => {
                const data = dataset.data[index]
                ctx.fillText(String(data), bar.x, bar.y - 12)
              })
            })
          },
        },
      },
    })
  }
})

const kps = computed(() => {
  return (props.learned ?? []).map((item: anyObj) => {
    return {
      id: item.id,
      name: item.name,
      times: item.answerCount,
      mastery: ['', '陌生', '熟悉', '已掌握'][item.masteryDegree],
    }
  })
})
</script>

<template>
  <h3>
    <LineFont text="知识图谱统计" size="48" />
  </h3>
  <h4>
    <LineFont text="我的知识图谱变化情况" size="40" />
  </h4>
  <div class="chart-container">
    <ul class="chart-legend">
      <li
        :class="{ invisible: !visibleLegends.includes('increase') }"
        :style="{ '--color': '#3FD15F' }"
        @click="handleToggleLegend('increase')"
      >
        增加
      </li>
      <li
        :class="{ invisible: !visibleLegends.includes('decrease') }"
        :style="{ '--color': '#F94A55' }"
        @click="handleToggleLegend('decrease')"
      >
        减少
      </li>
    </ul>
    <canvas ref="chartRef"></canvas>
  </div>

  <h4>
    <LineFont text="已学知识点及掌握程度" size="40" />
  </h4>
  <div class="table-container">
    <table>
      <thead>
        <tr>
          <th>知识点名称</th>
          <th>答题次数</th>
          <th>掌握程度</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="kp in kps" :key="kp.id">
          <td>
            <span :class="{ flag: !!kp.id }">{{ kp.name }}</span>
          </td>
          <td>{{ kp.times }}</td>
          <td :class="{ 已掌握: 'mastered', 陌生: 'unfamiliar', 熟悉: 'familiar' }[kp.mastery]">
            {{ kp.mastery }}
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<style scoped lang="scss">
.chart-legend {
  text-align: center;
  color: #666;
  font-size: 2.33vh;
  line-height: 3.5vh;
  margin-bottom: 2vh;

  > li {
    display: inline-flex;
    align-items: center;

    + li {
      margin-left: 32px;
    }

    &.invisible {
      color: #666;
      text-decoration: line-through;

      &:before {
        background: #999;
      }
    }

    &:before {
      content: '';
      width: 28px;
      height: 0.5vh;
      background-color: var(--color);
      margin-right: 10px;
    }
  }
}

.flag {
  color: #8409d6;
  position: relative;
  display: inline-block;

  &:after {
    display: block;
    content: '';
    position: absolute;
    width: 100%;
    top: 100%;
    height: 0.92vh;
    background: url(../assets/timetable/wave.svg) repeat-x;
    background-size: auto 11px;
  }
}

.mastered {
  color: #2f8a5b;
}

.unfamiliar {
  color: #a13c00;
}

.familiar {
  color: #2d39bc;
}

.table-container {
  padding: 0 16px;
  margin-top: 4vh;
  margin-bottom: 4vh;
}

.chart-container {
  padding: 0 84px;
  margin-top: 4vh;
}

table {
  background: #fff;
  border-radius: 1.67vh;
  overflow: hidden;
  border-collapse: collapse;
  width: 100%;
  color: $font-color;
  font-size: 2.33vh;
  line-height: 3.5vh;
  text-align: center;
}

tr {
  position: relative;
}

tr::before {
  content: '';
  position: absolute;
  height: 0.17vh;
  bottom: 0;
  width: 100%;
  background: repeating-linear-gradient(
    to right,
    #deedfc,
    #deedfc 8px,
    transparent 8px,
    transparent 16px
  );
}

td,
th {
  padding: 2vh 32px;
}

th,
td {
  position: relative;
  white-space: nowrap;

  &:not(:last-child):after {
    content: '';
    position: absolute;
    height: 100%;
    bottom: 0;
    right: 0;
    width: 2px;
    background: repeating-linear-gradient(
      to bottom,
      #deedfc,
      #deedfc 8px,
      transparent 8px,
      transparent 16px
    );
  }
}

thead {
  background: #c7ccff;
}

h3,
h4 {
  text-align: center;
  margin-top: 6vh;
  font-weight: normal;
}

h3 {
  margin-top: 8vh;
}

h4 {
  margin-top: 4vh;
}

.title-outline {
  line-height: normal;
}
</style>
