<script setup lang="ts">
/**
 * Канбан — альтернативный вид сделок (по статусам). 14 колонок (lead_statuses).
 *
 * Источник дизайна: liderra_v8_handoff/concepts/v8_kanban.html.
 * DnD реализован через vuedraggable@4 (обёртка SortableJS) — карточки можно
 * перетаскивать между колонками. При drop:
 *   - событие 'added' в целевой колонке → меняем `statusSlug` сделки.
 *   - событие 'removed' в исходной колонке → ничего не делаем (обработано в added).
 *   - событие 'moved' внутри одной колонки → только смена порядка (statusSlug
 *     не меняется; на API будущем — PATCH /api/deals/{id} {sort_order}).
 *
 * Не входит в этот коммит:
 * - PATCH /api/deals/{id} {status_slug} при drop — backend.
 * - Filters (Проект/Менеджер) — общий filter-bar с DealsView.
 * - DealDetailDrawer на click по карточке (event @open-deal).
 */
import { computed, onMounted, reactive, ref } from 'vue';
import { LEAD_STATUSES } from '../composables/leadStatuses';
import { MOCK_DEALS, type MockDeal } from '../composables/mockDeals';
import { mapApiDeal } from '../composables/dealsApiMapper';
import { usePolling } from '../composables/usePolling';
import * as dealsApi from '../api/deals';
import KanbanColumn from '../components/kanban/KanbanColumn.vue';
// NB: DealDetailDrawer и NewDealDialog оставлены sync — Vitest падает с
// EnvironmentTeardownError при async-загрузке chunk'ов после teardown jsdom
// (KanbanView.spec.ts). Sprint 2 Phase B / O-perf-06 split применён к DealsView.
import DealDetailDrawer from '../components/deals/DealDetailDrawer.vue';
import NewDealDialog from '../components/deals/NewDealDialog.vue';
import { useAuthStore } from '../stores/auth';
import { useLeadStatusesStore } from '../stores/leadStatuses';

const auth = useAuthStore();
const leadStatusesStore = useLeadStatusesStore();
const leadStatuses = computed(() => leadStatusesStore.statuses);

interface DraggableChangeEvent {
    added?: { element: MockDeal; newIndex: number };
    removed?: { element: MockDeal; oldIndex: number };
    moved?: { element: MockDeal; oldIndex: number; newIndex: number };
}

// Reactive Record<slug, MockDeal[]> — отдельный массив для каждой колонки
// (vuedraggable v-model требует независимые arrays). Deep-clone объектов
// сделок чтобы не мутировать MOCK_DEALS const при DnD.
const dealsByStatus = reactive<Record<string, MockDeal[]>>(
    LEAD_STATUSES.reduce<Record<string, MockDeal[]>>((acc, s) => {
        acc[s.slug] = MOCK_DEALS.filter((d) => d.statusSlug === s.slug).map((d) => ({ ...d }));
        return acc;
    }, {}),
);

function onColumnChange(targetSlug: MockDeal['statusSlug'], event: DraggableChangeEvent) {
    if (event.added) {
        // Карточка переехала в эту колонку → синхронизируем statusSlug.
        // На production будет POST /api/deals/{id}/transition с проверкой allowed-переходов.
        event.added.element.statusSlug = targetSlug;
    }
    // 'removed' и 'moved' — обрабатываются автоматически через v-model
    // (vuedraggable мутирует array; reactive triggers re-render).
}

const drawerOpen = ref(false);
const selectedDeal = ref<MockDeal | null>(null);

function onOpenDeal(id: number) {
    // Найти deal среди всех reactive-массивов dealsByStatus.
    for (const slug of Object.keys(dealsByStatus)) {
        const found = dealsByStatus[slug].find((d) => d.id === id);
        if (found) {
            selectedDeal.value = found;
            drawerOpen.value = true;
            return;
        }
    }
}

const totalDeals = ref(MOCK_DEALS.length);
const fetchError = ref(false);

const newDealOpen = ref(false);

function onDealCreated(deal: MockDeal) {
    if (!dealsByStatus[deal.statusSlug]) dealsByStatus[deal.statusSlug] = [];
    dealsByStatus[deal.statusSlug].unshift(deal);
    totalDeals.value++;
}

