<script setup lang="ts">
/**
 * Тело панели деталей сделки (hero + параметры + комментарий + timeline).
 * Извлечено из DealDetailDrawer (редизайн 2026-05-17) — общее тело
 * для overlay-дровера (Канбан) и inline-панели master-detail («Сделки»).
 *
 * Backend: GET /api/deals/{id}, PATCH /api/deals/{id}, GET /api/deals/{id}/events.
 */
import { computed, ref, watch } from 'vue';
import type { MockDeal } from '../../composables/mockDeals';
import { type DealEvent } from '../../composables/mockDealEvents';
import { mapApiDealEvent } from '../../composables/dealsApiMapper';
import { stripChannelPrefix } from '../../composables/projectName';
import * as dealsApi from '../../api/deals';
import { useLeadStatusesStore } from '../../stores/leadStatuses';
import DealDetailHero from './DealDetailHero.vue';
import DealDetailTimeline from './DealDetailTimeline.vue';

const leadStatusesStore = useLeadStatusesStore();

const props = defineProps<{
    deal: MockDeal | null;
    tenantId?: number;
}>();

const emit = defineEmits<{
    close: [];
    // 18.05.2026 ux: статус меняется через inline picker в Hero.
    // Эмитим slug наверх — parent (DealDetailDrawer → DealsView/KanbanView)
    // делает optimistic update + API call + rollback.
    'status-changed': [slug: string];
}>();

const status = computed(() => {
    if (!props.deal) return null;
    return leadStatusesStore.findBySlug(props.deal.statusSlug);
});

function formatCost(cost: number): string {
    return new Intl.NumberFormat('ru-RU').format(cost) + ' ₽';
}

// Drawer-«легенда» (18.05.2026 ux): Тип + Источник проекта (read-only).
// Редактирование — только в карточке проекта на /projects (см. план Task 5).
const TYPE_LABELS: Record<string, string> = { site: 'Сайт', call: 'Звонок', sms: 'СМС' };
const projectTypeLabel = computed((): string => {
    const t = props.deal?.projectSignalType;
    return t ? (TYPE_LABELS[t] ?? '—') : '—';
});
const projectSourceLabel = computed((): string => {
    if (!props.deal) return '—';
    const t = props.deal.projectSignalType;
    if (t === 'site' || t === 'call') return props.deal.projectSignalIdentifier ?? '—';
    if (t === 'sms') {
        const sender = props.deal.projectSmsSenders?.[0] ?? '';
        const kw = props.deal.projectSmsKeyword;
        if (sender && kw) return `${sender} (${kw})`;
        return sender || '—';
    }
    return '—';
});

const events = ref<DealEvent[]>([]);
const eventsLoading = ref(false);
const eventsFetchError = ref(false);

const commentDraft = ref<string>('');
const commentSaving = ref(false);
const commentSaveError = ref(false);
const commentToastOpen = ref(false);
const commentToastText = ref('');

async function loadEvents() {
    if (!props.deal || !props.tenantId) {
        events.value = [];
        commentDraft.value = '';
        return;
    }
    eventsLoading.value = true;
    eventsFetchError.value = false;
    try {
        const res = await dealsApi.getDeal(props.deal.id, props.tenantId);
        events.value = res.events.map((e) =>
            mapApiDealEvent(e, new Date(), (slug) => leadStatusesStore.findBySlug(slug)?.nameRu ?? slug),
        );
        commentDraft.value = res.deal.comment ?? '';
    } catch {
        eventsFetchError.value = true;
        events.value = [];
        commentDraft.value = '';
    } finally {
        eventsLoading.value = false;
    }
}

function onStatusChange(slug: string): void {
    if (!props.deal) return;
    if (props.deal.statusSlug === slug) return;
    emit('status-changed', slug);
}

