<template>
    <div class="projects-view" :class="{ 'has-drawer': singleSelectedProject !== null }">
        <div class="d-flex justify-space-between align-center mb-4">
            <h1 class="text-h4">Проекты</h1>
            <v-btn color="primary" prepend-icon="mdi-plus" @click="openCreate">+ Создать проект</v-btn>
        </div>

        <div class="d-flex gap-3 mb-4">
            <v-select
                v-model="store.filters.signal_type"
                :items="typeFilters"
                label="Тип"
                clearable
                density="comfortable"
                style="max-width: 180px"
                hide-details
                @update:model-value="store.fetch()"
            />
            <v-select
                v-model="store.filters.status"
                :items="statusFilters"
                label="Статус"
                clearable
                density="comfortable"
                style="max-width: 180px"
                hide-details
                @update:model-value="store.fetch()"
            />
            <v-text-field
                v-model="store.filters.search"
                label="Поиск"
                prepend-inner-icon="mdi-magnify"
                density="comfortable"
                hide-details
                style="max-width: 240px"
                @input="onSearchDebounced"
            />
        </div>

        <div v-if="!store.loading && store.items.length > 0" class="projects-toolbar d-flex align-center gap-3 mb-3">
            <label class="toolbar-check" data-testid="select-all-toggle">
                <input
                    type="checkbox"
                    aria-label="Выбрать все проекты по текущим фильтрам"
                    :checked="store.selectAllByFilter"
                    @change="(e) => onToggleSelectAll((e.target as HTMLInputElement).checked)"
                />
                <span
                    class="toolbar-check__box"
                    :class="{ 'toolbar-check__box--partial': !store.selectAllByFilter && store.selectedIds.size > 0 }"
                />
            </label>
            <span class="text-body-2"
                >Выбрано: {{ store.selectedIds.size }} из {{ store.total }} (по текущим фильтрам)</span
            >
        </div>

        <div v-if="store.loading" class="text-center py-8">
            <v-progress-circular indeterminate color="primary" />
        </div>
        <div v-else-if="store.items.length === 0" class="text-center py-12 text-medium-emphasis">
            Нет проектов. Создайте первый — кнопка справа сверху.
        </div>
        <div v-else class="projects-grid">
            <ProjectCard
                v-for="project in store.items"
                :key="project.id"
                :project="project"
                :selected="store.selectedIds.has(project.id)"
                @toggle-select="store.toggleSelect"
                @edit="openEdit"
                @toggle-active="store.toggleActive"
                @sync-now="(p: Project) => store.syncNow(p.id)"
                @archive="(p: Project) => store.archive(p.id)"
            />
        </div>

        <BulkActionsBar v-if="store.selectedIds.size >= 2" />

        <ProjectDetailsDrawer
            :project="singleSelectedProject"
            @close="onDrawerClose"
            @saved="onDrawerSaved"
        />
        <NewProjectDialog v-model="createOpen" mode="create" @saved="store.fetch()" />
        <EditProjectDialog v-model="editOpen" :project="editing" @saved="store.fetch()" />
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, computed } from 'vue';
import { useProjectsStore, type Project } from '../stores/projectsStore';
import ProjectCard from '../components/projects/ProjectCard.vue';
import ProjectDetailsDrawer from '../components/projects/ProjectDetailsDrawer.vue';
import BulkActionsBar from '../components/projects/BulkActionsBar.vue';
import NewProjectDialog from './projects/NewProjectDialog.vue';
import EditProjectDialog from './projects/EditProjectDialog.vue';

const store = useProjectsStore();
const createOpen = ref(false);
const editOpen = ref(false);
const editing = ref<Project | null>(null);

const singleSelectedProject = computed<Project | null>(() => {
    if (store.selectedIds.size !== 1) return null;
    const [id] = store.selectedIds;
    return store.items.find((p: Project) => p.id === id) ?? null;
});

function onDrawerClose(): void {
    store.clearSelection();
}
function onDrawerSaved(): void {
    void store.fetch();
}

const typeFilters = [
    { title: 'Сайт', value: 'site' },
    { title: 'Звонок', value: 'call' },
    { title: 'СМС', value: 'sms' },
];

const statusFilters = [
    { title: 'Активные', value: 'active' },
    { title: 'На паузе', value: 'paused' },
    { title: 'Архивные', value: 'archived' },
];

let searchTimer: ReturnType<typeof setTimeout> | null = null;
function onSearchDebounced() {
    if (searchTimer) clearTimeout(searchTimer);
    searchTimer = setTimeout(() => store.fetch(), 300);
}

function openCreate() {
    createOpen.value = true;
}
function openEdit(project: Project) {
    editing.value = project;
    editOpen.value = true;
}

function onToggleSelectAll(value: boolean | null) {
    if (value) {
        store.selectAllByFilter = true;
        store.items.forEach((p: Project) => store.selectedIds.add(p.id));
    } else {
        store.selectAllByFilter = false;
        store.clearSelection();
    }
}

watch(
    () => store.pendingIds.size,
    (size) => {
        if (size > 0) store.startPolling();
    },
);

onMounted(store.fetch);
onUnmounted(() => store.stopPolling());
</script>

<style scoped>
.projects-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 16px;
}
/* Workaround: MDI-шрифт не подключён в проекте (Диз-4),
   `<i class="mdi-close-circle">` рендерится пустым. Подменяем глиф на Unicode `✕`
   и показываем только когда поле имеет значение (Vuetify ставит `.v-field--dirty`). */
.projects-view :deep(.v-field__clearable) {
    position: relative;
}
.projects-view :deep(.v-field__clearable .v-icon) {
    color: transparent;
    width: 20px;
    height: 20px;
}
.projects-view :deep(.v-field--dirty .v-field__clearable)::after {
    content: '✕';
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(1, 32, 25, 0.55);
    font-size: 14px;
    font-family: 'Inter', system-ui, sans-serif;
    pointer-events: none;
    transition: color 150ms ease;
}
.projects-view :deep(.v-field--dirty .v-field__clearable:hover)::after {
    color: var(--liderra-noir, #012019);
}
.toolbar-check {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    padding: 4px;
}
.toolbar-check input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.toolbar-check__box {
    width: 20px;
    height: 20px;
    border: 2px solid var(--liderra-noir);
    border-radius: 4px;
    background: #fff;
    display: inline-block;
    position: relative;
    transition: background 150ms ease;
}
.toolbar-check input:checked + .toolbar-check__box {
    background: var(--liderra-teal, #0f6e56);
    border-color: var(--liderra-teal, #0f6e56);
}
.toolbar-check input:checked + .toolbar-check__box::after {
    content: '';
    position: absolute;
    left: 5px;
    top: 1px;
    width: 6px;
    height: 11px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
.toolbar-check__box--partial {
    background: var(--liderra-teal, #0f6e56);
    border-color: var(--liderra-teal, #0f6e56);
}
.toolbar-check__box--partial::after {
    content: '';
    position: absolute;
    left: 3px;
    top: 7px;
    width: 10px;
    height: 2px;
    background: #fff;
}
.projects-view {
    transition: padding-right 240ms cubic-bezier(0.16, 1, 0.3, 1);
}
.projects-view.has-drawer {
    padding-right: 480px;
}
</style>
