<template>
    <LayoutAuthenticated>
        <Head title="Collections"></Head>
        <SectionMain>
            <SectionTitleLineWithButton :icon="mdiLibraryShelves" title="Library Classification" main>
                <div class="bg-lime-100 shadow rounded-lg p-6 mb-6 flex items-center justify-between">
                    <div>
                        <label for="role-select" class="block text-lg font-medium text-gray-700 mb-1">
                            Select Classification Role <span class="text-red-500">*</span>
                        </label>
                        <select id="role-select" v-model="selectedCollectionRole"
                            class="w-full border border-gray-300 rounded-md p-2 text-gray-700 focus:ring-2 focus:ring-indigo-500"
                            required>
                            <!-- <option value="" disabled selected>Please select a role</option> -->
                            <option v-for="collRole in collectionRoles" :key="collRole.id" :value="collRole">
                                {{ collRole.name }}
                            </option>
                        </select>
                    </div>
                    <div class="ml-4 hidden md:block">
                        <span class="text-sm text-gray-600 italic">* required</span>
                    </div>
                </div>
            </SectionTitleLineWithButton>


            <!-- Available TopLevel Collections -->
            <CardBox class="mb-4 rounded-lg p-4">
                <h2 class="text-lg font-bold text-gray-800 dark:text-slate-400 mb-2">Available Toplevel-Collections
                    <span v-if="selectedCollectionRole && !selectedToplevelCollection"
                        class="text-sm text-red-500 italic">(click to
                        select)</span>
                </h2>
                <ul class="flex flex-wrap gap-2">
                    <li v-for="col in collections" :key="col.id" :class="{
                        'cursor-pointer p-2 border border-gray-200 rounded hover:bg-sky-50 text-sky-700 text-sm': true,
                        'bg-sky-100 border-sky-500': selectedToplevelCollection && selectedToplevelCollection.id === col.id
                    }" @click="onToplevelCollectionSelected(col)">
                        {{ `${col.name} (${col.number})` }}
                    </li>
                    <li v-if="collections.length === 0" class="text-gray-800 dark:text-slate-400">
                        No collections available.
                    </li>
                </ul>
            </CardBox>

            <!-- Collections Listing -->
            <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">

                <!-- Broader Collection (Parent) -->
                <CardBox v-if="selectedCollection" class="rounded-lg p-4" has-form-data>
                    <h2 class="text-lg font-bold text-gray-800 dark:text-slate-400 mb-2">Broader Collection</h2>                   
                    <draggable v-if="broaderCollections.length > 0" v-model="broaderCollections"
                        :group="{ name: 'collections' }" tag="ul" class="flex flex-wrap gap-2 max-h-60 overflow-y-auto">
                        <template #item="{ element: parent }">
                            <li :key="parent.id" :draggable="!parent.inUse" :class="getChildClasses(parent)"
                                @click="onCollectionSelected(parent)">
                                {{ `${parent.name} (${parent.number})` }}
                            </li>
                        </template>
                    </draggable>
                    <ul v-else class="flex flex-wrap gap-2 max-h-60 overflow-y-auto">
                        <li class="text-gray-500 text-sm">
                            No broader collections available.
                        </li>
                    </ul>
                </CardBox>

                <!-- Selected Collection Details -->
                <CardBox v-if="selectedCollection" class="rounded-lg p-4" has-form-data>
                    <h3 class="text-xl font-bold text-gray-800 dark:text-slate-400 mb-2">Selected Collection</h3>
                     <!-- <p :class="[
                        'cursor-pointer p-2 border border-gray-200 rounded text-sm',
                        selectedCollection.inUse ? 'bg-gray-200 text-gray-500 drag-none' : 'bg-green-50 text-green-700 hover:bg-green-100 hover:underline cursor-move'
                    ]"></p> -->
                    <draggable v-model="selectedCollectionArray" :group="{ name: 'collections', pull: 'clone', put: false }" tag="ul" class="flex flex-wrap gap-2 max-h-60 overflow-y-auto">
                        <template #item="{ element }">
                            <li :key="element.id" :class="[
                                'p-2 border border-gray-200 rounded text-sm',
                                element.inUse ? 'bg-gray-200 text-gray-500 drag-none' : 'bg-green-50 text-green-700 hover:bg-green-100 hover:underline cursor-move'
                            ]">
                                {{ `${element.name} (${element.number})` }}
                            </li>
                        </template>
                    </draggable>
                </CardBox>
                <!-- Narrower Collections (Children) -->
                <CardBox v-if="selectedCollection" class="rounded-lg p-4" has-form-data>
                    <h2 class="text-lg font-bold text-gray-800 dark:text-slate-400 mb-2">Narrower Collections</h2>                  
                    <draggable v-if="narrowerCollections.length > 0" v-model="narrowerCollections"
                        :group="{ name: 'collections' }" tag="ul" class="flex flex-wrap gap-2 max-h-60 overflow-y-auto">
                        <template #item="{ element: child }">
                            <li :key="child.id" :draggable="!child.inUse" :class="getChildClasses(child)"
                                @click="onCollectionSelected(child)">
                                {{ `${child.name} (${child.number})` }}
                            </li>
                        </template>
                    </draggable>
                    <ul v-else class="flex flex-wrap gap-2 max-h-60 overflow-y-auto">
                        <li class="text-gray-500 text-sm">
                            No sub-collections available.
                        </li>
                    </ul>
                </CardBox>

            </div>

            <div class="mb-4 rounded-lg">
                <div v-if="selectedCollection || selectedCollectionList.length > 0" class="bg-gray-100 shadow rounded-lg p-6 mb-6" :class="{ 'opacity-50': selectedCollection && selectedCollectionList.length === 0 }">
                    <p class="mb-4 text-gray-700">Please drag your collections here to classify your previously created
                        dataset
                        according to library classification standards.</p>
                    <draggable v-model="selectedCollectionList" :group="{ name: 'collections' }"
                        class="min-h-36 border-dashed border-2 border-gray-400 p-4 text-sm flex flex-wrap gap-2 max-h-60 overflow-y-auto"
                        tag="ul"
                        :disabled="selectedCollection === null && selectedCollectionList.length > 0"
                        :style="{ opacity: (selectedCollection === null && selectedCollectionList.length > 0) ? 0.5 : 1, pointerEvents: (selectedCollection === null && selectedCollectionList.length > 0) ? 'none' : 'auto' }">
                        <template #item="{ element }">
                            <div :key="element.id"
                                class="p-2 m-1 bg-sky-200 text-sky-800 rounded flex items-center gap-2 h-7">
                                <span>{{ element.name }} ({{ element.number }})</span>
                                <button
                                    @click="selectedCollectionList = selectedCollectionList.filter(item => item.id !== element.id)"
                                    class="hover:text-sky-600 flex items-center">
                                    <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 20 20"
                                        fill="currentColor">
                                        <path fill-rule="evenodd"
                                            d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
                                            clip-rule="evenodd" />
                                    </svg>
                                </button>
                            </div>
                        </template>
                    </draggable>                
                </div>
            </div>
            <div class="p-6 border-t border-gray-100 dark:border-slate-800">
                <BaseButtons>
                    <BaseButton @click.stop="syncDatasetCollections" label="Save" color="info" small
                        :disabled="isSaveDisabled" :style="{ opacity: isSaveDisabled ? 0.5 : 1 }">
                    </BaseButton>
                </BaseButtons>
            </div>
        </SectionMain>
    </LayoutAuthenticated>
