<template>
  <div class="session-form">
    <BoxedIconTitleBlock
      class="session-form__heading"
      :title="isEditMode ? 'ویرایش جلسه' : 'افزودن جلسه جدید'"
      desc="در این قسمت می‌توانید جلسه خود را مدیریت کنید."
    >
      <template #icon>
        <SvgIcon name="book" :size="24" color="var(--color-primary)" />
      </template>
    </BoxedIconTitleBlock>

    <form class="session-form__form" @submit.prevent="onSubmit">
      <LineTitleBlock title="اطلاعات جلسه" title-en="Session Details" />

      <!-- row 1 — title / startTime / endTime -->
      <div class="session-form__row session-form__row--three">
        <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>
        <DatePickerField
          v-model="form.startTime"
          name="startTime"
          label="زمان شروع"
          type="datetime"
          :error="errors.startTime"
          @blur="validateAt('startTime', form.startTime)"
        />
        <DatePickerField
          v-model="form.endTime"
          name="endTime"
          label="زمان پایان"
          type="datetime"
          :error="errors.endTime"
        />
      </div>

      <!-- row 2 — durationMinutes / courseId / contentType -->
      <div class="session-form__row session-form__row--three">
        <TextField
          v-model="form.durationMinutes"
          name="durationMinutes"
          label="مدت زمان جلسه (دقیقه)"
          inputmode="numeric"
          :convert-digits="true"
          :error="errors.durationMinutes"
          @blur="validateAt('durationMinutes', form.durationMinutes)"
        />
        <SelectField
          v-model="form.courseId"
          name="courseId"
          label="دوره"
          :options="courseOptions"
          option-label="title"
          option-value="id"
          :searchable="true"
          :on-search="searchCourses"
          :error="errors.courseId"
        />
        <SelectField
          v-model="form.contentType"
          name="contentType"
          label="محتوای جلسه"
          :options="contentTypeOptions"
          option-label="label"
          option-value="value"
          :error="errors.contentType"
          @change="onContentTypeChange"
        />
      </div>

      <!-- row 3 — sessionType / meetingLink -->
      <div class="session-form__row session-form__row--two">
        <SelectField
          v-model="form.sessionType"
          name="sessionType"
          label="نوع جلسه"
          :options="sessionTypeOptions"
          option-label="label"
          option-value="value"
          :error="errors.sessionType"
          @change="onSessionTypeChange"
        />
        <TextField
          v-model="form.meetingLink"
          name="meetingLink"
          label="لینک جلسه"
          :disabled="form.sessionType !== 'online'"
          :error="errors.meetingLink"
          @blur="validateAt('meetingLink', form.meetingLink)"
        />
      </div>

      <!-- row 4 — description -->
      <div class="session-form__row">
        <TextareaField
          v-model="form.description"
          name="description"
          label="توضیحات جلسه"
          :row="5"
        />
      </div>

      <!-- row 5 — content uploader -->
      <div class="session-form__row">
        <label class="session-form__uploader-label">محتوای جلسه</label>
        <FileUploader
          v-model="contentFiles"
          :accept="contentAccept"
          :multiple="false"
          :max-files="1"
          :disabled="!form.contentType"
          @select="onContentSelect"
          @remove="onContentRemove"
          @error="onContentError"
        />
      </div>

      <!-- row 6 — preview of uploaded content -->
      <div v-if="contentPreviewUrl" class="session-form__row session-form__preview">
        <video
          v-if="form.contentType === 'video'"
          :src="contentPreviewUrl"
          controls
          class="session-form__media"
        />
        <audio
          v-else-if="form.contentType === 'voice'"
          :src="contentPreviewUrl"
          controls
          class="session-form__media"
        />
        <a
          v-else
          :href="contentPreviewUrl"
          target="_blank"
          rel="noopener noreferrer"
          class="session-form__file-link"
        >
          <SvgIcon name="file" :size="18" color="var(--color-primary)" />
          <span>{{ contentFiles[0]?.name || 'فایل پیوست' }}</span>
        </a>
      </div>

      <div class="session-form__divider" />

      <div class="session-form__actions">
        <BaseButton
          variant="transparent"
          text="منصرف شدم"
          custom-class="session-form__btn-cancel"
          @click="onCancel"
        >
          <template #prependIcon>
            <SvgIcon name="caret-right" :size="14" color="var(--color-sec-gray)" />
          </template>
        </BaseButton>
        <BaseButton
          type="submit"
          :text="isEditMode ? 'ذخیره تغییرات' : 'تایید اطلاعات'"
          :loading="submitting"
          custom-class="session-form__btn-submit"
        >
          <template #appendIcon>
            <SvgIcon name="arrow-left" :size="20" color="#fff" />
          </template>
        </BaseButton>
      </div>
    </form>
  </div>
