<template>
  <BasicModal
    :title="isEditMode ? 'ویرایش تکلیف' : 'افزودن تکلیف جدید'"
    :title-en="isEditMode ? 'Edit Assignment' : 'Add Assignment'"
    width="95%"
    max-width="64rem"
    min-width="auto"
    :show-close-button="true"
  >
    <template #default="{ close }">
      <form class="add-assignment" @submit.prevent="onSubmit(close)">
        <div class="add-assignment__grid">
          <TextField
            v-model="form.title"
            name="title"
            label="عنوان تکلیف"
            :error="errors.title"
            @blur="validateAt('title', form.title)"
          >
            <template #appendIcon>
              <SvgIcon name="book" :size="20" color="var(--color-thd-gray)" />
            </template>
          </TextField>
          <SelectField
            v-model="form.termId"
            name="termId"
            label="ترم مرتبط"
            :options="termOptions"
            option-label="title"
            option-value="id"
            :searchable="true"
            :on-search="searchTerms"
            :error="errors.termId"
            @update:model-value="onTermChange"
          />
          <SelectField
            v-model="form.courseId"
            name="courseId"
            label="دوره مرتبط"
            :options="templateOptions"
            option-label="title"
            option-value="id"
            :searchable="true"
            :on-search="searchTemplates"
            :disabled="!form.termId"
            :error="errors.courseId"
            @update:model-value="onCourseChange"
          />
          <SelectField
            v-model="form.sessionId"
            name="sessionId"
            label="جلسه مرتبط"
            :options="sessionOptions"
            option-label="title"
            option-value="id"
            :searchable="true"
            :on-search="searchSessions"
            :disabled="!form.courseId"
            :error="errors.sessionId"
          />
          <DatePickerField
            v-model="form.deadline"
            name="deadline"
            label="ددلاین"
            :error="errors.deadline"
          />
          <SelectField
            v-model="form.priority"
            name="priority"
            label="اولویت تکلیف"
            :options="priorityOptions"
            option-label="label"
            option-value="value"
            :error="errors.priority"
          />
          <div class="add-assignment__cell--full">
            <TextareaField
              v-model="form.description"
              name="description"
              label="توضیحات تکلیف"
              :row="5"
            />
          </div>
        </div>

        <div class="add-assignment__files">
          <FileUploader
            v-model="attachments"
            accept=".mp4,.mov,.avi,.mp3,.wav,.jpg,.jpeg,.png,.pdf,.txt,.doc,.docx"
            :multiple="true"
            :max-files="10"
            @select="onAttachmentsSelect"
            @error="onAttachmentsError"
          />
        </div>

        <div class="add-assignment__divider" />

        <div class="add-assignment__actions">
          <BaseButton
            variant="transparent"
            text="منصرف شدم"
            custom-class="add-assignment__btn-cancel"
            @click="close"
          >
            <template #prependIcon>
              <SvgIcon name="caret-right" :size="14" color="var(--color-sec-gray)" />
            </template>
          </BaseButton>
          <BaseButton
            type="submit"
            text="تایید اطلاعات"
            :loading="submitting"
            custom-class="add-assignment__btn-submit"
          >
            <template #appendIcon>
              <SvgIcon name="arrow-left" :size="18" color="#fff" />
            </template>
          </BaseButton>
        </div>
      </form>
    </template>
  </BasicModal>
</template>

