<script setup lang="ts">
import { watch, ref, onMounted, computed } from "vue"
import { useI18n } from "vue-i18n"
import { createReadableMetricValue, getEvalColor, mapGtId } from "@/helpers/utils"
import type { EvaluationRun } from "@/types"
import Dropdown from 'primevue/dropdown'
import workflowsStore from "@/store/workflows-store"
import api from "@/helpers/api"
import filtersStore from "@/store/filters-store"

const { t } = useI18n()

const groupedData = ref({})
const evals = ref([])

const sortOptions = ref([{
  value: 'documents',
  label: t('documents')
}, {
  value: 'workflows',
  label: t('workflows')
}])

const sortBy = ref(sortOptions.value[0])
const latestRuns = ref<EvaluationRun[]>([])
const filteredRuns = ref<EvaluationRun[]>([])
const evalDefinitions = ref([])
const loading = ref(false)

onMounted(async () => {
  loading.value = true
  latestRuns.value = workflowsStore.getLatestRuns()
  evalDefinitions.value = await api.getEvalDefinitions()
  setFilteredRuns()
  groupRuns(sortBy.value.value)
  loading.value = false
})

watch(() => filtersStore.gt, () => {
  setFilteredRuns()
  groupRuns(sortBy.value.value)
})

watch(sortBy, () => {
  groupRuns(sortBy.value.value)
})

function setFilteredRuns() {
  filteredRuns.value = latestRuns.value.filter(({ metadata }) => filtersStore.gt.findIndex(({ value }) => value === mapGtId(metadata.gt_workspace.id)) > -1)
}

function groupRuns(groupBy: string) {
  if (groupBy === 'workflows') groupByWorkflows()
  else if (groupBy === 'documents') groupByDocuments()
}

const groupByWorkflows = () => {
  groupedData.value = filteredRuns.value.filter(item => !!(item.metadata.ocr_workflow)).reduce((acc, cur) => {
    const ocrWorkflowId = mapGtId(cur.metadata.ocr_workflow['id'])
    const label = workflowsStore.getWorkflowById(ocrWorkflowId)?.label

    evals.value = Object.keys(cur.evaluation_results.document_wide)

    const subject = {
      label: workflowsStore.getGtById(mapGtId(cur.metadata.gt_workspace.id))?.label,
      evaluations: Object.keys(cur.evaluation_results.document_wide).map(key => ({
        name: key,
        value: cur.evaluation_results.document_wide[key]
      }))
    }
    if (!acc[ocrWorkflowId]) {
      acc[ocrWorkflowId] = {
        label,
        subjects: [subject]
      }
    } else {
      acc[ocrWorkflowId].subjects.push(subject)
      acc[ocrWorkflowId].subjects.sort((a, b) => {
        if (a.label > b.label) return 1
        else return -1
      })
    }
    return acc
  }, {})
}

const groupByDocuments = () => {
  groupedData.value = filteredRuns.value.filter(item => !!(item.metadata.gt_workspace)).reduce((acc, cur) => {
    const gtWorkspaceId = mapGtId(cur.metadata.gt_workspace['id'])
    const label = workflowsStore.getGtById(gtWorkspaceId)?.label
    evals.value = Object.keys(cur.evaluation_results.document_wide)
    const subject = {
      label: workflowsStore.getWorkflowById(mapGtId(cur.metadata.ocr_workflow['id']))?.label,
      evaluations: Object.keys(cur.evaluation_results.document_wide).map(key => ({
        name: key,
        value: cur.evaluation_results.document_wide[key]
      }))
    }
    if (!acc[gtWorkspaceId]) {
      acc[gtWorkspaceId] = {
        label,
        subjects: [subject]
      }
    } else {
      acc[gtWorkspaceId].subjects.push(subject)
      acc[gtWorkspaceId].subjects.sort((a, b) => {
        if (a.label > b.label) return 1
        else return -1
      })
    }
    return acc
  }, {})
}
</script>

<template>
  <template v-if="loading">
    Loading...
  </template>
  <template v-else>
    <div class="flex mb-4" v-if="evals.length > 0">
      <div class="flex items-center ml-auto">
        <p class="mr-2">{{ $t('group_by') }}:</p>
        <Dropdown v-model="sortBy" :options="sortOptions" optionLabel="label" placeholder="Choose something.." class="" />
      </div>
    </div>
    <table v-if="evals.length > 0" class="w-full border border-collapse rounded text-sm">
      <thead>
      <tr>
        <th class="p-2 border">{{ sortBy.value === 'documents' ? $t('documents') : $t('workflows') }}</th>
        <th class="p-2 border">{{ sortBy.value === 'documents' ? $t('workflows') : $t('documents') }}</th>
        <th v-for="(evalKey, i) in evals" :key="i" class="p-2 border">
          <span class="def-label flex items-center justify-center cursor-pointer">
            {{ evalDefinitions[evalKey] ? evalDefinitions[evalKey].label : evalKey }}
            <i-icon name="ink-info"/>
            <div class="def-tooltip">
              <div class="flex p-2 bg-white border rounded">
                {{ evalDefinitions[evalKey] ? evalDefinitions[evalKey].short_descr : $t('no_description') }}.
                <a v-if="evalDefinitions[evalKey]" :href="evalDefinitions[evalKey].url">{{ $t('details') }}</a>
              </div>
            </div>
          </span>
        </th>
      </tr>
      </thead>
      <tbody>
      <template v-for="(key, i) in Object.keys(groupedData)" :key="i">
        <tr v-for="(subject, j) in groupedData[key].subjects" :key="j">
          <td v-if="j === 0" :rowspan="groupedData[key].subjects.length" class="align-top pl-2 border w-1/3">
            <span class="font-bold">{{ groupedData[key].label }}</span>
          </td>
          <td class="align-top pl-2 border">{{ subject.label }}</td>
          <td
            v-for="({ name, value }, k) in subject.evaluations"
            :key="k"
            class="text-center pt-1 border"
            :class="(j === groupedData[key].subjects.length - 1) ? 'pb-5' : 'pb-1'"
          >
            <span
              class="metric inline-block cursor-pointer text-sm leading-none p-1 rounded-lg min-w-[48px]"
              :class="getEvalColor(name, value)">
              {{ createReadableMetricValue(name, value) }}
            </span>
          </td>
        </tr>
      </template>
      </tbody>
    </table>
    <div v-else>{{ $t('no_table_data') }}</div>
  </template>
</template>

<style scoped lang="scss">

.def-label {
  position: relative;

  &:hover {
    .def-tooltip {
      visibility: visible;
    }
  }
}

.def-tooltip {
  visibility: hidden;
  position: absolute;
  top: 0;
  transform: translateY(-100%);
  width: 300px;
  z-index: 100;
  padding-bottom: 10px;

  .card {
    box-shadow: rgba(0, 0, 0, 0.1) 0px 20px 25px -5px, rgba(0, 0, 0, 0.04) 0px 10px 10px -5px;
  }
}

th, th span {
  font-weight: bold;
}
</style>