<script lang="ts" setup>
import { computed, onMounted, reactive, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import dayjs from 'dayjs'
import * as select from '@zag-js/select'
import { CircleAlert, CircleCheck, Trash } from '@lucide/vue'
import {
  AlertRoot,
  AlertTitle,
  AlertDescription,
  AlertCloseTrigger,
} from '@/components/ui/alert'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import { Field, FieldLabel } from '@/components/ui/field'
import { Input } from '@/components/ui/input'
import { input as inputStyles } from '@/components/ui/styles/input.styles'
import { Textarea } from '@/components/ui/textarea'
import { cn } from '@mykopkb/core/utils/cn'
import {
  SelectRoot,
  SelectControl,
  SelectTrigger,
  SelectValueText,
  SelectContent,
  SelectItemGroup,
  SelectItem,
  SelectItemText,
} from '@/components/ui/select'
import { getApiErrorMessage } from '@/core/utils/getApiErrorMessage'
import ActivityReportsSection from '../components/ActivityReportsSection.vue'
import ActivityTypeSelectField from '../components/ActivityTypeSelectField.vue'
import {
  deleteActivityDocument,
  deleteActivityGalleryImage,
  getActivity,
  updateActivity,
  uploadActivityDocument,
  uploadActivityGalleryImage,
} from '../services/activity.service'
import type { ActivityDetail } from '../types/activity.types'

type SelectOption = { label: string; value: string }

const ACTIVE_STATUS_OPTIONS: SelectOption[] = [
  { label: 'Aktif', value: '1' },
  { label: 'Tidak Aktif', value: '0' },
]

function createSelectCollection(options: SelectOption[]) {
  return select.collection({
    items: options,
    itemToValue: (item) => item.label,
  })
}

function labelToValue(options: SelectOption[], label: string | undefined): string {
  if (!label) return options[0]?.value ?? ''
  return options.find((option) => option.label === label)?.value ?? ''
}

function valueToLabel(options: SelectOption[], value: string): string[] {
  const option = options.find((item) => item.value === value)
  return option ? [option.label] : []
}

function toDatetimeLocalValue(value: string | null): string {
  if (!value) return ''
  return dayjs(value).format('YYYY-MM-DDTHH:mm')
}

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

const activityId = computed(() => String(route.params.id ?? ''))

const loading = ref(false)
const saving = ref(false)
const uploadingGallery = ref(false)
const uploadingDocuments = ref(false)
const deletingAssetId = ref<string | null>(null)
const error = ref<string | null>(null)
const successMessage = ref<string | null>(null)

const activity = ref<ActivityDetail | null>(null)

const form = reactive({
  activity_type_id: '',
  title: '',
  reference_number: '',
  description: '',
  start_datetime: '',
  end_datetime: '',
  organizer: '',
  location: '',
  is_active: true,
})

const activeStatusCollection = createSelectCollection(ACTIVE_STATUS_OPTIONS)

const activeStatusInitial = ref<string[]>([])

function setActiveStatusValue(details: { value: string[] }) {
  form.is_active = labelToValue(ACTIVE_STATUS_OPTIONS, details.value[0]) === '1'
}

function syncFormFromActivity(data: ActivityDetail) {
  form.activity_type_id = data.activity_type_id
  form.title = data.title
  form.reference_number = data.reference_number ?? ''
  form.description = data.description ?? ''
  form.start_datetime = toDatetimeLocalValue(data.start_datetime)
  form.end_datetime = toDatetimeLocalValue(data.end_datetime)
  form.organizer = data.organizer ?? ''
  form.location = data.location ?? ''
  form.is_active = data.is_active

  activeStatusInitial.value = valueToLabel(
    ACTIVE_STATUS_OPTIONS,
    data.is_active ? '1' : '0',
  )
}

async function loadActivity() {
  const data = await getActivity(activityId.value)
  activity.value = data
  syncFormFromActivity(data)
}

async function fetchData() {
  loading.value = true
  error.value = null
  successMessage.value = null

  try {
    await loadActivity()
  } catch (err) {
    error.value = getApiErrorMessage(err, 'Gagal memuatkan maklumat aktiviti.')
  } finally {
    loading.value = false
  }
}

function showTransientSuccess(message: string) {
  successMessage.value = message
  setTimeout(() => {
    if (successMessage.value === message) {
      successMessage.value = null
    }
  }, 2500)
}

async function onGalleryFilesChange(event: Event) {
  const input = event.target as HTMLInputElement
  const files = input.files ? Array.from(input.files) : []
  input.value = ''

  if (!files.length || uploadingGallery.value) return

  uploadingGallery.value = true
  error.value = null

  try {
    for (const file of files) {
      const data = await uploadActivityGalleryImage(activityId.value, file)
      activity.value = data
    }

    showTransientSuccess(
      files.length === 1
        ? 'Imej galeri berjaya dimuat naik.'
        : `${files.length} imej galeri berjaya dimuat naik.`,
    )
  } catch (err) {
    error.value = getApiErrorMessage(err, 'Gagal memuat naik imej galeri.')
  } finally {
    uploadingGallery.value = false
  }
}

async function onDocumentFilesChange(event: Event) {
  const input = event.target as HTMLInputElement
  const files = input.files ? Array.from(input.files) : []
  input.value = ''

  if (!files.length || uploadingDocuments.value) return

  uploadingDocuments.value = true
  error.value = null

  try {
    for (const file of files) {
      const data = await uploadActivityDocument(activityId.value, file)
      activity.value = data
    }

    showTransientSuccess(
      files.length === 1
        ? 'Dokumen berjaya dimuat naik.'
        : `${files.length} dokumen berjaya dimuat naik.`,
    )
  } catch (err) {
    error.value = getApiErrorMessage(err, 'Gagal memuat naik dokumen.')
  } finally {
    uploadingDocuments.value = false
  }
}

async function handleSubmit() {
  saving.value = true
  error.value = null
  successMessage.value = null

  try {
    await updateActivity(activityId.value, {
      activity_type_id: form.activity_type_id,
      title: form.title.trim(),
      reference_number: form.reference_number.trim() || null,
      description: form.description.trim() || null,
      start_datetime: form.start_datetime || null,
      end_datetime: form.end_datetime || null,
      organizer: form.organizer.trim() || null,
      location: form.location.trim() || null,
      is_active: form.is_active,
    })

    successMessage.value = 'Aktiviti berjaya dikemaskini.'
    setTimeout(() => {
      router.push({ name: 'view-activity', params: { id: activityId.value } })
    }, 400)
  } catch (err) {
    error.value = getApiErrorMessage(err, 'Gagal mengemaskini aktiviti.')
  } finally {
    saving.value = false
  }
}

async function handleDeleteGalleryImage(imageId: string) {
  if (deletingAssetId.value || uploadingGallery.value) return

  deletingAssetId.value = imageId
  error.value = null

  try {
    const data = await deleteActivityGalleryImage(activityId.value, imageId)
    activity.value = data
    syncFormFromActivity(data)
    showTransientSuccess('Imej galeri berjaya dipadam.')
  } catch (err) {
    error.value = getApiErrorMessage(err, 'Gagal memadam imej galeri.')
  } finally {
    deletingAssetId.value = null
  }
}

async function handleDeleteDocument(documentId: string) {
  if (deletingAssetId.value || uploadingDocuments.value) return

  deletingAssetId.value = documentId
  error.value = null

  try {
    const data = await deleteActivityDocument(activityId.value, documentId)
    activity.value = data
    syncFormFromActivity(data)
    showTransientSuccess('Dokumen berjaya dipadam.')
  } catch (err) {
    error.value = getApiErrorMessage(err, 'Gagal memadam dokumen.')
  } finally {
    deletingAssetId.value = null
  }
}

function goBack() {
  router.push({ name: 'view-activity', params: { id: activityId.value } })
}

onMounted(() => {
  fetchData()
})
</script>

<template>
  <div class="w-full space-y-6">
    <div class="flex flex-wrap items-center gap-3">
      <h2 class="mr-auto text-lg font-medium">Kemaskini Aktiviti</h2>
      <Button look="outline" variant="secondary" type="button" @click="goBack">
        Kembali
      </Button>
    </div>

    <AlertRoot v-if="successMessage" variant="success">
      <CircleCheck />
      <AlertTitle>Berjaya</AlertTitle>
      <AlertDescription>{{ successMessage }}</AlertDescription>
      <AlertCloseTrigger @click="successMessage = null" />
    </AlertRoot>

    <AlertRoot v-if="error" variant="danger">
      <CircleAlert />
      <AlertTitle>Ralat</AlertTitle>
      <AlertDescription>{{ error }}</AlertDescription>
      <AlertCloseTrigger @click="error = null" />
    </AlertRoot>

    <div v-if="loading" class="opacity-70">Memuatkan maklumat aktiviti...</div>

    <form v-else-if="activity" class="space-y-6" @submit.prevent="handleSubmit">
      <Box class="p-5 sm:p-6">
        <div class="grid gap-5 sm:grid-cols-2">
          <Field class="sm:col-span-2">
            <FieldLabel for="activity-title">Tajuk</FieldLabel>
            <Input id="activity-title" v-model="form.title" required :disabled="saving" />
          </Field>

          <ActivityTypeSelectField v-model="form.activity_type_id" :disabled="saving" />

          <Field>
            <FieldLabel>Status</FieldLabel>
            <SelectRoot
              :key="activeStatusInitial[0]"
              class="w-full"
              :collection="activeStatusCollection"
              :default-value="activeStatusInitial"
              :disabled="saving"
              @value-change="setActiveStatusValue"
            >
              <SelectControl>
                <SelectTrigger>
                  <SelectValueText placeholder="Pilih status" />
                </SelectTrigger>
              </SelectControl>
              <SelectContent>
                <SelectItemGroup>
                  <SelectItem
                    v-for="item in activeStatusCollection.items"
                    :key="item.label"
                    :item="item"
                  >
                    <SelectItemText>{{ item.label }}</SelectItemText>
                  </SelectItem>
                </SelectItemGroup>
              </SelectContent>
            </SelectRoot>
          </Field>

          <Field>
            <FieldLabel for="activity-reference">No. Rujukan</FieldLabel>
            <Input
              id="activity-reference"
              v-model="form.reference_number"
              :disabled="saving"
            />
          </Field>

          <Field>
            <FieldLabel for="activity-organizer">Penganjur</FieldLabel>
            <Input id="activity-organizer" v-model="form.organizer" :disabled="saving" />
          </Field>

          <Field class="sm:col-span-2">
            <FieldLabel for="activity-location">Lokasi</FieldLabel>
            <Input id="activity-location" v-model="form.location" :disabled="saving" />
          </Field>

          <Field>
            <FieldLabel for="activity-start">Tarikh Mula</FieldLabel>
            <Input
              id="activity-start"
              v-model="form.start_datetime"
              type="datetime-local"
              :disabled="saving"
            />
          </Field>

          <Field>
            <FieldLabel for="activity-end">Tarikh Tamat</FieldLabel>
            <Input
              id="activity-end"
              v-model="form.end_datetime"
              type="datetime-local"
              :disabled="saving"
            />
          </Field>

          <Field class="sm:col-span-2">
            <FieldLabel for="activity-description">Penerangan</FieldLabel>
            <Textarea
              id="activity-description"
              v-model="form.description"
              rows="4"
              :disabled="saving"
            />
          </Field>
        </div>
      </Box>

      <Box class="p-5 sm:p-6">
        <div class="font-medium">Galeri Foto</div>
        <p class="mt-1 text-sm opacity-70">
          Imej dimuat naik serta-merta apabila dipilih. Padam imej tanpa perlu simpan borang.
        </p>

        <div
          v-if="activity.gallery_images.length"
          class="mt-4 grid grid-cols-2 gap-3 sm:grid-cols-4"
        >
          <div
            v-for="image in activity.gallery_images"
            :key="image.id"
            class="relative overflow-hidden rounded-lg border border-foreground/10"
          >
            <img :src="image.url" :alt="image.name" class="aspect-square w-full object-cover" />
            <Button
              type="button"
              variant="danger"
              size="sm"
              class="absolute top-2 right-2"
              :disabled="deletingAssetId === image.id || uploadingGallery || saving"
              @click="handleDeleteGalleryImage(image.id)"
            >
              <Trash class="size-4" />
            </Button>
          </div>
        </div>

        <Field class="mt-4">
          <FieldLabel for="activity-gallery-upload">Tambah Imej Galeri</FieldLabel>
          <input
            id="activity-gallery-upload"
            type="file"
            accept="image/jpeg,image/jpg,image/png,image/webp,image/gif"
            multiple
            :class="cn(inputStyles)"
            :disabled="uploadingGallery || saving"
            @change="onGalleryFilesChange"
          />
          <p v-if="uploadingGallery" class="mt-2 text-sm opacity-70">Memuat naik imej...</p>
        </Field>
      </Box>

      <Box class="p-5 sm:p-6">
        <div class="font-medium">Dokumen Lampiran</div>
        <p class="mt-1 text-sm opacity-70">
          Dokumen dimuat naik serta-merta apabila dipilih. Padam dokumen tanpa perlu simpan borang.
        </p>

        <div v-if="activity.documents.length" class="mt-4 space-y-2">
          <div
            v-for="document in activity.documents"
            :key="document.id"
            class="flex items-center justify-between gap-3 rounded-lg border border-foreground/10 p-3"
          >
            <div class="min-w-0">
              <div class="truncate text-sm font-medium">{{ document.name }}</div>
              <div class="text-xs opacity-70">{{ document.mime_type }}</div>
            </div>
            <Button
              type="button"
              variant="danger"
              look="outline"
              size="sm"
              :disabled="deletingAssetId === document.id || uploadingDocuments || saving"
              @click="handleDeleteDocument(document.id)"
            >
              <Trash class="mr-2 size-4" />
              Padam
            </Button>
          </div>
        </div>

        <Field class="mt-4">
          <FieldLabel for="activity-documents-upload">Tambah Dokumen</FieldLabel>
          <input
            id="activity-documents-upload"
            type="file"
            accept=".pdf,.jpg,.jpeg,.png,.doc,.docx,application/pdf,image/*"
            multiple
            :class="cn(inputStyles)"
            :disabled="uploadingDocuments || saving"
            @change="onDocumentFilesChange"
          />
          <p v-if="uploadingDocuments" class="mt-2 text-sm opacity-70">Memuat naik dokumen...</p>
        </Field>
      </Box>

      <ActivityReportsSection
        v-if="activity"
        :activity-id="activity.id"
        :reports="activity.reports ?? []"
        @changed="loadActivity"
      />

      <div class="flex flex-wrap justify-end gap-3">
        <Button type="button" look="outline" variant="secondary" :disabled="saving" @click="goBack">
          Batal
        </Button>
        <Button type="submit" variant="primary" :disabled="saving">
          {{ saving ? 'Menyimpan...' : 'Simpan Perubahan' }}
        </Button>
      </div>
    </form>
  </div>
</template>
