<template>
    <div>
        <div class="sticky top-8 z-20 bg-white pb-4 sm:top-12">
            <div class="flex items-center justify-between gap-3">
                <div class="min-w-0">
                    <NuxtLink
                        to="/portal"
                        class="text-sm text-neutral-400 hover:text-primary-500"
                    >
                        {{ $t('portal.backToProject') }}
                    </NuxtLink>
                    <h1 class="mt-1 text-xl font-bold text-primary-500 sm:text-2xl">{{ projectName }}</h1>
                </div>
                <NuxtLink
                    v-if="isClient"
                    :to="`/portal/projects/${projectId}/new-ticket`"
                    class="shrink-0 rounded-md bg-primary-500 px-3 py-2 text-xs font-semibold text-white hover:bg-secondary-500 sm:px-4 sm:text-sm"
                >
                    <span class="hidden sm:inline">+ {{ $t('portal.newTicket') }}</span>
                    <span class="sm:hidden">+ Ticket</span>
                </NuxtLink>
            </div>
        </div>

        <div v-if="isLoading" class="py-8 text-center text-sm text-neutral-400">
            {{ $t('common.loading') }}
        </div>

        <div v-else-if="tickets.length === 0" class="py-8 text-center text-sm text-neutral-400">
            {{ $t('clientTicket.noTickets') }}
        </div>

        <!-- Kanban board -->
        <div v-else class="mt-4 flex flex-col gap-4 sm:flex-row sm:overflow-x-auto sm:pb-4">
            <div
                v-for="col in columns"
                :key="col.status"
                class="min-w-0 flex-1 sm:min-w-[280px]"
            >
                <div class="mb-3 flex items-center gap-2">
                    <div class="h-2 w-2 rounded-full" :class="col.dotClass" />
                    <h3 class="text-sm font-bold text-neutral-700">{{ col.label }}</h3>
                    <span class="ml-auto rounded-full bg-neutral-100 px-2 py-0.5 text-xs font-semibold text-neutral-500">
                        {{ col.tickets.length }}
                    </span>
                </div>
                <div
                    class="min-h-[60px] space-y-2 rounded-lg border-2 border-transparent p-1 transition-colors"
                    :class="dragOverStatus === col.status ? 'border-primary-300 bg-primary-50/50' : ''"
                    @dragover.prevent="onDragOver(col.status)"
                    @dragleave="onDragLeave"
                    @drop.prevent="onDrop(col.status)"
                >
                    <div
                        v-for="ticket in col.tickets"
                        :key="ticket.id"
                        class="cursor-pointer rounded-lg border border-neutral-200 bg-white p-3 shadow-sm transition hover:shadow-md"
                        :class="isAdmin ? 'cursor-grab active:cursor-grabbing' : ''"
                        :draggable="isAdmin"
                        @dragstart="onDragStart(ticket)"
                        @dragend="onDragEnd"
                        @click="openDetail(ticket)"
                    >
                        <div class="flex items-center gap-2">
                            <span class="text-xs font-bold text-primary-500">CT-{{ String(ticket.number).padStart(3, '0') }}</span>
                            <span
                                class="rounded-full px-2 py-0.5 text-xs font-semibold text-white"
                                :class="typeBadgeClass(ticket.type)"
                            >
                                {{ $t(`clientTicket.type.${ticket.type}`) }}
                            </span>
                        </div>
                        <h4 class="mt-1.5 text-sm font-semibold leading-snug text-neutral-900">{{ ticket.title }}</h4>
                        <p class="mt-1.5 text-xs text-neutral-400">{{ formatDate(ticket.createdAt) }}</p>
                    </div>
                    <p
                        v-if="col.tickets.length === 0"
                        class="py-4 text-center text-xs text-neutral-400"
                    >
                        {{ $t('clientTicket.noTickets') }}
                    </p>
                </div>
            </div>
        </div>

        <!-- Ticket detail modal -->
        <ClientTicketDetailModal
            v-model="detailOpen"
            :ticket="selectedTicket"
            @refresh="loadTickets"
        />

        <!-- Reject comment modal -->
        <Teleport v-if="rejectModalOpen" to="body">
            <div class="fixed inset-0 z-[60] flex items-center justify-center p-4">
                <div class="absolute inset-0 bg-slate-900/40 backdrop-blur-sm" @click="cancelReject" />
                <div class="relative z-10 w-full max-w-md rounded-2xl bg-white p-6 shadow-2xl">
                    <h3 class="text-lg font-bold text-neutral-900">{{ $t('clientTicket.changeStatus') }}</h3>
                    <p class="mt-2 text-sm text-neutral-600">{{ $t('clientTicket.rejectionRequired') }}</p>
                    <textarea
                        v-model="rejectComment"
                        rows="3"
                        class="mt-3 w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-1 focus:ring-primary-500"
                        :placeholder="$t('clientTicket.rejectComment')"
                    />
                    <div class="mt-4 flex justify-end gap-3">
                        <button
                            type="button"
                            class="rounded-lg border border-neutral-300 px-4 py-2 text-sm font-semibold text-neutral-700 hover:bg-neutral-50"
                            @click="cancelReject"
                        >
                            {{ $t('common.cancel') }}
                        </button>
                        <button
                            type="button"
                            class="rounded-lg bg-red-600 px-4 py-2 text-sm font-semibold text-white hover:bg-red-700 disabled:opacity-50"
                            :disabled="!rejectComment.trim()"
                            @click="confirmReject"
                        >
                            {{ $t('clientTicket.status.rejected') }}
                        </button>
                    </div>
                </div>
            </div>
        </Teleport>
    </div>
