<script setup lang="ts">
import { ClassroomComplianceAPIClient, ComplianceLevel, getCategoryScore, getComplianceLevel, type Class, type Entry, type Student, type StudentStatisticsOverview } from '@/api/classroom_compliance'
import ConfirmDialog from '@/components/ConfirmDialog.vue'
import { useAuthStore } from '@/stores/auth'
import { computed, onMounted, ref, useTemplateRef, type Ref } from 'vue'
import { useRouter } from 'vue-router'
import StudentEntriesList from './StudentEntriesList.vue'
import { APIError } from '@/api/base'
import { formatScorePercent, getFormattedDate } from '@/util'

const props = defineProps<{
  classId: string
  studentId: string
}>()
const authStore = useAuthStore()
const router = useRouter()

const cls: Ref<Class | null> = ref(null)
const student: Ref<Student | null> = ref(null)
const entries: Ref<Entry[]> = ref([])
const labels: Ref<string[]> = ref([])
const newLabel = ref('')
const statistics: Ref<StudentStatisticsOverview | null> = ref(null)
// Filtered set of entries for "last week", used in the week overview dialog.
const lastWeeksEntries = computed(() => {
  const now = new Date()
  now.setHours(0, 0, 0, 0)
  const toDate = new Date()
  if (now.getDay() >= 1 && now.getDay() <= 5) {
    // If we're currently in a week, shift the to-date to the Friday of this week.
    const dayDiff = 5 - now.getDay()
    toDate.setDate(now.getDate() + dayDiff)
  } else {
    // If it's saturday or sunday, shift back to the previous Friday.
    if (now.getDay() === 6) {
      toDate.setDate(now.getDate() - 1)
    } else {
      toDate.setDate(now.getDate() - 2)
    }
  }

  const fromDate = new Date()
  fromDate.setHours(0, 0, 0, 0)
  fromDate.setDate(toDate.getDate() - 4)

  const filtered = entries.value
    .filter(e => new Date(e.date + 'T00:00:00').getTime() >= fromDate.getTime() &&
      new Date(e.date + 'T00:00:00').getTime() <= toDate.getTime())
  filtered.sort((a, b) => new Date(b.date + 'T00:00:00').getTime() - new Date(a.date + 'T00:00:00').getTime())
  return filtered
})

const apiClient = new ClassroomComplianceAPIClient(authStore)
const deleteConfirmDialog = useTemplateRef('deleteConfirmDialog')
const weekOverviewDialog = useTemplateRef('weekOverviewDialog')
const labelsDialog = useTemplateRef('labelsDialog')

onMounted(async () => {
  const classIdNumber = parseInt(props.classId, 10)
  cls.value = await apiClient.getClass(classIdNumber).handleErrorsWithAlert()
  if (!cls.value) {
    await router.replace('/classroom-compliance')
    return
  }
  const studentIdNumber = parseInt(props.studentId, 10)
  student.value = await apiClient.getStudent(classIdNumber, studentIdNumber).handleErrorsWithAlert()
  if (!student.value) {
    await router.replace(`/classroom-compliance/classes/${cls.value.id}`)
    return
  }

  apiClient.getStudentEntries(cls.value.id, student.value.id).handleErrorsWithAlert()
    .then(values => {
      if (values !== null) {
        entries.value = values
      }
    })
  apiClient.getStudentStatisticsOverview(cls.value.id, student.value.id).result
    .then(result => {
      if (!(result instanceof APIError)) {
        statistics.value = result
      } else {
        console.warn('Failed to get student statistics: ', result.message)
      }
    })
  fetchLabels()
})

async function fetchLabels() {
  if (!cls.value || !student.value) {
    labels.value = []
    return
  }
  const result = await apiClient.getStudentLabels(cls.value.id, student.value.id).result
  if (result instanceof APIError) {
    console.error("Failed to get labels.", result.message)
    labels.value = []
  } else {
    labels.value = result
  }
}

async function deleteThisStudent() {
  if (!cls.value || !student.value || cls.value.archived) return
  const choice = await deleteConfirmDialog.value?.show()
  if (!choice) return
  await apiClient.deleteStudent(cls.value.id, student.value.id)
  await router.replace(`/classroom-compliance/classes/${cls.value.id}`)
}

async function addLabel() {
  if (!cls.value || !student.value || cls.value.archived) return
  const newLabels = [...labels.value, newLabel.value.trim()]
  const success = await apiClient.updateStudentLabels(cls.value.id, student.value.id, newLabels)
    .handleErrorsWithAlertNoBody()
  if (success) {
    newLabel.value = ''
    await fetchLabels()
  }
}