async function loadDeals() {
    if (!auth.user?.tenant_id) return;
    fetchError.value = false;
    try {
        const { deals, total } = await dealsApi.listDeals({ tenantId: auth.user.tenant_id, limit: 500 });
        const mapped = deals.map((d) => mapApiDeal(d));
        // Очищаем все колонки и распределяем заново.
        for (const slug of Object.keys(dealsByStatus)) {
            dealsByStatus[slug].splice(0, dealsByStatus[slug].length);
        }
        for (const deal of mapped) {
            if (!dealsByStatus[deal.statusSlug]) dealsByStatus[deal.statusSlug] = [];
            dealsByStatus[deal.statusSlug].push(deal);
        }
        totalDeals.value = total;
    } catch {
        fetchError.value = true; // оставляем MOCK_DEALS как fallback
    }
}

onMounted(() => {
    void leadStatusesStore.load();
    void loadDeals();
});

usePolling(loadDeals);

defineExpose({ dealsByStatus, totalDeals, newDealOpen, onDealCreated, fetchError, loadDeals });
</script>

<template>
    <v-container fluid class="kanban pa-6">
        <header class="page-head">
            <div>
                <h1 class="text-h4 mb-2 page-title">Канбан</h1>
                <div class="page-stats text-body-2 text-medium-emphasis">
                    <span
                        ><span class="num">{{ leadStatuses.length }}</span> статусов</span
                    >
                    <span class="sep">·</span>
                    <span
                        ><span class="num">{{ totalDeals }}</span> сделок</span
                    >
                    <span class="sep">·</span>
                    <span class="text-caption text-medium-emphasis"> Перетаскивание между колонками </span>
                </div>
            </div>
            <div class="d-flex ga-2">
                <v-btn variant="outlined" prepend-icon="mdi-refresh" data-testid="reload-btn" @click="loadDeals">
                    Обновить
                </v-btn>
                <v-btn
                    color="primary"
                    variant="flat"
                    prepend-icon="mdi-plus"
                    data-testid="new-deal-btn"
                    @click="newDealOpen = true"
                >
                    Новая сделка
                </v-btn>
            </div>
        </header>

        <v-alert
            v-if="fetchError"
            type="warning"
            variant="tonal"
            density="compact"
            closable
            class="mt-3"
            data-testid="fetch-error-alert"
        >
            Backend недоступен — показаны mock-данные.
        </v-alert>

        <div class="kanban-board mt-4" tabindex="0" role="region" aria-label="Канбан-доска воронки продаж">
            <KanbanColumn
                v-for="status in leadStatuses"
                :key="status.slug"
                :status="status"
                :deals="dealsByStatus[status.slug] || []"
                @update:deals="(list) => (dealsByStatus[status.slug] = list)"
                @change="(e) => onColumnChange(status.slug, e)"
                @open-deal="onOpenDeal"
            />
        </div>

        <DealDetailDrawer v-model:open="drawerOpen" :deal="selectedDeal" :tenant-id="auth.user?.tenant_id" />

        <NewDealDialog v-model="newDealOpen" :tenant-id="auth.user?.tenant_id" @created="onDealCreated" />
    </v-container>
</template>

<style scoped>
.kanban {
    max-width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
}

.page-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
}

.page-title {
    font-variation-settings: 'opsz' 28;
    letter-spacing: -0.018em;
}

.page-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}
.page-stats .sep {
    /* WCAG2AA 4.5:1 fix (was #92907b → 2.92:1 on ivory; #6b6356 → 5.33:1). */
    color: #6b6356;
}

.num {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-feature-settings: 'tnum';
    font-weight: 500;
}

.kanban-board {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    overflow-y: hidden;
    flex: 1 1 auto;
    min-height: 600px;
    padding-bottom: 12px;
}

.kanban-board::-webkit-scrollbar {
    height: 8px;
}
.kanban-board::-webkit-scrollbar-track {
    background: transparent;
}
.kanban-board::-webkit-scrollbar-thumb {
    background: #d9d5cd;
    border-radius: 4px;
}
.kanban-board::-webkit-scrollbar-thumb:hover {
    background: #92907b;
}
</style>
