<script setup lang="ts">
/**
 * Админка SaaS → Реклама: расход и маржа по тенантам.
 *
 * Сколько тенанты тратят на рекламу (client_spend), сколько из этого мы
 * платим Яндексу за закупку (yandex_cost) и что остаётся нам маржой
 * (our_margin). Источник данных: GET /api/admin/advertising/spend.
 */
import { computed, onMounted, reactive, ref, watch } from 'vue';
import * as adminApi from '../../api/admin';
import type { AdminAwaitingCampaign, AdvertisingSpendPeriod } from '../../api/admin';
import { extractErrorMessage } from '../../api/client';
import { formatPlain } from '../../composables/billingFormatters';

type SpendRow = {
    tenant_id: number;
    tenant_name: string;
    client_spend_rub: number;
    yandex_cost_rub: number;
    our_margin_rub: number;
};

const periodOptions: { value: AdvertisingSpendPeriod; label: string }[] = [
    { value: 'current_month', label: 'Текущий месяц' },
    { value: 'last_month', label: 'Прошлый месяц' },
    { value: '90d', label: '90 дней' },
    { value: 'all', label: 'Всё время' },
];

const period = ref<AdvertisingSpendPeriod>('current_month');
const rows = reactive<SpendRow[]>([]);
const totals = reactive({
    client_spend_rub: 0,
    yandex_cost_rub: 0,
    our_margin_rub: 0,
});
const adMarginPercent = ref('');
const loading = ref(false);
const fetchError = ref(false);
const errorMessage = ref('');

const cpm = ref('');
const margin = ref('');
const cpmSaving = ref(false);
const cpmSaved = ref(false);
const cpmError = ref('');

async function loadCpm() {
    try {
        const res = await adminApi.fetchAdSettings();
        cpm.value = res.client_cpm_rub;
        margin.value = res.ad_margin_percent;
    } catch (e) {
        cpmError.value = extractErrorMessage(e);
    }
}

async function saveCpm() {
    cpmSaving.value = true;
    cpmError.value = '';
    cpmSaved.value = false;
    try {
        await adminApi.updateAdSettings({ client_cpm_rub: cpm.value, ad_margin_percent: margin.value });
        cpmSaved.value = true;
    } catch (e) {
        cpmError.value = extractErrorMessage(e);
    } finally {
        cpmSaving.value = false;
    }
}

async function loadSpend() {
    loading.value = true;
    fetchError.value = false;
    errorMessage.value = '';
    try {
        const res = await adminApi.fetchAdvertisingSpend(period.value);
        const mapped: SpendRow[] = res.data.map((r) => ({
            tenant_id: r.tenant_id,
            tenant_name: r.tenant_name,
            client_spend_rub: parseFloat(r.client_spend_rub),
            yandex_cost_rub: parseFloat(r.yandex_cost_rub),
            our_margin_rub: parseFloat(r.our_margin_rub),
        }));
        rows.splice(0, rows.length, ...mapped);
        totals.client_spend_rub = parseFloat(res.totals.client_spend_rub);
        totals.yandex_cost_rub = parseFloat(res.totals.yandex_cost_rub);
        totals.our_margin_rub = parseFloat(res.totals.our_margin_rub);
        adMarginPercent.value = res.ad_margin_percent;
    } catch (e) {
        fetchError.value = true;
        errorMessage.value = extractErrorMessage(e);
    } finally {
        loading.value = false;
    }
}

onMounted(loadSpend);
onMounted(loadCpm);
watch(period, loadSpend);

const isEmpty = computed(() => !loading.value && !fetchError.value && rows.length === 0);

// === Кампании, ждущие номер креатива Яндекса (8e) ===

const awaitingCampaigns = reactive<AdminAwaitingCampaign[]>([]);
const awaitingLoading = ref(false);
const awaitingError = ref('');
/** Ввод «номер креатива» построчно, id кампании → строка из поля. */
const creativeInputs = reactive<Record<number, string>>({});
const creativeSaving = reactive<Record<number, boolean>>({});
const creativeSaved = reactive<Record<number, boolean>>({});
const creativeErrors = reactive<Record<number, string>>({});

const awaitingIsEmpty = computed(() => !awaitingLoading.value && awaitingCampaigns.length === 0);

async function loadAwaiting() {
    awaitingLoading.value = true;
    awaitingError.value = '';
    try {
        const list = await adminApi.fetchAdAwaitingCampaigns();
        awaitingCampaigns.splice(0, awaitingCampaigns.length, ...list);
        for (const c of list) {
            creativeInputs[c.id] = c.yandex_creative_id !== null ? String(c.yandex_creative_id) : '';
        }
    } catch (e) {
        awaitingError.value = extractErrorMessage(e);
    } finally {
        awaitingLoading.value = false;
    }
}