</template>

<script setup lang="ts">
import type { ClientTicket, ClientTicketStatus } from '~/services/dto/client-ticket'
import { useClientTicketService } from '~/services/client-tickets'
import { useProjectService } from '~/services/projects'

definePageMeta({
    layout: 'portal',
})

const route = useRoute()
const { t } = useI18n()
const projectId = computed(() => Number(route.params.id))

useHead({ title: t('portal.title') })

const clientTicketService = useClientTicketService()
const projectService = useProjectService()
const auth = useAuthStore()

const tickets = ref<ClientTicket[]>([])
const projectName = ref('')
const isLoading = ref(true)
const detailOpen = ref(false)
const selectedTicket = ref<ClientTicket | null>(null)

const isClient = computed(() => auth.user?.roles?.includes('ROLE_CLIENT') && !auth.user?.roles?.includes('ROLE_ADMIN'))
const isAdmin = computed(() => auth.user?.roles?.includes('ROLE_ADMIN') ?? false)
const { typeBadgeClass, formatDate } = useClientTicketHelpers()

const allStatuses: ClientTicketStatus[] = ['new', 'in_progress', 'done', 'rejected']

function statusDotClass(status: string): string {
    switch (status) {
        case 'new': return 'bg-blue-500'
        case 'in_progress': return 'bg-yellow-500'
        case 'done': return 'bg-green-500'
        case 'rejected': return 'bg-red-500'
        default: return 'bg-neutral-400'
    }
}

const columns = computed(() => allStatuses.map(status => ({
    status,
    label: t(`clientTicket.status.${status}`),
    dotClass: statusDotClass(status),
    tickets: tickets.value.filter(tk => tk.status === status),
})))

// Drag & drop (admin only)
const draggedTicket = ref<ClientTicket | null>(null)
const dragOverStatus = ref<ClientTicketStatus | null>(null)

function onDragStart(ticket: ClientTicket) {
    draggedTicket.value = ticket
}

function onDragEnd() {
    draggedTicket.value = null
    dragOverStatus.value = null
}

function onDragOver(status: ClientTicketStatus) {
    if (!draggedTicket.value) return
    dragOverStatus.value = status
}

function onDragLeave() {
    dragOverStatus.value = null
}

async function onDrop(newStatus: ClientTicketStatus) {
    dragOverStatus.value = null
    const ticket = draggedTicket.value
    draggedTicket.value = null

    if (!ticket || ticket.status === newStatus) return

    // Rejected requires a comment
    if (newStatus === 'rejected') {
        pendingRejectTicket.value = ticket
        rejectComment.value = ''
        rejectModalOpen.value = true
        return
    }

    // Optimistic update
    const oldStatus = ticket.status
    ticket.status = newStatus
    try {
        await clientTicketService.updateStatus(ticket.id, { status: newStatus })
        await loadTickets()
    } catch {
        ticket.status = oldStatus
    }
}

// Reject modal
const rejectModalOpen = ref(false)
const rejectComment = ref('')
const pendingRejectTicket = ref<ClientTicket | null>(null)

function cancelReject() {
    rejectModalOpen.value = false
    pendingRejectTicket.value = null
    rejectComment.value = ''
}

async function confirmReject() {
    const ticket = pendingRejectTicket.value
    if (!ticket || !rejectComment.value.trim()) return

    const oldStatus = ticket.status
    ticket.status = 'rejected'
    rejectModalOpen.value = false

    try {
        await clientTicketService.updateStatus(ticket.id, {
            status: 'rejected',
            statusComment: rejectComment.value.trim(),
        })
        await loadTickets()
    } catch {
        ticket.status = oldStatus
    }

    pendingRejectTicket.value = null
    rejectComment.value = ''
}

function openDetail(ticket: ClientTicket) {
    selectedTicket.value = ticket
    detailOpen.value = true
}

async function loadData() {
    isLoading.value = true
    try {
        const [ticketList, project] = await Promise.all([
            clientTicketService.getAll({ project: projectId.value }),
            projectService.getById(projectId.value),
        ])
        tickets.value = ticketList
        projectName.value = project.name
    } finally {
        isLoading.value = false
    }
}

async function loadTickets() {
    tickets.value = await clientTicketService.getAll({ project: projectId.value })
}

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