<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { mdiTrashCan } from '@mdi/js';
import { mdiDragVariant, mdiChevronLeft, mdiChevronRight } from '@mdi/js';
import { mdiAccount, mdiDomain } from '@mdi/js';
import BaseIcon from '@/Components/BaseIcon.vue';
import BaseButton from '@/Components/BaseButton.vue';
import { Person } from '@/Dataset';
import Draggable from 'vuedraggable';
import FormControl from '@/Components/FormControl.vue';

interface Props {
    checkable?: boolean;
    persons?: Person[];
    relation: string;
    contributortypes?: Record<string, string>;
    errors?: Record<string, string[]>;
    isLoading?: boolean;
    canDelete?: boolean;
    canEdit?: boolean;
    canReorder?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
    checkable: false,
    persons: () => [],
    contributortypes: () => ({}),
    errors: () => ({}),
    isLoading: false,
    canDelete: true,
    canEdit: true,
    canReorder: true,
});

const emit = defineEmits<{
    'update:persons': [value: Person[]];
    'remove-person': [index: number, person: Person];
    'person-updated': [index: number, person: Person];
    'reorder': [oldIndex: number, newIndex: number];
}>();

// Local state
const perPage = ref(5);
const currentPage = ref(0);
const dragEnabled = ref(props.canReorder);

// Name type options
const nameTypeOptions = {
    'Personal': 'Personal',
    'Organizational': 'Org'
};

// Computed properties
const items = computed({
    get() {
        return props.persons;
    },
    set(value) {
        props.persons.length = 0;
        props.persons.push(...value);
    },
});

const itemsPaginated = computed(() => {
    const start = perPage.value * currentPage.value;
    const end = perPage.value * (currentPage.value + 1);
    return items.value.slice(start, end);
});

const numPages = computed(() => Math.ceil(items.value.length / perPage.value));
const currentPageHuman = computed(() => currentPage.value + 1);
const hasMultiplePages = computed(() => numPages.value > 1);
const showContributorTypes = computed(() => Object.keys(props.contributortypes).length > 0);

const pagesList = computed(() => {
    const pages: number[] = [];
    const maxVisible = 10;

    if (numPages.value <= maxVisible) {
        for (let i = 0; i < numPages.value; i++) {
            pages.push(i);
        }
    } else {
        // Smart pagination with ellipsis
        if (currentPage.value <= 2) {
            for (let i = 0; i < 4; i++) pages.push(i);
            pages.push(-1); // Ellipsis marker
            pages.push(numPages.value - 1);
        } else if (currentPage.value >= numPages.value - 3) {
            pages.push(0);
            pages.push(-1);
            for (let i = numPages.value - 4; i < numPages.value; i++) {
                pages.push(i);
            }
        } else {
            pages.push(0);
            pages.push(-1);
            for (let i = currentPage.value - 1; i <= currentPage.value + 1; i++) {
                pages.push(i);
            }
            pages.push(-1);
            pages.push(numPages.value - 1);
        }
    }

    return pages;
});

// Methods
const removeAuthor = (index: number) => {
    const actualIndex = perPage.value * currentPage.value + index;
    const person = items.value[actualIndex];

    const displayName = person.name_type === 'Organizational' 
        ? person.last_name || person.email 
        : `${person.first_name || ''} ${person.last_name || person.email}`.trim();

    if (confirm(`Are you sure you want to remove ${displayName}?`)) {
        items.value.splice(actualIndex, 1);
        emit('remove-person', actualIndex, person);

        if (itemsPaginated.value.length === 0 && currentPage.value > 0) {
            currentPage.value--;
        }
    }
};

const updatePerson = (index: number, field: keyof Person, value: any) => {
    const actualIndex = perPage.value * currentPage.value + index;
    const person = items.value[actualIndex];
    
    // Handle name_type change - clear first_name if switching to Organizational
    if (field === 'name_type' && value === 'Organizational') {
        person.first_name = '';
    }
    
    (person as any)[field] = value;
    emit('person-updated', actualIndex, person);
};

const goToPage = (page: number) => {
    if (page >= 0 && page < numPages.value) {
        currentPage.value = page;
    }
};