</template>

<script setup lang="ts">
import { ref, Ref, watch, computed } from 'vue';
import { useForm } from '@inertiajs/vue3';
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
import SectionMain from '@/Components/SectionMain.vue';
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
import axios from 'axios';
import { mdiLibraryShelves } from '@mdi/js';
import draggable from 'vuedraggable';
import BaseButton from '@/Components/BaseButton.vue';
import BaseButtons from '@/Components/BaseButtons.vue';
import CardBox from '@/Components/CardBox.vue';
import { stardust } from '@eidellev/adonis-stardust/client';
import { CollectionRole, Collection } from '@/types/models';

// import CollectionRoleSelector from '@/Components/Collection/CollectionRoleSelector.vue';
// import ToplevelCollections from '@/Components/Collection/ToplevelCollections.vue';
// import CollectionHierarchy from '@/Components/Collection/CollectionHierarchy.vue';
// import CollectionDropZone from '@/Components/Collection/CollectionDropZone.vue';



/* --------------------------------------------------------------------------
   Props & Reactive State
-------------------------------------------------------------------------- */
const props = defineProps({
    collectionRoles: {
        type: Array,
        required: true,
        default: () => []
    },
    dataset: {
        type: Object,
        default: () => ({}),
    },
    relatedCollections: {
        type: Array as () => Collection[],
        default: () => [] as const
    }
});

const collectionRoles: Ref<CollectionRole[]> = ref(props.collectionRoles as CollectionRole[]);
const collections: Ref<Collection[]> = ref<Collection[]>([]);
const selectedCollectionRole = ref<CollectionRole | null>(null);
const selectedToplevelCollection = ref<Collection | null>(null);
const selectedCollection = ref<Collection | null>(null);
const narrowerCollections = ref<Collection[]>([]);
const broaderCollections = ref<Collection[]>([]);
// Reactive list that holds collections dropped by the user
const selectedCollectionList: Ref<Collection[]> = ref<Collection[]>([]);


// Wrap selectedCollection in an array for draggable (always expects an array)
const selectedCollectionArray = computed({
  get: () => (selectedCollection.value ? [selectedCollection.value] : []),
  set: (value: Collection[]) => {
    selectedCollection.value = value.length ? value[0] : null
  }
})


const form = useForm({
    collections: [] as number[],
});

// Watch for changes in dropCollections
watch(
    () => selectedCollectionList.value,
    () => {
        if (selectedCollection.value) {
            fetchCollections(selectedCollection.value.id);
        }
    },
    { deep: true }
);