<script setup>
import { toast } from 'vue3-toastify'
import useYup from '@/composables/useYup'
import { computed, ref, watch } from 'vue'
import useModal from '@/composables/useModal'
import { ASSIGNMENT_PRIORITY } from '@/enums'
import useDebounce from '@/composables/useDebounce'
import { useQueryClient } from '@tanstack/vue-query'
import BasicModal from '@/components/BasicModal.vue'
import BaseButton from '@/components/BaseButton.vue'
import SvgIcon from '@/components/icons/SvgIcon.vue'
import TextField from '@/components/form/TextField.vue'
import SelectField from '@/components/form/SelectField.vue'
import FileUploader from '@/components/form/FileUploader.vue'
import { objectToFormData } from '@/utils/object-to-formdata'
import { useUploadMediaMutation } from '@/services/query/auth'
import TextareaField from '@/components/form/TextareaField.vue'
import DatePickerField from '@/components/form/DatePickerField.vue'
import { useAdminTermsListQuery } from '@/services/query/admin-terms'
import { assignmentSchema } from '@/features/admin/assignments/schema'
import { useAdminCoursesListQuery } from '@/services/query/admin-courses'
import { useAdminSessionsListQuery } from '@/services/query/admin-sessions'
import {
  adminAssignmentsKeys,
  useAddAdminAssignmentMutation,
  useAdminAssignmentQuery,
  useUpdateAdminAssignmentMutation,
} from '@/services/query/admin-assignments'

defineOptions({ name: 'AddAssignmentModal' })

const queryClient = useQueryClient()
const { getModal } = useModal()

const modalData = computed(() => getModal('AddAssignmentModal')?.data ?? {})
const assignmentId = computed(() => modalData.value.id ?? null)
const isEditMode = computed(() => !!assignmentId.value)

const priorityOptions = Object.entries(ASSIGNMENT_PRIORITY).map(([value, label]) => ({
  value,
  label,
}))

const form = ref({
  title: '',
  termId: '',
  courseId: '',
  sessionId: '',
  deadline: '',
  priority: 'mandatory',
  description: '',
})

const attachments = ref([])

const schema = assignmentSchema

const { validate, validateAt, errors, resetErrors } = useYup(schema)

const termSearch = ref('')
const termFilters = computed(() => ({ title: termSearch.value }))
const termPagination = ref({ page: 1, perPage: 10 })
const { data: termsResponse } = useAdminTermsListQuery(termFilters, termPagination)
const selectedTerm = ref(null)
const termOptions = computed(() => {
  const base = termsResponse.value?.data ?? []
  if (selectedTerm.value && !base.some((t) => t.id === selectedTerm.value.id)) {
    return [...base, selectedTerm.value]
  }
  return base
})

const templateSearch = ref('')
const templateFilters = computed(() => ({
  title: templateSearch.value,
  termId: form.value.termId || undefined,
}))
const templatePagination = ref({ page: 1, perPage: 10 })
const { data: templatesResponse } = useAdminCoursesListQuery(templateFilters, templatePagination, {
  enabled: () => !!form.value.termId,
})
const selectedTemplate = ref(null)
const templateOptions = computed(() => {
  const base = templatesResponse.value?.data ?? []
  if (selectedTemplate.value && !base.some((t) => t.id === selectedTemplate.value.id)) {
    return [...base, selectedTemplate.value]
  }
  return base
})

const sessionSearch = ref('')
const sessionFilters = computed(() => ({
  title: sessionSearch.value,
  courseId: form.value.courseId,
}))
const sessionPagination = ref({ page: 1, perPage: 10 })
const { data: sessionsResponse } = useAdminSessionsListQuery(sessionFilters, sessionPagination, {
  enabled: () => !!form.value.courseId,
})
const selectedSession = ref(null)
const sessionOptions = computed(() => {
  const base = sessionsResponse.value?.data ?? []
  if (selectedSession.value && !base.some((s) => s.id === selectedSession.value.id)) {
    return [...base, selectedSession.value]
  }
  return base
})

const searchTerms = useDebounce((q) => {
  termSearch.value = q || ''
}, 400)
const searchTemplates = useDebounce((q) => {
  templateSearch.value = q || ''
}, 400)
const searchSessions = useDebounce((q) => {
  sessionSearch.value = q || ''
}, 400)

const onTermChange = (value) => {
  form.value.termId = value
  form.value.courseId = ''
  form.value.sessionId = ''
  selectedTemplate.value = null
  selectedSession.value = null
}

const onCourseChange = (value) => {
  form.value.courseId = value
  form.value.sessionId = ''
  selectedSession.value = null
}

