<script lang="ts" setup>
import { computed } from 'vue'
import { useRouter } from 'vue-router'
import dayjs from 'dayjs'
import * as select from '@zag-js/select'
import { Badge } from '@/components/ui/badge'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import {
  MenuRoot,
  MenuTrigger,
  MenuPositioner,
  MenuContent,
  MenuItem,
} from '@/components/ui/menu'
import {
  PaginationContext,
  PaginationRoot,
  PaginationItem,
  PaginationPrevTrigger,
  PaginationNextTrigger,
  PaginationEllipsis,
} from '@/components/ui/pagination'
import {
  SelectRoot,
  SelectControl,
  SelectTrigger,
  SelectValueText,
  SelectContent,
  SelectItemGroup,
  SelectItem,
  SelectItemText,
} from '@/components/ui/select'
import { AlertRoot, AlertTitle, AlertDescription } from '@/components/ui/alert'
import { usePermissions } from '@/composables/usePermissions'
import { useActivityList } from '../composables/useActivityList'
import type { ActivityListItem } from '../types/activity.types'

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

const PER_PAGE_OPTIONS: SelectOption[] = [
  { label: '10', value: '10' },
  { label: '25', value: '25' },
  { label: '35', value: '35' },
  { label: '50', value: '50' },
]

const SORT_OPTIONS: SelectOption[] = [
  { label: 'Tarikh Mula (Terbaharu)', value: 'start_datetime:desc' },
  { label: 'Tarikh Mula (Terlama)', value: 'start_datetime:asc' },
  { label: 'Tajuk (A-Z)', value: 'title:asc' },
  { label: 'Tajuk (Z-A)', value: 'title:desc' },
  { label: 'Dicipta (Terbaharu)', value: 'created_at:desc' },
]

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] : options[0] ? [options[0].label] : []
}

const perPageCollection = createSelectCollection(PER_PAGE_OPTIONS)
const sortCollection = createSelectCollection(SORT_OPTIONS)

const { hasPermission } = usePermissions()
const canCreate = computed(() => hasPermission('tambah aktiviti'))
const canEdit = computed(() => hasPermission('kemaskini aktiviti'))
const router = useRouter()

const {
  activities,
  loading,
  error,
  search,
  page,
  itemsPerPage,
  sortBy,
  sortOrder,
  pagination,
} = useActivityList()

const perPageInitial = computed(() => valueToLabel(PER_PAGE_OPTIONS, String(itemsPerPage.value)))
const sortInitial = computed(() => valueToLabel(SORT_OPTIONS, `${sortBy.value}:${sortOrder.value}`))

function handlePageChange(details: { page: number }) {
  page.value = details.page
}

function setPerPageValue(details: { value: string[] }) {
  const next = Number(labelToValue(PER_PAGE_OPTIONS, details.value[0]))
  if (!Number.isNaN(next)) {
    itemsPerPage.value = next
  }
}

function setSortValue(details: { value: string[] }) {
  const raw = labelToValue(SORT_OPTIONS, details.value[0])
  const [field, order] = raw.split(':')
  if (field) sortBy.value = field
  if (order === 'asc' || order === 'desc') sortOrder.value = order
}

function formatDateTime(value: string | null): string {
  if (!value) return '-'
  return dayjs(value).format('DD MMM YYYY, HH:mm')
}

function coverImageUrl(activity: ActivityListItem): string | null {
  return activity.cover_image?.url ?? null
}

function truncateText(value: string | null, length = 140): string {
  if (!value) return ''
  return value.length > length ? `${value.slice(0, length).trim()}...` : value
}

function goToActivity(id: string) {
  router.push({ name: 'view-activity', params: { id } })
}

function goToEdit(id: string) {
  router.push({ name: 'edit-activity', params: { id } })
}

function goToCreate() {
  router.push({ name: 'create-activity' })
}
</script>