</template>

<script setup>
import { toast } from 'vue3-toastify'
import useYup from '@/composables/useYup'
import { computed, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import useDebounce from '@/composables/useDebounce'
import { useQueryClient } from '@tanstack/vue-query'
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 LineTitleBlock from '@/components/LineTitleBlock.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 { sessionSchema } from '@/features/admin/sessions/schema'
import DatePickerField from '@/components/form/DatePickerField.vue'
import { useAdminCoursesListQuery } from '@/services/query/admin-courses'
import BoxedIconTitleBlock from '@/components/blocks/BoxedIconTitleBlock.vue'
import { COURSE_CONTENT_TYPE, COURSE_CONTENT_TYPE_ACCEPT, SESSION_TYPE } from '@/enums'
import {
  adminSessionsKeys,
  useAddAdminSessionMutation,
  useAdminSessionQuery,
  useUpdateAdminSessionMutation,
} from '@/services/query/admin-sessions'

const route = useRoute()
const router = useRouter()
const queryClient = useQueryClient()

const sessionId = computed(() => (route.params.id ? Number(route.params.id) : null))
const isEditMode = computed(() => !!sessionId.value)

// نوع جلسه: only the two delivery modes — backend `type` collapses to online/offline.
const sessionTypeOptions = [
  { value: 'in_person', label: SESSION_TYPE.in_person },
  { value: 'online', label: SESSION_TYPE.online },
]

// محتوای جلسه: voice / video / text — reuses the course content-type enum.
const contentTypeOptions = Object.entries(COURSE_CONTENT_TYPE).map(([value, label]) => ({
  value,
  label,
}))

const form = ref({
  title: '',
  startTime: '',
  endTime: '',
  durationMinutes: '',
  courseId: '',
  contentType: '',
  sessionType: '',
  meetingLink: '',
  description: '',
  contentMediaId: null,
})

const contentFiles = ref([])

const contentAccept = computed(() => COURSE_CONTENT_TYPE_ACCEPT[form.value.contentType] || '*')
const contentPreviewUrl = computed(() => contentFiles.value[0]?.url || '')

const { validate, validateAt, errors } = useYup(sessionSchema)

const courseSearch = ref('')
const courseFilters = computed(() => ({ title: courseSearch.value }))
const coursePagination = ref({ page: 1, perPage: 30 })
const { data: coursesResponse } = useAdminCoursesListQuery(courseFilters, coursePagination)
const selectedCourse = ref(null)
const courseOptions = computed(() => {
  const base = coursesResponse.value?.data ?? []
  if (selectedCourse.value && !base.some((c) => c.id === selectedCourse.value.id)) {
    return [...base, selectedCourse.value]
  }
  return base
})

const searchCourses = useDebounce((q) => {
  courseSearch.value = q || ''
}, 400)

const onContentTypeChange = () => {
  contentFiles.value = []
  form.value.contentMediaId = null
}

const onSessionTypeChange = () => {
  if (form.value.sessionType !== 'online') form.value.meetingLink = ''
}

const { data: existingSession } = useAdminSessionQuery(sessionId, {
  enabled: () => !!sessionId.value,
})

watch(existingSession, (session) => {
  if (!session) return
  if (session.course) selectedCourse.value = session.course
  form.value = {
    title: session.title || '',
    startTime: session.startsAt || session.sessionConfig?.startTime || '',
    endTime: session.endsAt || session.sessionConfig?.endTime || '',
    durationMinutes: session.durationMinutes ?? '',
    courseId: session.course?.id || session.courseId || '',
    contentType: session.contentType || '',
    sessionType: session.sessionType || '',
    meetingLink: session.link || session.sessionConfig?.meetingLink || '',
    description: session.description || '',
    contentMediaId: session.contentMediaId || null,
  }
  if (session.contentMedia) {
    contentFiles.value = [
      {
        id: session.contentMedia.id,
        name: session.contentMedia.fileName || session.contentMedia.name || 'file',
        size: session.contentMedia.fileSize ?? 0,
        url: session.contentMedia.url,
      },
    ]
  }
})

const uploadMutation = useUploadMediaMutation()

const purposeForContentType = (contentType) => {
  if (contentType === 'video') return 'video'
  if (contentType === 'voice') return 'voice'
  return 'attachment'
}

const onContentSelect = async (files) => {
  const file = files?.[0]
  if (!file) return
  try {
    const formData = objectToFormData({
      file,
      purpose: purposeForContentType(form.value.contentType),
      context: 'session',
    })
    const response = await uploadMutation.mutateAsync(formData)
    const payload = response?.data ?? response
    const id = payload?.id ?? payload?.uploadId
    contentFiles.value = [{ id, name: file.name, size: file.size, url: payload?.url }]
    form.value.contentMediaId = id
  } catch {
    contentFiles.value = []
  }
}

const onContentRemove = () => {
  contentFiles.value = []
  form.value.contentMediaId = null
}

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

const buildPayload = (values) => {
  const payload = {
    title: values.title,
    startTime: values.startTime,
    endTime: values.endTime,
    durationMinutes: values.durationMinutes,
    courseId: values.courseId,
    contentType: values.contentType,
    sessionType: values.sessionType,
    meetingLink: values.sessionType === 'online' ? values.meetingLink : undefined,
    description: values.description,
    contentMediaId: values.contentMediaId,
  }
  Object.keys(payload).forEach((key) => {
    if (payload[key] === undefined || payload[key] === '' || payload[key] === null) {
      delete payload[key]
    }
  })
  return payload
}

const addMutation = useAddAdminSessionMutation()
const updateMutation = useUpdateAdminSessionMutation()

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

const onSubmit = async () => {
  const { isValid } = await validate(form.value)
  if (!isValid) return
  const payload = buildPayload(form.value)
  if (isEditMode.value) {
    await updateMutation.mutateAsync({ id: sessionId.value, payload })
  } else {
    await addMutation.mutateAsync(payload)
  }
  await queryClient.invalidateQueries({ queryKey: adminSessionsKeys.all })
  router.push({ name: 'admin-sessions' })
}

const onCancel = () => router.push({ name: 'admin-sessions' })
</script>

<style lang="scss" scoped>
.session-form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;

  &__heading {
    margin-bottom: 0.75rem;
  }

  &__form {
    background: rgba(255, 255, 255, 60%);
    padding: 1rem;
    border-radius: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
  }

  &__row {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.5rem;

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

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

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

  &__uploader-label {
    display: block;
    margin-bottom: 0.5rem;
    font-family: var(--font-family-fa);
    font-weight: 300;
    line-height: 1.5rem;
    font-size: 0.875rem;
    color: var(--color-prim-gray);
  }

  &__preview {
    place-items: center center;
  }

  &__media {
    max-width: 100%;
    border-radius: 0.75rem;
    background: #000;
  }

  &__file-link {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--color-primary);
    text-decoration: none;
    font-family: var(--font-family-fa);
    font-size: 0.875rem;
    padding: 0.5rem 0;

    &:hover {
      text-decoration: underline;
    }
  }

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

  &__actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.625rem;
  }

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

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