async function saveCreative(campaignId: number) {
    creativeSaving[campaignId] = true;
    creativeSaved[campaignId] = false;
    creativeErrors[campaignId] = '';
    try {
        const value = Number(creativeInputs[campaignId]);
        const res = await adminApi.setAdCampaignCreative(campaignId, value);
        const row = awaitingCampaigns.find((c) => c.id === campaignId);
        if (row) row.yandex_creative_id = res.yandex_creative_id;
        creativeSaved[campaignId] = true;
    } catch (e) {
        creativeErrors[campaignId] = extractErrorMessage(e);
    } finally {
        creativeSaving[campaignId] = false;
    }
}

onMounted(loadAwaiting);

defineExpose({
    rows,
    totals,
    adMarginPercent,
    loading,
    fetchError,
    errorMessage,
    period,
    loadSpend,
    cpm,
    margin,
    cpmSaving,
    cpmSaved,
    cpmError,
    saveCpm,
    loadCpm,
    awaitingCampaigns,
    awaitingLoading,
    awaitingError,
    creativeInputs,
    creativeSaving,
    creativeSaved,
    creativeErrors,
    loadAwaiting,
    saveCreative,
});
</script>

<template>
    <v-container fluid class="admin-advertising pa-6" data-testid="admin-advertising-view">
        <header class="page-head mb-4 d-flex justify-space-between align-start flex-wrap ga-4">
            <div>
                <h1 class="text-h4 page-title">Реклама — расход и маржа</h1>
                <p class="text-body-2 text-medium-emphasis ma-0">
                    Сколько тенанты тратят на рекламу и сколько из этого остаётся нам маржой.
                </p>
            </div>
            <v-btn
                variant="outlined"
                prepend-icon="mdi-refresh"
                :loading="loading"
                data-testid="reload-btn"
                @click="loadSpend"
            >
                Обновить
            </v-btn>
        </header>

        <v-card variant="outlined" class="pa-4 mb-4" data-testid="ad-cpm-card">
            <div class="text-h6 mb-1">Цена клиенту за показы</div>
            <p class="text-caption text-medium-emphasis mb-3">Сколько клиент платит за 1000 показов, ₽</p>
            <div class="d-flex align-center flex-wrap ga-3">
                <v-text-field
                    v-model="cpm"
                    type="number"
                    min="0"
                    density="comfortable"
                    variant="outlined"
                    hide-details
                    style="max-width: 200px"
                    class="font-mono tabular"
                    data-testid="ad-cpm-input"
                />
                <v-text-field
                    v-model="margin"
                    type="number"
                    min="0"
                    max="90"
                    density="comfortable"
                    variant="outlined"
                    label="Наша наценка, %"
                    hint="В Директ уходит на столько меньше. Клиент не видит."
                    persistent-hint
                    style="max-width: 240px"
                    class="font-mono tabular"
                    data-testid="ad-margin-input"
                />
                <v-btn
                    color="primary"
                    :loading="cpmSaving"
                    data-testid="ad-cpm-save"
                    @click="saveCpm"
                >
                    Сохранить
                </v-btn>
                <span v-if="cpmSaved" class="text-success-strong text-body-2" data-testid="ad-cpm-saved">
                    Цена сохранена
                </span>
                <span v-if="cpmError" class="text-error text-body-2" data-testid="ad-cpm-error">
                    {{ cpmError }}
                </span>
            </div>
        </v-card>

        <v-btn-toggle
            v-model="period"
            mandatory
            density="comfortable"
            color="primary"
            variant="outlined"
            class="mb-4"
            data-testid="ad-spend-period"
        >
            <v-btn
                v-for="opt in periodOptions"
                :key="opt.value"
                :value="opt.value"
                :data-testid="`period-${opt.value}`"
            >
                {{ opt.label }}
            </v-btn>
        </v-btn-toggle>

        <v-alert
            v-if="fetchError"
            type="warning"
            variant="tonal"
            density="compact"
            closable
            class="mb-4"
            data-testid="fetch-error-alert"
        >
            {{ errorMessage || 'Не удалось загрузить расход на рекламу. Попробуйте обновить.' }}
        </v-alert>

        <!-- ИТОГО-строка -->
        <v-row class="mb-4" data-testid="ad-spend-totals">
            <v-col cols="12" sm="4">
                <v-card variant="outlined" class="pa-3">
                    <div class="text-caption text-medium-emphasis">Расход клиентов</div>
                    <div class="text-h6 font-mono tabular" data-testid="ad-spend-total-client">
                        {{ formatPlain(totals.client_spend_rub) }}
                    </div>
                </v-card>
            </v-col>
            <v-col cols="12" sm="4">
                <v-card variant="outlined" class="pa-3">
                    <div class="text-caption text-medium-emphasis">Расход у Яндекса</div>
                    <div class="text-h6 font-mono tabular" data-testid="ad-spend-total-yandex">
                        {{ formatPlain(totals.yandex_cost_rub) }}
                    </div>
                </v-card>
            </v-col>
            <v-col cols="12" sm="4">
                <v-card variant="outlined" class="pa-3">
                    <div class="text-caption text-medium-emphasis">Наша маржа</div>
                    <div class="text-h6 font-mono tabular text-success-strong" data-testid="ad-spend-total-margin">
                        {{ formatPlain(totals.our_margin_rub) }}
                    </div>
                </v-card>
            </v-col>
        </v-row>

        <v-card variant="outlined" class="pa-4">
            <div class="d-flex justify-space-between align-center mb-3">
                <h2 class="text-h6 ma-0">По тенантам</h2>
                <span class="text-caption text-medium-emphasis" data-testid="ad-spend-markup">
                    Наценка: {{ adMarginPercent }}%
                </span>
            </div>

            <div v-if="loading" class="d-flex justify-center pa-8">
                <v-progress-circular indeterminate color="primary" data-testid="ad-spend-loading" />
            </div>

            <p v-else-if="isEmpty" class="text-body-2 text-medium-emphasis ma-0 pa-4" data-testid="ad-spend-empty">
                За период рекламных расходов нет.
            </p>

            <v-table v-else density="comfortable" class="font-mono-nums">
                <thead>
                    <tr>
                        <th>Тенант</th>
                        <th class="text-right">Расход клиента</th>
                        <th class="text-right">Расход Яндекса</th>
                        <th class="text-right">Наша маржа</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="row in rows" :key="row.tenant_id" data-testid="ad-spend-row">
                        <td class="font-weight-medium">{{ row.tenant_name }}</td>
                        <td class="text-right font-mono tabular">{{ formatPlain(row.client_spend_rub) }}</td>
                        <td class="text-right font-mono tabular">{{ formatPlain(row.yandex_cost_rub) }}</td>
                        <td class="text-right font-mono tabular text-success-strong">
                            {{ formatPlain(row.our_margin_rub) }}
                        </td>
                    </tr>
                </tbody>
            </v-table>
        </v-card>

        <v-card variant="outlined" class="pa-4 mt-4" data-testid="ad-awaiting-card">
            <div class="text-h6 mb-1">Кампании на запуск — номер креатива</div>
            <p class="text-caption text-medium-emphasis mb-3">
                Оформите креатив в конструкторе Яндекса и впишите его номер, чтобы кампанию можно было запустить.
            </p>

            <v-alert
                v-if="awaitingError"
                type="warning"
                variant="tonal"
                density="compact"
                closable
                class="mb-4"
                data-testid="ad-awaiting-fetch-error"
            >
                {{ awaitingError }}
            </v-alert>

            <div v-if="awaitingLoading" class="d-flex justify-center pa-8">
                <v-progress-circular indeterminate color="primary" data-testid="ad-awaiting-loading" />
            </div>

            <p
                v-else-if="awaitingIsEmpty"
                class="text-body-2 text-medium-emphasis ma-0 pa-4"
                data-testid="ad-awaiting-empty"
            >
                Кампаний, ждущих номер креатива, нет.
            </p>

            <v-table v-else density="comfortable">
                <thead>
                    <tr>
                        <th>Тенант</th>
                        <th>Кампания</th>
                        <th class="text-right">Смета показов</th>
                        <th>Ссылка</th>
                        <th>Номер креатива</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="c in awaitingCampaigns" :key="c.id" data-testid="ad-awaiting-row">
                        <td class="font-weight-medium">{{ c.tenant_name }}</td>
                        <td>{{ c.name }}</td>
                        <td class="text-right font-mono tabular">
                            {{ c.estimated_impressions !== null ? c.estimated_impressions : '—' }}
                        </td>
                        <td>
                            <a v-if="c.landing_url" :href="c.landing_url" target="_blank" rel="noopener">{{
                                c.landing_url
                            }}</a>
                            <span v-else>—</span>
                        </td>
                        <td>
                            <v-text-field
                                v-model="creativeInputs[c.id]"
                                type="number"
                                min="1"
                                density="comfortable"
                                variant="outlined"
                                hide-details
                                style="max-width: 200px"
                                class="font-mono tabular"
                                data-testid="ad-creative-input"
                            />
                        </td>
                        <td>
                            <v-btn
                                color="primary"
                                size="small"
                                :loading="creativeSaving[c.id]"
                                data-testid="ad-creative-save"
                                @click="saveCreative(c.id)"
                            >
                                Сохранить
                            </v-btn>
                            <div
                                v-if="creativeSaved[c.id]"
                                class="text-success-strong text-body-2"
                                data-testid="ad-creative-saved"
                            >
                                Сохранено
                            </div>
                            <div
                                v-if="creativeErrors[c.id]"
                                class="text-error text-body-2"
                                data-testid="ad-creative-error"
                            >
                                {{ creativeErrors[c.id] }}
                            </div>
                        </td>
                    </tr>
                </tbody>
            </v-table>
        </v-card>
    </v-container>
</template>

<style scoped>
.admin-advertising {
    max-width: 1400px;
}
.page-title {
    font-variation-settings: 'opsz' 28;
    letter-spacing: -0.018em;
}
.font-mono {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
}
.tabular {
    font-feature-settings: 'tnum';
}
</style>
