<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { mdiTrashCan } from '@mdi/js';
import { mdiDragVariant, mdiChevronLeft, mdiChevronRight } from '@mdi/js';
import BaseIcon from '@/Components/BaseIcon.vue';
import BaseButtons from '@/Components/BaseButtons.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 = defineProps({
//     checkable: Boolean,
//     persons: {
//         type: Array<Person>,
//         default: () => [],
//     },
//     relation: {
//         type: String,
//         required: true,
//     },
//     contributortypes: {
//         type: Object,
//         default: () => ({}),
//     },
//     errors: {
//         type: Object,
//         default: () => ({}),
//     },
// });
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);

// Computed properties
const items = computed({
    get() {
        return props.persons;
    },
    // setter
    set(value) {
        // Note: we are using destructuring assignment syntax here.

        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;
});

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

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

        // Adjust current page if needed
        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];
    (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,
    () => {
        // Reset to first page if current page is out of bounds
        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 p-3 border-b border-gray-200 dark:border-slate-700">
            <div class="flex items-center gap-2">
                <span class="text-sm text-gray-600 dark:text-gray-400">
                    Showing {{ currentPage * perPage + 1 }} to
                    {{ Math.min((currentPage + 1) * perPage, items.length) }}
                    of {{ items.length }} entries
                </span>
            </div>
            <select
                v-model="perPage"
                @change="currentPage = 0"
                class="px-3 py-1 text-sm border rounded-md dark:bg-slate-800 dark:border-slate-600"
            >
                <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">
                <thead>
                    <tr class="border-b border-gray-200 dark:border-slate-700">
                        <th v-if="canReorder" class="w-10 p-3" />
                        <th scope="col" class="text-left p-3">#</th>
                        <th scope="col">Id</th>
                        <th>First Name</th>
                        <th>Last Name / Organization</th>
                        <th>Email</th>
                        <th v-if="showContributorTypes" scope="col" class="text-left p-3">Type</th>
                        <th v-if="canDelete" class="w-20 p-3">Actions</th>
                    </tr>
                </thead>
                <!-- <tbody> -->
                <!-- <tr v-for="(client, index) in itemsPaginated" :key="client.id"> -->
                <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-gray-50 dark:hover:bg-slate-800">
                            <td class="p-3">
                                <div class="drag-handle cursor-move text-gray-400 hover:text-gray-600">
                                    <BaseIcon :path="mdiDragVariant" />
                                </div>
                            </td>
                            <td class="p-3">{{ index + 1 }}</td>
                            <td data-label="Id" class="p-3 text-sm text-gray-600">{{ element.id || '-' }}</td>

                            <!-- First Name - Hidden for Organizational -->
                            <td class="p-3" data-label="First Name" v-if="element.name_type !== 'Organizational'">
                                <FormControl
                                    required
                                    v-model="element.first_name"
                                    type="text"
                                    :is-read-only="element.status == true"
                                    placeholder="[FIRST NAME]"
                                />
                                <div class="text-red-400 text-sm" v-if="errors && Array.isArray(errors[`${relation}.${index}.first_name`])">
                                    {{ errors[`${relation}.${index}.first_name`].join(', ') }}
                                </div>
                            </td>
                            <td v-else></td>
                            <!-- Empty cell for organizational entries -->

                            <!-- Last Name / Organization Name -->
                            <td :data-label="element.name_type === 'Organizational' ? 'Organization Name' : 'Last Name'">
                                <FormControl
                                    required
                                    v-model="element.last_name"
                                    type="text"
                                    :is-read-only="element.status == true"
                                    :placeholder="element.name_type === 'Organizational' ? '[ORGANIZATION NAME]' : '[LAST NAME]'"
                                />
                                <div class="text-red-400 text-sm" v-if="errors && Array.isArray(errors[`${relation}.${index}.last_name`])">
                                    {{ errors[`${relation}.${index}.last_name`].join(', ') }}
                                </div>
                            </td>

                            <!-- Email -->
                            <td data-label="Email">
                                <FormControl
                                    required
                                    v-model="element.email"
                                    type="text"
                                    :is-read-only="element.status == true"
                                    placeholder="[EMAIL]"
                                />
                                <div class="text-red-400 text-sm" v-if="errors && Array.isArray(errors[`${relation}.${index}.email`])">
                                    {{ errors[`${relation}.${index}.email`].join(', ') }}
                                </div>
                            </td>

                            <!-- Contributor Type -->
                            <td v-if="Object.keys(contributortypes).length">
                                <FormControl
                                    required
                                    v-model="element.pivot_contributor_type"
                                    type="select"
                                    :options="contributortypes"
                                    placeholder="[relation type]"
                                >
                                    <div
                                        class="text-red-400 text-sm"
                                        v-if="errors && Array.isArray(errors[`${relation}.${index}.pivot_contributor_type`])"
                                    >
                                        {{ errors[`${relation}.${index}.pivot_contributor_type`].join(', ') }}
                                    </div>
                                </FormControl>
                            </td>

                            <!-- Actions -->
                            <td class="before:hidden lg:w-1 whitespace-nowrap">
                                <BaseButtons type="justify-start lg:justify-end" no-wrap>
                                    <BaseButton color="danger" :icon="mdiTrashCan" small @click.prevent="removeAuthor(index)" />
                                </BaseButtons>
                            </td>
                        </tr>
                    </template>
                </draggable>
                <!-- </tbody> -->
                <!-- 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-gray-50 dark:hover:bg-slate-800"
                    >
                        <td v-if="canReorder" class="p-3 text-gray-400">
                            <BaseIcon :path="mdiDragVariant" />
                        </td>
                        <td class="p-3">{{ currentPage * perPage + index + 1 }}</td>
                        <td class="p-3 text-sm text-gray-600">{{ element.id || '-' }}</td>

                        <!-- Same field structure as draggable version -->
                        <td class="p-3">
                            <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]"
                                :error="getFieldError(index, 'first_name')"
                            />
                            <span v-else class="text-gray-400">-</span>
                            <div v-if="getFieldError(index, 'first_name')" class="text-red-400 text-sm">
                                {{ getFieldError(index, 'first_name') }}
                            </div>
                        </td>

                        <td class="p-3">
                            <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 NAME]' : '[LAST NAME]'"
                                :error="getFieldError(index, 'last_name')"
                            />
                            <div v-if="getFieldError(index, 'last_name')" class="text-red-400 text-sm">
                                {{ getFieldError(index, 'last_name') }}
                            </div>
                        </td>

                        <td class="p-3">
                            <FormControl
                                required
                                :model-value="element.email"
                                @update:model-value="updatePerson(index, 'email', $event)"
                                type="email"
                                :is-read-only="element.status || !canEdit"
                                placeholder="[EMAIL]"
                                :error="getFieldError(index, 'email')"
                            />
                            <div v-if="getFieldError(index, 'email')" class="text-red-400 text-sm">
                                {{ getFieldError(index, 'email') }}
                            </div>
                        </td>

                        <td v-if="showContributorTypes" class="p-3">
                            <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="[Select type]"
                                :error="getFieldError(index, 'pivot_contributor_type')"
                            />                          
                             <div v-if="getFieldError(index, 'pivot_contributor_type')" class="text-red-400 text-sm">
                                {{ getFieldError(index, 'pivot_contributor_type') }}
                            </div>
                        </td>

                        <td v-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>

                    <!-- Empty State -->
                    <tr v-if="items.length === 0">
                        <td :colspan="canReorder ? 8 : 7" 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;
}

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

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