async function deleteLabel(label: string) {
  if (!cls.value || !student.value || cls.value.archived) return
  const newLabels = labels.value.filter(s => s !== label)
  const success = await apiClient.updateStudentLabels(cls.value.id, student.value.id, newLabels)
    .handleErrorsWithAlertNoBody()
  if (success) {
    await fetchLabels()
  }
}
</script>
<template>
  <div v-if="student" class="centered-content">
    <h1 class="align-center" style="margin-bottom: 0;">{{ student.name }}</h1>
    <p class="align-center" style="margin-top: 0;">
      in
      <RouterLink class="link link-color" :to="'/classroom-compliance/classes/' + classId">
        <span v-text="'class ' + cls?.number"></span>
      </RouterLink>
    </p>

    <div class="button-bar align-center">
      <button type="button"
        @click="router.push(`/classroom-compliance/classes/${student.classId}/edit-student?studentId=${student.id}`)"
        :disabled="cls?.archived">Edit</button>
      <button type="button" @click="deleteThisStudent" :disabled="cls?.archived">Delete</button>
      <button type="button" @click="weekOverviewDialog?.showModal()" :disabled="lastWeeksEntries.length < 1">Week
        overview</button>
      <button type="button" @click="labelsDialog?.showModal()">Labels</button>
    </div>

    <table class="student-properties-table">
      <tbody>
        <tr>
          <th>Desk Number</th>
          <td>
            <span v-if="student.deskNumber !== 0">{{ student.deskNumber }}</span>
            <span v-if="student.deskNumber === 0" style="font-style: italic; font-size: small;">No assigned desk</span>
          </td>
        </tr>
        <tr>
          <th>Removed</th>
          <td>{{ student.removed ? 'True' : 'False' }}</td>
        </tr>
        <tr v-if="statistics">
          <th>Attendance Rate</th>
          <td>{{ (statistics.attendanceRate * 100).toFixed(1) }}%</td>
        </tr>
        <tr v-if="statistics">
          <th>Total Entries</th>
          <td>{{ statistics.entryCount }}</td>
        </tr>
      </tbody>
    </table>

    <StudentEntriesList :student="student" />

    <ConfirmDialog ref="deleteConfirmDialog">
      <p>
        Are you sure you want to delete <span v-text="student.name"></span>? This will permanently
        delete all records for them.
      </p>
      <p>This <strong>cannot</strong> be undone!</p>
    </ConfirmDialog>

    <!-- Dialog that, when opened, shows an overview of the student's activity for the current week. -->
    <dialog ref="weekOverviewDialog" method="dialog" class="weekly-overview-dialog">
      <div>
        <h2>This week's overview for <span v-text="student.name"></span></h2>
        <div v-for="entry in lastWeeksEntries" :key="entry.date" class="weekly-overview-dialog-day">
          <h4>{{ getFormattedDate(entry.date) }}</h4>

          <div v-if="entry.absent">
            <p style="color: gray;">Absent</p>
          </div>


          <div v-if="getComplianceLevel(entry, 'Classroom Readiness') !== null">
            <h5>Classroom Readiness: {{ formatScorePercent(getCategoryScore(entry, 'Classroom Readiness')) }}</h5>
            <p v-if="getComplianceLevel(entry, 'Classroom Readiness') === ComplianceLevel.Good">✅ Ready for class</p>
            <p v-if="getComplianceLevel(entry, 'Classroom Readiness') !== ComplianceLevel.Good">❌ Not ready for class
            </p>
          </div>

          <div v-if="getComplianceLevel(entry, 'Behavior') !== null">
            <h5>Behavior: {{ formatScorePercent(getCategoryScore(entry, 'Behavior')) }}</h5>
            <p v-if="getComplianceLevel(entry, 'Behavior') === ComplianceLevel.Poor">
              Poor
            </p>
            <p v-if="getComplianceLevel(entry, 'Behavior') === ComplianceLevel.Mediocre">
              Mediocre
            </p>
            <p v-if="getComplianceLevel(entry, 'Behavior') === ComplianceLevel.Good">
              Good
            </p>
          </div>

          <div v-if="entry.comment.length > 0">
            <h5>Instructor Remarks</h5>
            <p>{{ entry.comment }}</p>
          </div>

          <div v-if="entry.checklistItems.filter(ck => ck.checked).length > 0">
            <h5>Classroom Readiness & Behavioral Issues</h5>
            <ul>
              <li v-for="item in entry.checklistItems.filter(ck => ck.checked)" :key="item.category + item.item">
                {{ item.item }}
              </li>
            </ul>
          </div>
        </div>
      </div>
      <div class="button-bar align-right">
        <button @click.prevent="weekOverviewDialog?.close()">Close</button>
      </div>
    </dialog>

    <!-- Dialog for editing a student's labels. -->
    <dialog ref="labelsDialog" method="dialog">
      <div>
        <h2>Labels</h2>
        <div v-for="label in labels" :key="label"
          style="display: flex; flex-direction: row; justify-content: space-between; margin: 0.75rem 0;">
          <span>{{ label }}</span>
          <span style="cursor: pointer;" @click="deleteLabel(label)">❌</span>
        </div>
        <div>
          <input type="text" v-model="newLabel" />
          <button type="button" :disabled="newLabel.trim().length === 0 || cls?.archived"
            @click="addLabel()">Add</button>
        </div>
      </div>
      <div>
        <button type="button" @click="labelsDialog?.close()">Close</button>
      </div>
    </dialog>
  </div>
</template>
<style scoped>
.student-properties-table {
  width: 100%;
  border-collapse: collapse;
}

.student-properties-table :is(th, td) {
  border: 1px solid gray;
  padding: 0.25em;
}

.student-properties-table td {
  text-align: right;
  font-family: 'SourceCodePro', monospace;
}

.weekly-overview-dialog-day {
  margin-left: 1rem;
}

.weekly-overview-dialog h4 {
  margin: 1rem 0 -0.5rem -1rem;
}

.weekly-overview-dialog h5 {
  margin: 1rem 0 0.5rem 0;
}

.weekly-overview-dialog p {
  margin: 0.5rem 0 0.5rem 1rem;
  font-size: 12px;
}

.weekly-overview-dialog ul {
  margin: 0.5rem 0;
  padding-left: 1.5rem;
  font-size: 12px;
}
</style>
