<script setup>
import { onMounted, ref, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { getTerms, createTerm, updateTerm, deleteTerm } from '@/api/termService.js'
import { getStudents } from '@/api/studentService.js'
import { fromApiBool } from '@/api/boolCodec.js'
import { useCrudList } from '@/composables/useCrudList.js'
import { useFlashMessage } from '@/composables/useFlashMessage.js'
import TermTable from '@/components/term/TermTable.vue'
import TermEditDialog from '@/components/term/TermEditDialog.vue'
import TermDeleteDialog from '@/components/term/TermDeleteDialog.vue'

const { t } = useI18n()

// Reference data (view-owned per R2 — composable does not see it).
const students = ref([])
async function fetchStudents() {
  try {
    const data = await getStudents()
    students.value = Array.isArray(data) ? data : []
  } catch (e) {
    // Pre-existing silent failure: terms will show unknownStudent.
    console.error('Failed to fetch students:', e)
  }
}

// Dropdown options — filter to enabled students only.
const studentOptions = computed(() =>
  students.value
    .filter((s) => fromApiBool(s.enabled))
    .map((s) => ({ title: s.student_name, value: s.student_id })),
)

// mapRow: denormalize student_name into each term. Applied at fetch AND
// inside applySaved so a newly-saved term gets the join immediately
// (fixes the pre-existing "locally saved term has no student_name" bug).
function joinStudentName(term) {
  const student = students.value.find((s) => s.student_id === term.student_id)
  return { ...term, student_name: student ? student.student_name : t('term.messages.unknownStudent') }
}

const crud = useCrudList({
  list: getTerms,
  create: createTerm,
  update: updateTerm,
  deleteFn: deleteTerm,
  idKey: 'term_id',
  mapRow: joinStudentName,
  loadErrorKey: t('term.messages.loadError'),
})

const flash = useFlashMessage()

// fetchTerms must run AFTER fetchStudents — the mapRow join needs
// `students` populated. Do NOT switch to Promise.all.
onMounted(async () => {
  await fetchStudents()
  await crud.fetch()
})

function onSaved(entity) {
  const isCreate = crud.applySaved(entity)
  flash.show(t(isCreate ? 'term.messages.createSuccess' : 'term.messages.updateSuccess'))
}

function onDeleted(id) {
  const item = crud.items.value.find((x) => x.term_id === id)
  crud.applyDeleted(id)
  flash.show(t('term.messages.deleteSuccess', { name: item?.term_name ?? '' }))
  crud.closeEdit()
}
</script>

<template>
  <v-container fluid>
    <v-row class="mb-4" align="center" justify="space-between">
      <v-col cols="12" sm="6">
        <h2 class="text-h5">{{ t('term.title') }}</h2>
      </v-col>
      <v-col cols="12" sm="6" class="text-sm-right text-right">
        <v-btn
          color="success"
          prepend-icon="mdi-plus"
          class="mr-2"
          @click="crud.openCreate()"
        >
          {{ t('term.buttons.addTerm') }}
        </v-btn>
        <v-btn
          color="primary"
          prepend-icon="mdi-refresh"
          :loading="crud.isLoading.value"
          @click="crud.fetch()"
        >
          {{ t('common.buttons.refresh') }}
        </v-btn>
      </v-col>
    </v-row>

    <v-alert
      v-if="flash.message.value"
      type="success"
      class="mb-4"
      closable
      @click:close="flash.clear()"
    >
      {{ flash.message.value }}
    </v-alert>

    <v-alert v-if="crud.isError.value" type="error" class="mb-4" closable>
      {{ crud.errorMessage.value }}
    </v-alert>

    <v-progress-linear
      v-if="crud.isLoading.value"
      indeterminate
      color="primary"
      class="mb-4"
    ></v-progress-linear>

    <TermTable
      :items="crud.items.value"
      @edit="crud.openEdit"
      @delete="crud.openDelete"
    />

    <TermEditDialog
      :open="crud.editingDialogOpen.value"
      :term="crud.editingItem.value"
      :student-options="studentOptions"
      @close="crud.closeEdit()"
      @saved="onSaved"
    />

    <TermDeleteDialog
      :open="crud.deleteDialogOpen.value"
      :term="crud.itemToDelete.value"
      @close="crud.closeDelete()"
      @deleted="onDeleted"
    />
  </v-container>
</template>