const getFieldError = (index: number, field: string): string => {
    const actualIndex = perPage.value * currentPage.value + index;
    const errorKey = `${props.relation}.${actualIndex}.${field}`;
    return props.errors[errorKey]?.join(', ') || '';
};

const handleDragEnd = (evt: any) => {
    if (evt.oldIndex !== evt.newIndex) {
        emit('reorder', evt.oldIndex, evt.newIndex);
    }
};

// Watchers
watch(
    () => props.persons.length,
    () => {
        if (currentPage.value >= numPages.value && numPages.value > 0) {
            currentPage.value = numPages.value - 1;
        }
    },
);

// Pagination helper
const perPageOptions = [
    { value: 5, label: '5 per page' },
    { value: 10, label: '10 per page' },
    { value: 20, label: '20 per page' },
    { value: 50, label: '50 per page' },
];
</script>

<template>
    <div class="card">
        <!-- Table Controls -->
        <div v-if="hasMultiplePages" class="flex justify-between items-center px-4 py-2.5 border-b border-gray-200 dark:border-slate-700 bg-gray-50 dark:bg-slate-800/50">
            <div class="flex items-center gap-2">
                <span class="text-xs text-gray-600 dark:text-gray-400">
                    {{ currentPage * perPage + 1 }}-{{ Math.min((currentPage + 1) * perPage, items.length) }} of {{ items.length }}
                </span>
            </div>
            <select
                v-model="perPage"
                @change="currentPage = 0"
                class="px-2 py-1 text-xs border rounded dark:bg-slate-800 dark:border-slate-600 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
            >
                <option v-for="option in perPageOptions" :key="option.value" :value="option.value">
                    {{ option.label }}
                </option>
            </select>
        </div>

        <!-- Table -->
        <div class="overflow-x-auto">
            <table class="w-full table-compact">
                <thead>
                    <tr class="bg-gray-50 dark:bg-slate-800/50 border-b border-gray-200 dark:border-slate-700">
                        <th v-if="canReorder" class="w-8 px-2 py-2" />
                        <th scope="col" class="text-left px-2 py-2 text-xs font-semibold text-gray-600 dark:text-gray-300 w-10">#</th>
                        <th class="text-left px-2 py-2 text-[10px] font-semibold text-gray-600 dark:text-gray-300 w-40">Type</th>
                        <th class="text-left px-2 py-2 text-xs font-semibold text-gray-600 dark:text-gray-300 min-w-[120px]">First Name</th>
                        <th class="text-left px-2 py-2 text-xs font-semibold text-gray-600 dark:text-gray-300 min-w-[160px]">Last Name / Org</th>
                        <th class="text-left px-2 py-2 text-xs font-semibold text-gray-600 dark:text-gray-300 min-w-[140px]">ORCID</th>
                        <th class="text-left px-2 py-2 text-xs font-semibold text-gray-600 dark:text-gray-300 min-w-[160px]">Email</th>
                        <th v-if="showContributorTypes" scope="col" class="text-left px-2 py-2 text-xs font-semibold text-gray-600 dark:text-gray-300 w-32">Role</th>
                        <th v-if="canDelete" class="w-16 px-2 py-2 text-xs font-semibold text-gray-600 dark:text-gray-300">Actions</th>
                    </tr>
                </thead>

                <!-- Draggable tbody for non-paginated view -->
                <draggable
                    v-if="canReorder && !hasMultiplePages"
                    tag="tbody"
                    v-model="items"
                    item-key="id"
                    :disabled="!dragEnabled || isLoading"
                    @end="handleDragEnd"
                    handle=".drag-handle"
                >
                    <template #item="{ index, element }">
                        <tr class="border-b border-gray-100 dark:border-slate-800 hover:bg-blue-50 dark:hover:bg-slate-800/70 transition-colors">
                            <td v-if="canReorder" class="px-2 py-2">
                                <div class="drag-handle cursor-move text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
                                    <BaseIcon :path="mdiDragVariant" :size="18" />
                                </div>
                            </td>
                            <td class="px-2 py-2 text-xs text-gray-600 dark:text-gray-400">{{ index + 1 }}</td>

                            <!-- Name Type Selector -->
                            <td class="px-2 py-2">
                                <div class="flex items-center gap-1.5">
                                    <BaseIcon 
                                        :path="element.name_type === 'Organizational' ? mdiDomain : mdiAccount" 
                                        :size="16"
                                        :class="element.name_type === 'Organizational' ? 'text-purple-500' : 'text-blue-500'"
                                        :title="element.name_type"
                                    />
                                    <FormControl
                                        required
                                        v-model="element.name_type"
                                        type="select"
                                        :options="nameTypeOptions"
                                        :is-read-only="element.status == true"
                                        class="text-[8px] compact-select-mini flex-1"
                                    />
                                </div>
                                <div class="text-red-500 text-[8px] mt-0.5" v-if="errors && Array.isArray(errors[`${relation}.${index}.name_type`])">
                                    {{ errors[`${relation}.${index}.name_type`][0] }}
                                </div>
                            </td>

                            <!-- First Name - Only shown for Personal type -->
                            <td class="px-2 py-2">
                                <FormControl
                                    v-if="element.name_type !== 'Organizational'"
                                    required
                                    v-model="element.first_name"
                                    type="text"
                                    :is-read-only="element.status == true"
                                    placeholder="First name"
                                    class="text-xs compact-input"
                                />
                                <span v-else class="text-gray-400 text-xs italic">—</span>
                                <div class="text-red-500 text-xs mt-0.5" v-if="errors && Array.isArray(errors[`${relation}.${index}.first_name`])">
                                    {{ errors[`${relation}.${index}.first_name`][0] }}
                                </div>
                            </td>

                            <!-- Last Name / Organization Name -->
                            <td class="px-2 py-2">
                                <FormControl
                                    required
                                    v-model="element.last_name"
                                    type="text"
                                    :is-read-only="element.status == true"
                                    :placeholder="element.name_type === 'Organizational' ? 'Organization' : 'Last name'"
                                    class="text-xs compact-input"
                                />
                                <div class="text-red-500 text-xs mt-0.5" v-if="errors && Array.isArray(errors[`${relation}.${index}.last_name`])">
                                    {{ errors[`${relation}.${index}.last_name`][0] }}
                                </div>
                            </td>

                            <!-- Orcid -->
                            <td class="px-2 py-2">
                                <FormControl
                                    v-model="element.identifier_orcid"
                                    type="text"
                                    :is-read-only="element.status == true"
                                    placeholder="0000-0000-0000-0000"
                                    class="text-xs compact-input font-mono"
                                />
                                <div class="text-red-500 text-xs mt-0.5" v-if="errors && Array.isArray(errors[`${relation}.${index}.identifier_orcid`])">
                                    {{ errors[`${relation}.${index}.identifier_orcid`][0] }}
                                </div>
                            </td>

                            <!-- Email -->
                            <td class="px-2 py-2">
                                <FormControl
                                    required
                                    v-model="element.email"
                                    type="email"
                                    :is-read-only="element.status == true"
                                    placeholder="email@example.com"
                                    class="text-xs compact-input"
                                />
                                <div class="text-red-500 text-xs mt-0.5" v-if="errors && Array.isArray(errors[`${relation}.${index}.email`])">
                                    {{ errors[`${relation}.${index}.email`][0] }}
                                </div>
                            </td>

                            <!-- Contributor Type -->
                            <td v-if="Object.keys(contributortypes).length" class="px-2 py-2">
                                <FormControl
                                    required
                                    v-model="element.pivot_contributor_type"
                                    type="select"
                                    :options="contributortypes"
                                    placeholder="Role"
                                    class="text-xs compact-select"
                                />
                                <div
                                    class="text-red-500 text-xs mt-0.5"
                                    v-if="errors && Array.isArray(errors[`${relation}.${index}.pivot_contributor_type`])"
                                >
                                    {{ errors[`${relation}.${index}.pivot_contributor_type`][0] }}
                                </div>
                            </td>

                            <!-- Actions -->
                            <td class="px-2 py-2 whitespace-nowrap">
                                <BaseButton 
                                    color="danger" 
                                    :icon="mdiTrashCan" 
                                    small 
                                    @click.prevent="removeAuthor(index)"
                                    class="compact-button"
                                />
                            </td>
                        </tr>
                    </template>
                </draggable>

                <!-- Non-draggable tbody for paginated view -->
                <tbody v-else>
                    <tr
                        v-for="(element, index) in itemsPaginated"
                        :key="element.id || index"
                        class="border-b border-gray-100 dark:border-slate-800 hover:bg-blue-50 dark:hover:bg-slate-800/70 transition-colors"
                    >
                        <td   v-if="canReorder" class="px-2 py-2 text-gray-400">
                            <BaseIcon :path="mdiDragVariant" :size="18" />
                        </td>
                        <td class="px-2 py-2 text-xs text-gray-600 dark:text-gray-400">{{ currentPage * perPage + index + 1 }}</td>

                        <!-- Name Type Selector -->
                        <td class="px-2 py-2">
                            <BaseIcon 
                                        :path="element.name_type === 'Organizational' ? mdiDomain : mdiAccount" 
                                        :size="16"
                                        :class="element.name_type === 'Organizational' ? 'text-purple-500' : 'text-blue-500'"
                                        :title="element.name_type"
                                    />
                            <FormControl
                                required
                                :model-value="element.name_type"                              
                                @update:model-value="updatePerson(index, 'name_type', $event)"
                                type="select"
                                :options="nameTypeOptions"
                                :is-read-only="element.status || !canEdit"
                                class="text-xs compact-select"
                                :error="getFieldError(index, 'name_type')"
                            />
                            <div v-if="getFieldError(index, 'name_type')" class="text-red-500 text-xs mt-0.5">
                                {{ getFieldError(index, 'name_type') }}
                            </div>
                        </td>

                        <!-- First Name -->
                        <td class="px-2 py-2">
                            <FormControl
                                v-if="element.name_type !== 'Organizational'"
                                required
                                :model-value="element.first_name"
                                @update:model-value="updatePerson(index, 'first_name', $event)"
                                type="text"
                                :is-read-only="element.status || !canEdit"
                                placeholder="First name"
                                class="text-xs compact-input"
                                :error="getFieldError(index, 'first_name')"
                            />
                            <span v-else class="text-gray-400 text-xs italic">—</span>
                            <div v-if="getFieldError(index, 'first_name')" class="text-red-500 text-xs mt-0.5">
                                {{ getFieldError(index, 'first_name') }}
                            </div>
                        </td>

                        <!-- Last Name / Organization -->
                        <td class="px-2 py-2">
                            <FormControl
                                required
                                :model-value="element.last_name"
                                @update:model-value="updatePerson(index, 'last_name', $event)"
                                type="text"
                                :is-read-only="element.status || !canEdit"
                                :placeholder="element.name_type === 'Organizational' ? 'Organization' : 'Last name'"
                                class="text-xs compact-input"
                                :error="getFieldError(index, 'last_name')"
                            />
                            <div v-if="getFieldError(index, 'last_name')" class="text-red-500 text-xs mt-0.5">
                                {{ getFieldError(index, 'last_name') }}
                            </div>
                        </td>

                        <!-- Orcid -->
                        <td class="px-2 py-2">
                            <FormControl
                                :model-value="element.identifier_orcid"
                                @update:model-value="updatePerson(index, 'identifier_orcid', $event)"
                                type="text"
                                :is-read-only="element.status || !canEdit"
                                placeholder="0000-0000-0000-0000"
                                class="text-xs compact-input font-mono"
                                :error="getFieldError(index, 'identifier_orcid')"
                            />
                            <div v-if="getFieldError(index, 'identifier_orcid')" class="text-red-500 text-xs mt-0.5">
                                {{ getFieldError(index, 'identifier_orcid') }}
                            </div>
                        </td>

                        <!-- Email -->
                        <td class="px-2 py-2">
                            <FormControl
                                required
                                :model-value="element.email"
                                @update:model-value="updatePerson(index, 'email', $event)"
                                type="email"
                                :is-read-only="element.status || !canEdit"
                                placeholder="email@example.com"
                                class="text-xs compact-input"
                                :error="getFieldError(index, 'email')"
                            />
                            <div v-if="getFieldError(index, 'email')" class="text-red-500 text-xs mt-0.5">
                                {{ getFieldError(index, 'email') }}
                            </div>
                        </td>

                        <!-- Contributor Type -->
                        <td v-if="showContributorTypes" class="px-2 py-2">
                            <FormControl
                                required
                                :model-value="element.pivot_contributor_type"
                                @update:model-value="updatePerson(index, 'pivot_contributor_type', $event)"
                                type="select"
                                :options="contributortypes"
                                :is-read-only="element.status || !canEdit"
                                placeholder="Role"
                                class="text-xs compact-select"
                                :error="getFieldError(index, 'pivot_contributor_type')"
                            />
                            <div v-if="getFieldError(index, 'pivot_contributor_type')" class="text-red-500 text-xs mt-0.5">
                                {{ getFieldError(index, 'pivot_contributor_type') }}
                            </div>
                        </td>

                        <!-- Actions -->
                        <td v-if="canDelete" class="px-2 py-2 whitespace-nowrap">
                            <BaseButton
                                color="danger"
                                :icon="mdiTrashCan"
                                small
                                @click="removeAuthor(index)"
                                :disabled="element.status || !canEdit"
                                title="Remove person"
                                class="compact-button"
                            />
                        </td>
                    </tr>

                    <!-- Empty State -->
                    <!-- <tr v-if="items.length === 0">
                        <td :colspan="showContributorTypes ? 9 : 8" class="text-center py-12 text-gray-400">
                            <div class="flex flex-col items-center gap-2">
                                <BaseIcon :path="mdiBookOpenPageVariant" :size="32" class="text-gray-300" />
                                <span class="text-sm">No persons added yet</span>
                            </div>
                        </td>
                    </tr>
                </tbody>-if="canDelete" class="p-3">
                            <BaseButtons type="justify-start lg:justify-end" no-wrap>
                                <BaseButton
                                    color="danger"
                                    :icon="mdiTrashCan"
                                    small
                                    @click="removeAuthor(index)"
                                    :disabled="element.status || !canEdit"
                                    title="Remove person"
                                />
                            </BaseButtons>
                        </td>
                    </tr>

                   
                    <tr v-if="items.length === 0">
                        <td :colspan="showContributorTypes ? 10 : 9" class="text-center p-8 text-gray-500">
                            No persons added yet
                        </td>
                    </tr> -->
                </tbody>
            </table>
        </div>

        <!-- Pagination -->
        <div v-if="hasMultiplePages" class="flex justify-between items-center p-3 border-t border-gray-200 dark:border-slate-700">
            <div class="flex gap-1">
                <BaseButton :disabled="currentPage === 0" @click="goToPage(currentPage - 1)" :icon="mdiChevronLeft" small outline />

                <template v-for="(page, i) in pagesList" :key="i">
                    <span v-if="page === -1" class="px-3 py-1">...</span>
                    <BaseButton
                        v-else
                        @click="goToPage(page)"
                        :label="String(page + 1)"
                        :color="page === currentPage ? 'info' : 'whiteDark'"
                        small
                        :outline="page !== currentPage"
                    />
                </template>

                <BaseButton
                    :disabled="currentPage >= numPages - 1"
                    @click="goToPage(currentPage + 1)"
                    :icon="mdiChevronRight"
                    small
                    outline
                />
            </div>

            <span class="text-sm text-gray-600 dark:text-gray-400">
                Page {{ currentPageHuman }} of {{ numPages }}
            </span>
        </div>
    </div>
</template>

<style lang="postcss" scoped>
.drag-handle {
    transition: color 0.2s;
}

.card {
    @apply bg-white dark:bg-slate-900 rounded-lg shadow-sm;
}

@media (max-width: 768px) {
    table {
        font-size: 0.875rem;
    }

    th,
    td {
        padding: 0.5rem !important;
    }
}
</style>