async function saveComment() {
    if (!props.deal || !props.tenantId) return;
    commentSaving.value = true;
    commentSaveError.value = false;
    try {
        await dealsApi.updateDeal(props.deal.id, {
            tenant_id: props.tenantId,
            comment: commentDraft.value || null,
        });
        commentToastText.value = 'Комментарий сохранён.';
        commentToastOpen.value = true;
        await loadEvents();
    } catch {
        commentSaveError.value = true;
        commentToastText.value = 'Не удалось сохранить — попробуйте позже.';
        commentToastOpen.value = true;
    } finally {
        commentSaving.value = false;
    }
}

// Загрузка при появлении/смене сделки. Компонент смонтирован всегда — тело (<div v-if="deal">) рендерится только при deal != null.
watch(
    () => [props.deal?.id, props.tenantId] as const,
    () => {
        if (props.deal) {
            loadEvents();
        }
    },
    { immediate: true },
);

defineExpose({
    events,
    eventsLoading,
    eventsFetchError,
    loadEvents,
    commentDraft,
    commentSaving,
    commentSaveError,
    commentToastOpen,
    commentToastText,
    saveComment,
});
</script>

<template>
    <div v-if="deal" class="drawer-content">
        <DealDetailHero
            :deal="deal"
            :status="status"
            :all-statuses="leadStatusesStore.statuses"
            @close="emit('close')"
            @change-status="onStatusChange"
        />

        <v-divider />

        <section class="section pa-5">
            <h3 class="section-title text-subtitle-2 mb-3">Параметры</h3>
            <dl class="params">
                <div class="param">
                    <dt class="text-caption text-medium-emphasis">Проект</dt>
                    <dd class="text-body-2">{{ stripChannelPrefix(deal.project) }}</dd>
                </div>
                <div class="param">
                    <dt class="text-caption text-medium-emphasis">Стоимость лида</dt>
                    <dd class="text-body-2 num">{{ deal.costKopecks != null ? formatCost(deal.costKopecks / 100) : '—' }}</dd>
                </div>
                <div class="param">
                    <dt class="text-caption text-medium-emphasis">Тип</dt>
                    <dd class="text-body-2">{{ projectTypeLabel }}</dd>
                </div>
                <div class="param">
                    <dt class="text-caption text-medium-emphasis">Источник</dt>
                    <dd class="text-body-2">{{ projectSourceLabel }}</dd>
                </div>
                <div class="param">
                    <dt class="text-caption text-medium-emphasis">Город</dt>
                    <dd class="text-body-2">{{ deal.city || '—' }}</dd>
                </div>
            </dl>
        </section>

        <v-divider />

        <section v-if="tenantId" class="section pa-5" data-testid="comment-section">
            <h3 class="section-title text-subtitle-2 mb-3">Комментарий</h3>
            <v-textarea
                v-model="commentDraft"
                placeholder="Заметка менеджера…"
                variant="outlined"
                density="comfortable"
                auto-grow
                rows="3"
                hide-details
                counter="5000"
                data-testid="comment-textarea"
            />
            <div class="d-flex ga-2 mt-2 justify-end">
                <v-btn
                    :loading="commentSaving"
                    color="primary"
                    size="small"
                    prepend-icon="mdi-content-save-outline"
                    data-testid="save-comment-btn"
                    @click="saveComment"
                >
                    Сохранить
                </v-btn>
            </div>
        </section>

        <DealDetailTimeline :events="events" :events-fetch-error="eventsFetchError" />

        <v-snackbar
            v-model="commentToastOpen"
            :timeout="3000"
            :color="commentSaveError ? 'warning' : undefined"
            data-testid="comment-toast"
            location="bottom right"
        >
            {{ commentToastText }}
        </v-snackbar>

    </div>
</template>

<style scoped>
.drawer-content {
    display: flex;
    flex-direction: column;
}
.section-title {
    font-weight: 600;
    color: #081319;
}
.params {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px 12px;
    margin: 0;
}
.param dt {
    font-size: 11px;
    margin-bottom: 2px;
}
.param dd {
    margin: 0;
    color: #081319;
}
.param .link {
    color: #0f6e56;
    cursor: pointer;
}
.param .link:hover {
    text-decoration: underline;
}
.num {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-feature-settings: 'tnum';
}

</style>