const uploadMediaMutation = useUploadMediaMutation()

const onAttachmentsSelect = async (files) => {
  for (const file of files) {
    try {
      const fd = objectToFormData({ file, purpose: 'homework_file', context: 'homework' })
      const response = await uploadMediaMutation.mutateAsync(fd)
      const payload = response?.data ?? response
      const id = payload?.id ?? payload?.uploadId
      if (id == null) continue
      attachments.value = [
        ...attachments.value,
        { id, name: file.name, size: file.size, url: payload?.url ?? '' },
      ]
    } catch {
      toast.error(`بارگذاری فایل "${file.name}" با خطا مواجه شد.`)
    }
  }
}

const onAttachmentsError = (msg) => toast.error(msg)

const { data: existingAssignment } = useAdminAssignmentQuery(assignmentId, {
  enabled: () => !!assignmentId.value,
})

watch(
  existingAssignment,
  (assignment) => {
    if (!assignment) return
    const sessionEntity = assignment.session
    const tpl = sessionEntity?.course || assignment.course
    const termEntity = tpl?.term || assignment.term
    const termId = termEntity?.id || tpl?.termId || assignment.termId || ''
    const priorityValue =
      assignment.priority ||
      (typeof assignment.isPriority === 'boolean'
        ? assignment.isPriority
          ? 'mandatory'
          : 'optional'
        : 'mandatory')
    if (termEntity) selectedTerm.value = termEntity
    if (tpl) selectedTemplate.value = tpl
    if (sessionEntity) selectedSession.value = sessionEntity
    form.value = {
      title: assignment.title || '',
      termId,
      courseId: tpl?.id || sessionEntity?.courseId || assignment.courseId || '',
      sessionId: sessionEntity?.id || assignment.sessionId || '',
      deadline: assignment.deadline || assignment.endDate || '',
      priority: priorityValue,
      description: assignment.description || '',
    }
    attachments.value = Array.isArray(assignment.media)
      ? assignment.media.map((m) => ({
          id: m.id,
          name: m.fileName || `فایل ${m.id}`,
          size: m.fileSize ?? 0,
          url: m.url || m.downloadUrl || '',
        }))
      : []
  },
  { immediate: false }
)

const addMutation = useAddAdminAssignmentMutation()
const updateMutation = useUpdateAdminAssignmentMutation()

const submitting = computed(() => addMutation.isPending.value || updateMutation.isPending.value)

const onSubmit = async (close) => {
  const { isValid, payload } = await validate(form.value)
  if (!isValid) return
  const finalPayload = {
    sessionId: payload.sessionId,
    title: payload.title,
    description: payload.description ?? '',
    deadline: payload.deadline || null,
    isActive: true,
    isPriority: payload.priority === 'mandatory',
    mediaIds: attachments.value.map((file) => file.id).filter((id) => id != null),
  }
  if (isEditMode.value) {
    await updateMutation.mutateAsync({ id: assignmentId.value, payload: finalPayload })
  } else {
    await addMutation.mutateAsync(finalPayload)
  }
  await queryClient.invalidateQueries({ queryKey: adminAssignmentsKeys.all })
  resetErrors()
  close()
}
</script>

<style lang="scss" scoped>
.add-assignment {
  width: 100%;
  text-align: start;
  padding: 0.5rem 0;

  &__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.5rem;
    margin-block: 0.75rem;

    @media (min-width: 768px) {
      grid-template-columns: repeat(2, 1fr);
    }

    @media (min-width: 1280px) {
      grid-template-columns: repeat(3, 1fr);
    }
  }

  &__cell--full {
    grid-column: 1 / -1;
  }

  &__files {
    margin-top: 1.5rem;
  }

  &__divider {
    border-block-end: 1px solid var(--color-thd-gray);
    margin-block: 1.5rem;
  }

  &__actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  &__btn-cancel {
    min-width: 9rem;
  }

  &__btn-submit {
    min-width: 12rem;
  }
}
</style>