/* --------------------------------------------------------------------------
   Watchers and Initial Setup
-------------------------------------------------------------------------- */
// If the collectionRoles prop might load asynchronously (or change), you can watch for it:
watch(
    () => props.collectionRoles as CollectionRole[],
    (newCollectionRoles: CollectionRole[]) => {
        collectionRoles.value = newCollectionRoles;
        // Preselect the role with name "ccs" if it exists
        const found: CollectionRole | undefined = collectionRoles.value.find(
            role => role.name.toLowerCase() === 'ccs'
        );
        if (found?.name === 'ccs') {
            selectedCollectionRole.value = found;
        }
    },
    { immediate: true }
);

// When collection role changes, update available collections and clear dependent state.
watch(
    () => selectedCollectionRole.value as CollectionRole,
    (newSelectedCollectionRole: CollectionRole | null) => {
        if (newSelectedCollectionRole != null) {
            collections.value = newSelectedCollectionRole.collections || []
        } else {
            selectedToplevelCollection.value = null;
            selectedCollection.value = null;
            collections.value = []
        }
        // Reset dependent variables when the role changes
        selectedCollection.value = null
        narrowerCollections.value = []
        broaderCollections.value = []
    },
    { immediate: true }
);

/* --------------------------------------------------------------------------
   Methods
-------------------------------------------------------------------------- */
const onToplevelCollectionSelected = (collection: Collection) => {
    selectedToplevelCollection.value = collection;
    selectedCollection.value = collection;
    // call the API endpoint to get both.
    fetchCollections(collection.id);
};

const onCollectionSelected = (collection: Collection) => {
    selectedCollection.value = collection;
    // call the API endpoint to get both.
    fetchCollections(collection.id);
};

/**
 * fetchCollections: Retrieves broader and narrower collections.
 * Marks any narrower collection as inUse if it appears in selectedCollectionList.
 */
const fetchCollections = async (collectionId: number) => {
    try {
        const response = await axios.get(`/api/collections/${collectionId}`);
        const data = response.data;
        // Map each returned narrower collection
        narrowerCollections.value = data.narrowerCollections.map((collection: Collection) => {
            // If found, mark it as inUse.
            const alreadyDropped = selectedCollectionList.value.find(dc => dc.id === collection.id);
            return alreadyDropped ? { ...collection, inUse: true } : { ...collection, inUse: false };
        });
        broaderCollections.value = data.broaderCollection.map((collection: Collection) => {
            const alreadyDropped = selectedCollectionList.value.find(dc => dc.id === collection.id);
            return alreadyDropped ? { ...collection, inUse: true } : { ...collection, inUse: false };
        });
        // Check if selected collection is in the selected list
        if (selectedCollection.value && selectedCollectionList.value.find(dc => dc.id === selectedCollection.value.id)) {
            selectedCollection.value = { ...selectedCollection.value, inUse: true };
        } else if (selectedCollection.value) {
            selectedCollection.value = { ...selectedCollection.value, inUse: false };
        }    
    } catch (error) {
        console.error('Error in fetchCollections:', error);
    }
};

const syncDatasetCollections = async () => {
    // Extract the ids from the dropCollections list
    form.collections = selectedCollectionList.value.map((item: Collection) => item.id);
    form.put(stardust.route('dataset.categorizeUpdate', [props.dataset.id]), {
        preserveState: true,
        onSuccess: () => {
            console.log('Dataset collections synced successfully');
        },
        onError: (errors) => {
            console.error('Error syncing dataset collections:', errors);
        },
    });
};

/**
 * getChildClasses returns the Tailwind CSS classes to apply to each collection list item.
 */
const getChildClasses = (child: Collection) => {
    return child.inUse
        ? 'p-2 border border-gray-200 rounded bg-gray-200 text-gray-500 cursor-pointer drag-none'
        : 'p-2 border border-gray-200 rounded bg-green-50 text-green-700 cursor-move hover:bg-green-100 hover:underline'
}

// If there are related collections passed in, fill dropCollections with these.
if (props.relatedCollections && props.relatedCollections.length > 0) {
    selectedCollectionList.value = props.relatedCollections;
}

// Add a computed property for the disabled state based on dropCollections length
const isSaveDisabled = computed(() => selectedCollectionList.value.length === 0);
</script>

<style scoped>
.btn-primary {
    background-color: #4f46e5;
    color: white;
    border-radius: 0.25rem;
}

.btn-primary:hover {
    background-color: #4338ca;
}

.btn-primary:focus {
    outline: none;
    box-shadow: 0 0 0 2px #fff, 0 0 0 4px #4f46e5;
}

.btn-secondary {
    background-color: white;
    color: #374151;
    border: 1px solid #d1d5db;
    border-radius: 0.25rem;
}

.btn-secondary:hover {
    background-color: #f9fafb;
}

.btn-secondary:focus {
    outline: none;
    box-shadow: 0 0 0 2px #fff, 0 0 0 4px #6366f1;
}
</style>
