<template>
    <div class="project-container">
        <h3>{{ projectData.name }} (ID: {{ projectData.id }})</h3>
        <div v-if="isLoadingInitialData">Загружаем карточки...</div>
        <div v-else>
            <div v-if="userstoriesForProject && userstoriesForProject.length === 0">Нет карточек на доске.</div>
            <div v-else-if="sortedUserstories" class="userstory-table-container">
                <table>
                    <thead>
                        <tr>
                            <th v-for="header in tableHeaders" :key="header.key" @click="handleSort(header.key)" style="cursor: pointer">
                                {{ header.label }}
                                <span v-if="sortKey === header.key">{{ sortOrder === "asc" ? "▲" : "▼" }}</span>
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr v-for="userstory in sortedUserstories" :key="userstory.id">
                            <td v-for="header in tableHeaders" :key="`${userstory.id}-${header.key}`">
                                {{ getCellValue(userstory, header) }}
                            </td>
                        </tr>
                        <tr v-if="isLoadingAttributesForAnyStory && (!sortedUserstories || sortedUserstories.length > 0)">
                            <td :colspan="tableHeaders.length">Загружаем данные карточек...</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed, watch } from "vue";
import { useDataStore } from "@/stores/data";
import type { Project, Userstory, ProjectField, UserstoryStatusInfo } from "@/types/api";

interface TableHeader {
    key: string;
    label: string;
    isAttribute: boolean;
    attributeId?: number;
}

const props = defineProps<{
    projectData: Project;
}>();

const dataStore = useDataStore();
const isLoadingInitialData = ref(true);
const isLoadingAttributesForAnyStory = ref(false);

const sortKey = ref<string | null>(null);
const sortOrder = ref<"asc" | "desc">("asc");

const tableHeaders = computed<TableHeader[]>(() => {
    const headers: TableHeader[] = [
        { key: "id", label: "ID", isAttribute: false },
        { key: "subject", label: "Заголовок карточки", isAttribute: false },
        { key: "status", label: "Статус", isAttribute: false },
    ];

    const fields = dataStore.projectFieldsMap.get(props.projectData.id);
    if (fields) {
        const sortedFields = [...fields].sort((a, b) => a.order - b.order);
        sortedFields.forEach((field) => {
            headers.push({
                key: `attr_${field.id}`,
                label: field.name,
                isAttribute: true,
                attributeId: field.id,
            });
        });
    }
    return headers;
});

const userstoriesForProject = computed(() => {
    return dataStore.userstoriesMap.get(props.projectData.id);
});

const sortedUserstories = computed(() => {
    if (!userstoriesForProject.value) {
        return [];
    }
    if (!sortKey.value) {
        return [...userstoriesForProject.value];
    }

    const sorted = [...userstoriesForProject.value];
    const currentSortKeyVal = sortKey.value;
    const currentSortOrderVal = sortOrder.value;

    const headerToSortBy = tableHeaders.value.find((h) => h.key === currentSortKeyVal);
    if (!headerToSortBy) {
        return userstoriesForProject.value;
    }

    sorted.sort((a, b) => {
        let valA_raw = getCellValue(a, headerToSortBy);
        let valB_raw = getCellValue(b, headerToSortBy);

        if (valA_raw === "...") valA_raw = "";
        if (valB_raw === "...") valB_raw = "";

        const valA_is_null_or_undefined = valA_raw === null || valA_raw === undefined;
        const valB_is_null_or_undefined = valB_raw === null || valB_raw === undefined;

        let comparisonResult = 0;

        if (typeof valA_raw === "number" && typeof valB_raw === "number") {
            comparisonResult = valA_raw - valB_raw;
        } else {
            const strA = valA_is_null_or_undefined ? "" : String(valA_raw).toLowerCase();
            const strB = valB_is_null_or_undefined ? "" : String(valB_raw).toLowerCase();

            if (strA < strB) {
                comparisonResult = -1;
            } else if (strA > strB) {
                comparisonResult = 1;
            }
        }

        return currentSortOrderVal === "asc" ? comparisonResult : -comparisonResult;
    });
    return sorted;
});

watch(
    userstoriesForProject,
    async (newUserstories) => {
        if (newUserstories && newUserstories.length > 0) {
            const storiesWithoutAttributes = newUserstories.filter((us) => !dataStore.userstoryAttributesMap.has(us.id));
            if (storiesWithoutAttributes.length > 0) {
                isLoadingAttributesForAnyStory.value = true;
                const attributePromises = storiesWithoutAttributes.map((us) => dataStore.fetchUserstoryAttributes(us.id));

                try {
                    await Promise.all(attributePromises);
                } catch (error) {
                    console.error(`Error loading attributes for project ${props.projectData.id}:`, error);
                } finally {
                    const stillLoading = newUserstories.some(
                        (us) => !dataStore.userstoryAttributesMap.has(us.id) && storiesWithoutAttributes.find((s) => s.id === us.id),
                    );
                    isLoadingAttributesForAnyStory.value = stillLoading;
                }
            } else {
                isLoadingAttributesForAnyStory.value = false;
            }
        } else {
            isLoadingAttributesForAnyStory.value = false;
        }
    },
    { immediate: true, deep: true },
);

onMounted(async () => {
    isLoadingInitialData.value = true;
    try {
        await Promise.all([dataStore.fetchProjectFields(props.projectData.id), dataStore.fetchUserstories(props.projectData.id)]);
    } catch (error) {
        console.error(`Error loading data for project ${props.projectData.id}:`, error);
    } finally {
        isLoadingInitialData.value = false;
    }
});

function handleSort(headerKey: string) {
    if (sortKey.value === headerKey) {
        sortOrder.value = sortOrder.value === "asc" ? "desc" : "asc";
    } else {
        sortKey.value = headerKey;
        sortOrder.value = "asc";
    }
}

function getCellValue(userstory: Userstory, header: TableHeader): string | number | null {
    if (!header.isAttribute) {
        if (header.key === "status") {
            return userstory.status_extra_info?.name || userstory.status?.toString() || "";
        }
        const value = userstory[header.key as keyof Userstory];

        if (value === null) return null;
        if (typeof value === "string" || typeof value === "number") return value;
        if (value === undefined) return "";
        return String(value);
    } else {
        if (header.attributeId === undefined) return "N/A (no attr ID)";

        const attributes = dataStore.userstoryAttributesMap.get(userstory.id);
        if (attributes) {
            const attrValue = attributes[header.attributeId.toString()];

            if (attrValue === null) return null;
            if (typeof attrValue === "string" || typeof attrValue === "number") return attrValue;
            if (attrValue === undefined) return "";
            return String(attrValue);
        }

        if (isLoadingAttributesForAnyStory.value && !dataStore.userstoryAttributesMap.has(userstory.id)) {
            return "...";
        }
        return "";
    }
}
</script>

<style scoped>
.project-container {
    margin-bottom: 30px;
    padding: 15px;
    border: 1px solid #e0e0e0;
    border-radius: 4px;
}
.userstory-table-container {
    max-height: 500px;
    overflow-y: auto;
    overflow-x: auto;
}
table thead tr th {
    font-weight: bold;
}
table thead tr th:hover {
    background-color: var(--vt-c-black-soft);
}
</style>
