<script lang="ts" setup>
import { onUnmounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
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 ActivityTypeSelectField from '../components/ActivityTypeSelectField.vue'
import { createActivity } from '../services/activity.service'

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

type StagedGalleryFile = {
  id: string
  file: File
  previewUrl: string
}

type StagedDocumentFile = {
  id: string
  file: File
}

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 ?? ''
}

const router = useRouter()

const saving = ref(false)
const error = ref<string | null>(null)
const successMessage = ref<string | null>(null)

const galleryFiles = ref<StagedGalleryFile[]>([])
const documentFiles = ref<StagedDocumentFile[]>([])

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[]>(['Aktif'])

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

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

  if (!files.length) return

  galleryFiles.value.push(
    ...files.map((file) => ({
      id: crypto.randomUUID(),
      file,
      previewUrl: URL.createObjectURL(file),
    })),
  )
}

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

  if (!files.length) return

  documentFiles.value.push(
    ...files.map((file) => ({
      id: crypto.randomUUID(),
      file,
    })),
  )
}

function removeGalleryFile(id: string) {
  const item = galleryFiles.value.find((file) => file.id === id)
  if (item) {
    URL.revokeObjectURL(item.previewUrl)
  }
  galleryFiles.value = galleryFiles.value.filter((file) => file.id !== id)
}

function removeDocumentFile(id: string) {
  documentFiles.value = documentFiles.value.filter((file) => file.id !== id)
}

function revokeGalleryPreviewUrls() {
  galleryFiles.value.forEach((file) => URL.revokeObjectURL(file.previewUrl))
}

async function handleSubmit() {
  if (!form.activity_type_id) {
    error.value = 'Sila pilih jenis aktiviti.'
    return
  }

  saving.value = true
  error.value = null
  successMessage.value = null

  try {
    const activity = await createActivity(
      {
        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,
      },
      {
        gallery: galleryFiles.value.map((item) => item.file),
        documents: documentFiles.value.map((item) => item.file),
      },
    )

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

function goBack() {
  router.push({ name: 'list-activities' })
}

onUnmounted(() => {
  revokeGalleryPreviewUrls()
})
</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">Daftar 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>

    <form 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"
            auto-select-first
          />

          <Field>
            <FieldLabel>Status</FieldLabel>
            <SelectRoot
              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">
          Pilihan. Tambah imej beberapa kali sebelum mendaftar. Imej dimuat naik semasa pendaftaran.
        </p>

        <div
          v-if="galleryFiles.length"
          class="mt-4 grid grid-cols-2 gap-3 sm:grid-cols-4"
        >
          <div
            v-for="image in galleryFiles"
            :key="image.id"
            class="relative overflow-hidden rounded-lg border border-foreground/10"
          >
            <img
              :src="image.previewUrl"
              :alt="image.file.name"
              class="aspect-square w-full object-cover"
            />
            <Button
              type="button"
              variant="danger"
              size="sm"
              class="absolute top-2 right-2"
              :disabled="saving"
              @click="removeGalleryFile(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="saving"
            @change="onGalleryFilesChange"
          />
        </Field>
      </Box>

      <Box class="p-5 sm:p-6">
        <div class="font-medium">Dokumen Lampiran</div>
        <p class="mt-1 text-sm opacity-70">
          Pilihan. Tambah dokumen beberapa kali sebelum mendaftar. Dokumen dimuat naik semasa pendaftaran.
        </p>

        <div v-if="documentFiles.length" class="mt-4 space-y-2">
          <div
            v-for="document in documentFiles"
            :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.file.name }}</div>
              <div class="text-xs opacity-70">{{ document.file.type || 'Dokumen' }}</div>
            </div>
            <Button
              type="button"
              variant="danger"
              look="outline"
              size="sm"
              :disabled="saving"
              @click="removeDocumentFile(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="saving"
            @change="onDocumentFilesChange"
          />
        </Field>
      </Box>

      <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 || !form.activity_type_id">
          {{ saving ? 'Menyimpan...' : 'Daftar Aktiviti' }}
        </Button>
      </div>
    </form>
  </div>
</template>