<template>
  <div>
    <div class="flex flex-col items-center sm:flex-row">
      <div class="mr-auto">
        <h2 class="text-lg font-medium">Senarai Aktiviti</h2>
        <p class="mt-1 text-sm opacity-70">Urus dan lihat aktiviti koperasi.</p>
      </div>
      <div class="mt-4 flex w-full sm:mt-0 sm:w-auto">
        <Button
          v-if="canCreate"
          look="outline"
          class="mr-2 shadow-sm"
          variant="primary"
          @click="goToCreate"
        >
          Tambah Aktiviti
        </Button>
      </div>
    </div>

    <AlertRoot v-if="error" class="mt-6" variant="danger">
      <AlertTitle>Ralat</AlertTitle>
      <AlertDescription>{{ error }}</AlertDescription>
    </AlertRoot>

    <div class="mt-5 grid grid-cols-12 gap-x-6 gap-y-8">
      <div class="col-span-12 flex flex-wrap items-center gap-3">
        <div class="relative w-full max-w-md flex-1">
          <Input v-model="search" class="pr-10" type="search" placeholder="Cari aktiviti..." />
          <Lucide class="absolute inset-y-0 right-0 my-auto mr-3 size-4 opacity-70" icon="Search" />
        </div>

        <SelectRoot
          :key="sortInitial[0]"
          class="w-full sm:w-56"
          :collection="sortCollection"
          :default-value="sortInitial"
          @value-change="setSortValue"
        >
          <SelectControl>
            <SelectTrigger>
              <SelectValueText placeholder="Susunan" />
            </SelectTrigger>
          </SelectControl>
          <SelectContent>
            <SelectItemGroup>
              <SelectItem
                v-for="item in sortCollection.items"
                :key="item.label"
                :item="item"
              >
                <SelectItemText>{{ item.label }}</SelectItemText>
              </SelectItem>
            </SelectItemGroup>
          </SelectContent>
        </SelectRoot>
      </div>

      <template v-if="loading">
        <Box
          v-for="index in 6"
          :key="index"
          class="col-span-12 animate-pulse p-0 md:col-span-6 xl:col-span-4"
        >
          <div class="h-64 bg-foreground/5" />
        </Box>
      </template>

      <template v-else>
        <Box
          v-for="activity in activities"
          :key="activity.id"
          class="col-span-12 cursor-pointer p-0 md:col-span-6 xl:col-span-4"
          @click="goToActivity(activity.id)"
        >
          <div class="flex items-center border-b border-foreground/15 px-5 py-4">
            <div
              class="flex size-10 shrink-0 items-center justify-center rounded-full bg-primary/10 text-primary"
            >
              <Lucide class="size-5" icon="CalendarDays" />
            </div>
            <div class="ml-3 mr-auto min-w-0">
              <div class="truncate font-medium">
                {{ activity.activity_type?.name ?? 'Aktiviti' }}
              </div>
              <div class="mt-0.5 flex truncate text-xs opacity-70">
                <span v-if="activity.reference_number" class="text-primary inline-block truncate">
                  {{ activity.reference_number }}
                </span>
                <span v-if="activity.reference_number" class="mx-1">•</span>
                <span>{{ formatDateTime(activity.start_datetime) }}</span>
              </div>
            </div>
            <Badge look="outline" :variant="activity.is_active ? 'success' : 'outline'">
              {{ activity.is_active ? 'Aktif' : 'Tidak Aktif' }}
            </Badge>
          </div>

          <div class="p-5">
            <div class="image-fit h-40 overflow-hidden rounded-md bg-foreground/5 2xl:h-56">
              <img
                v-if="coverImageUrl(activity)"
                class="size-full object-cover"
                :src="coverImageUrl(activity)!"
                :alt="activity.title"
              />
              <div
                v-else
                class="flex size-full flex-col items-center justify-center gap-2 text-muted-foreground"
              >
                <Lucide class="size-8 opacity-40" icon="Image" />
                <span class="text-xs opacity-70">Tiada imej</span>
              </div>
            </div>

            <div class="mt-5 block text-base font-medium">
              {{ activity.title }}
            </div>
            <div v-if="activity.description" class="mt-2 line-clamp-3 text-foreground/70">
              {{ truncateText(activity.description) }}
            </div>
            <div class="mt-3 space-y-1 text-xs opacity-70">
              <div v-if="activity.organizer" class="flex items-center gap-2">
                <Lucide class="size-3.5 shrink-0" icon="Users" />
                <span class="truncate">{{ activity.organizer }}</span>
              </div>
              <div v-if="activity.location" class="flex items-center gap-2">
                <Lucide class="size-3.5 shrink-0" icon="MapPin" />
                <span class="truncate">{{ activity.location }}</span>
              </div>
            </div>
          </div>

          <div class="flex items-center border-t border-foreground/15 px-5 py-3">
            <div class="mr-2 flex items-center gap-1 text-xs opacity-70">
              <Lucide class="size-3.5" icon="Images" />
              <span>{{ activity.gallery_image_count }} imej</span>
            </div>
            <div class="flex items-center gap-1 text-xs opacity-70">
              <Lucide class="size-3.5" icon="Paperclip" />
              <span>{{ activity.documents_count }} dokumen</span>
            </div>

            <div class="ml-auto w-auto" @click.stop>
            <MenuRoot>
              <MenuTrigger as-child>
                <Button variant="ghost" size="sm" class="size-8 p-0">
                  <Lucide class="size-5 opacity-70" icon="MoreVertical" />
                </Button>
              </MenuTrigger>
              <MenuPositioner>
                <MenuContent class="w-40">
                  <MenuItem value="view" @click="goToActivity(activity.id)">
                    <Lucide class="mr-2 size-4" icon="Eye" /> Lihat
                  </MenuItem>
                  <MenuItem
                    v-if="canEdit"
                    value="edit"
                    @click="goToEdit(activity.id)"
                  >
                    <Lucide class="mr-2 size-4" icon="Edit" /> Edit
                  </MenuItem>
                </MenuContent>
              </MenuPositioner>
            </MenuRoot>
            </div>
          </div>
        </Box>
      </template>

      <div v-if="!loading && !activities.length" class="col-span-12">
        <Box class="p-6 text-center opacity-70">Tiada aktiviti ditemui.</Box>
      </div>

      <div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
        <PaginationRoot
          :count="pagination.total"
          :page="page"
          :page-size="itemsPerPage"
          :sibling-count="1"
          :on-page-change="handlePageChange"
          class="w-full sm:mr-auto sm:w-auto"
        >
          <PaginationPrevTrigger>
            <Lucide class="size-4" icon="ChevronLeft" />
          </PaginationPrevTrigger>
          <PaginationContext v-slot="{ pagination: paginationApi }">
            <template v-for="(pageItem, index) in paginationApi?.pages" :key="index">
              <PaginationItem v-if="pageItem.type === 'page'" v-bind="{ ...pageItem }">
                {{ pageItem.value }}
              </PaginationItem>
              <PaginationEllipsis v-else :index="index" />
            </template>
          </PaginationContext>
          <PaginationNextTrigger>
            <Lucide class="size-4" icon="ChevronRight" />
          </PaginationNextTrigger>
        </PaginationRoot>

        <SelectRoot
          :key="perPageInitial[0]"
          class="mt-3 w-20 sm:mt-0"
          :collection="perPageCollection"
          :default-value="perPageInitial"
          @value-change="setPerPageValue"
        >
          <SelectControl>
            <SelectTrigger>
              <SelectValueText />
            </SelectTrigger>
          </SelectControl>
          <SelectContent>
            <SelectItemGroup>
              <SelectItem
                v-for="item in perPageCollection.items"
                :key="item.label"
                :item="item"
              >
                <SelectItemText>{{ item.label }}</SelectItemText>
              </SelectItem>
            </SelectItemGroup>
          </SelectContent>
        </SelectRoot>
      </div>
    </div>
  </div>
</template>
