<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/features/notices/GlobalNoticeBanner.vue
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
-->
<!-- Banner global no topo — position fixed acima da topbar, empurra layout via CSS var -->
<script setup>
import { watch, onBeforeUnmount, ref, nextTick } from 'vue';
import { useRouter } from 'vue-router';
import { useNoticeStore } from '@/stores/noticeStore';
import { useTenantStore } from '@/stores/tenantStore';

const noticeStore = useNoticeStore();
const tenantStore = useTenantStore();
const router = useRouter();

const bannerEl = ref(null);
const visible = ref(false);

// ── CSS variable: empurra topbar + layout ─────────────────────

function setHeight(px) {
    document.documentElement.style.setProperty('--notice-banner-height', px + 'px');
}

function measureAndSet() {
    nextTick(() => {
        const h = bannerEl.value?.offsetHeight || 0;
        setHeight(h);
    });
}

// ── Reactive: notice muda → mostra/esconde ───────────────────

watch(
    () => noticeStore.activeNotice,
    (notice) => {
        if (notice) {
            visible.value = true;
            measureAndSet();
            noticeStore.onView(notice);
        } else {
            visible.value = false;
            setHeight(0);
        }
    },
    { immediate: true }
);

// ── Ação CTA ─────────────────────────────────────────────────

async function handleCta(notice) {
    await noticeStore.onCtaClick(notice);

    if (notice.action_type === 'internal' && notice.action_route) {
        router.push(notice.action_route);
    } else if (notice.action_type === 'external' && notice.action_url) {
        const target = notice.link_target || '_blank';
        window.open(notice.action_url, target, 'noopener,noreferrer');
    }
}

// ── Dismiss ──────────────────────────────────────────────────

async function dismiss() {
    await noticeStore.dismiss(noticeStore.activeNotice);
}

// ── Limpa a CSS var ao desmontar ─────────────────────────────

onBeforeUnmount(() => setHeight(0));

// ── Variantes → estilos ──────────────────────────────────────

const VARIANT_STYLES = {
    info: { bg: 'var(--p-blue-600,   #2563eb)', icon: 'pi-info-circle' },
    success: { bg: 'var(--p-green-600,  #16a34a)', icon: 'pi-check-circle' },
    warning: { bg: 'var(--p-amber-500,  #f59e0b)', icon: 'pi-exclamation-triangle' },
    error: { bg: 'var(--p-red-600,    #dc2626)', icon: 'pi-times-circle' }
};

function variantStyle(variant) {
    return VARIANT_STYLES[variant] || VARIANT_STYLES.info;
}

const ALIGN_CLASS = {
    left: 'notice-inner--left',
    center: 'notice-inner--center',
    right: 'notice-inner--right',
    justify: 'notice-inner--justify'
};

function alignClass(align) {
    return ALIGN_CLASS[align] || ALIGN_CLASS.left;
}
</script>

<template>
    <Transition name="notice-slide">
        <div v-if="visible && noticeStore.activeNotice" ref="bannerEl" class="global-notice-banner" :style="{ background: variantStyle(noticeStore.activeNotice.variant).bg }" role="alert" :aria-label="noticeStore.activeNotice.title || 'Aviso'">
            <!-- notice-inner controla só o max-width/padding; o alinhamento fica no notice-group-wrap -->
            <div class="notice-inner" :class="alignClass(noticeStore.activeNotice.content_align)">
                <!-- Grupo alinhável: ícone + texto + cta -->
                <div class="notice-group">
                    <i class="notice-icon pi" :class="variantStyle(noticeStore.activeNotice.variant).icon" aria-hidden="true" />

                    <div class="notice-body">
                        <span v-if="noticeStore.activeNotice.title" class="notice-title">
                            {{ noticeStore.activeNotice.title }}
                        </span>
                        <!-- eslint-disable vue/no-v-html -->
                        <span class="notice-message" v-html="noticeStore.activeNotice.message" />
                    </div>

                    <button v-if="noticeStore.activeNotice.action_type !== 'none' && noticeStore.activeNotice.action_label" class="notice-cta" type="button" @click="handleCta(noticeStore.activeNotice)">
                        {{ noticeStore.activeNotice.action_label }}
                        <i v-if="noticeStore.activeNotice.action_type === 'external'" class="pi pi-external-link notice-cta__ext" />
                    </button>
                </div>

                <!-- Fechar: sempre absoluto no canto direito -->
                <button v-if="noticeStore.activeNotice.dismissible" class="notice-close" type="button" aria-label="Fechar aviso" @click="dismiss">
                    <i class="pi pi-times" />
                </button>
            </div>
        </div>
    </Transition>
</template>

<style scoped>
.global-notice-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 101; /* acima da topbar (z-index 100) */
    min-height: 44px;
    display: flex;
    align-items: stretch;
}

.notice-inner {
    position: relative; /* âncora do botão fechar absoluto */
    width: 100%;
    max-width: 1400px;
    margin: 0 auto;
    padding: 0 2.5rem 0 1rem; /* padding-right reserva espaço pro fechar */
    display: flex;
    align-items: center;
    min-height: 44px;
}

/* ── Grupo alinhável (ícone + texto + cta) ───────────────── */
.notice-group {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    padding: 6px 0;
}

/* ── Alinhamento: muda só o .notice-group dentro do .notice-inner ── */
.notice-inner--left {
    justify-content: flex-start;
}
.notice-inner--center {
    justify-content: center;
}
.notice-inner--right {
    justify-content: flex-end;
}
.notice-inner--justify {
    justify-content: flex-start;
}

/* justify: grupo expande para preencher toda a largura */
.notice-inner--justify .notice-group {
    flex: 1;
}
.notice-inner--justify .notice-body {
    flex: 1;
}

/* ── Ícone ───────────────────────────────────────────────── */
.notice-icon {
    font-size: 1rem;
    color: rgba(255, 255, 255, 0.92);
    flex-shrink: 0;
}

/* ── Corpo de texto ──────────────────────────────────────── */
.notice-body {
    min-width: 0;
    display: flex;
    align-items: baseline;
    gap: 0.45rem;
    flex-wrap: wrap;
    font-size: 0.85rem;
    color: #fff;
    line-height: 1.45;
}

.notice-title {
    font-weight: 700;
    white-space: nowrap;
}

.notice-message {
    opacity: 0.92;
}

/* Links dentro do HTML do message */
.notice-message :deep(a) {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* ── CTA button ──────────────────────────────────────────── */
.notice-cta {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 14px;
    border-radius: 6px;
    border: 1.5px solid rgba(255, 255, 255, 0.55);
    background: rgba(255, 255, 255, 0.15);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition:
        background 0.15s,
        border-color 0.15s;
    flex-shrink: 0;
}

.notice-cta:hover {
    background: rgba(255, 255, 255, 0.28);
    border-color: rgba(255, 255, 255, 0.8);
}

.notice-cta__ext {
    font-size: 0.65rem;
    opacity: 0.8;
}

/* ── Fechar: sempre ancorado no canto direito ────────────── */
.notice-close {
    position: absolute;
    right: 0.5rem;
    top: 50%;
    transform: translateY(-50%);
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: none;
    background: transparent;
    color: rgba(255, 255, 255, 0.75);
    display: grid;
    place-items: center;
    cursor: pointer;
    font-size: 0.8rem;
    transition:
        background 0.15s,
        color 0.15s;
}

.notice-close:hover {
    background: rgba(255, 255, 255, 0.2);
    color: #fff;
}

/* ── Transição slide-down ────────────────────────────────── */
.notice-slide-enter-active {
    transition:
        transform 0.28s cubic-bezier(0.22, 1, 0.36, 1),
        opacity 0.22s ease;
}
.notice-slide-leave-active {
    transition:
        transform 0.22s ease,
        opacity 0.2s ease;
}
.notice-slide-enter-from,
.notice-slide-leave-to {
    transform: translateY(-100%);
    opacity: 0;
}

/* ── Dark mode: sem mudança — cores via variante ─────────── */
</style>
