<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/views/pages/saas/SaasLoginCarousel.vue
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
-->
<script setup>
import { ref, computed, onMounted } from 'vue'
import { supabase } from '@/lib/supabase/client'
import { useToast } from 'primevue/usetoast'
import { useConfirm } from 'primevue/useconfirm'
import Editor from 'primevue/editor'

const toast   = useToast()
const confirm = useConfirm()

// ─── Estado ───────────────────────────────────────────────────────────────────
const slides       = ref([])
const loading      = ref(false)
const saving       = ref(false)
const previewIdx   = ref(0)

const dialogOpen   = ref(false)
const editingSlide = ref(null)   // null = novo

const form = ref({ title: '', body: '', icon: '', ordem: 0, ativo: true })

// ─── Ícones disponíveis (subset PrimeIcons relevantes) ────────────────────────
const ICONS = [
  { value: 'pi-calendar-clock',   label: 'Agenda'        },
  { value: 'pi-users',            label: 'Equipe'        },
  { value: 'pi-globe',            label: 'Online'        },
  { value: 'pi-shield',           label: 'Segurança'     },
  { value: 'pi-heart-fill',       label: 'Saúde'         },
  { value: 'pi-chart-line',       label: 'Estatísticas'  },
  { value: 'pi-bell',             label: 'Notificações'  },
  { value: 'pi-lock',             label: 'Privacidade'   },
  { value: 'pi-mobile',           label: 'Mobile'        },
  { value: 'pi-sync',             label: 'Sincronização' },
  { value: 'pi-star',             label: 'Destaque'      },
  { value: 'pi-check-circle',     label: 'Aprovação'     },
  { value: 'pi-comments',         label: 'Comunicação'   },
  { value: 'pi-file-edit',        label: 'Prontuário'    },
  { value: 'pi-briefcase',        label: 'Profissional'  },
  { value: 'pi-bolt',             label: 'Performance'   },
]

// ─── Computed ─────────────────────────────────────────────────────────────────
const slidesAtivos = computed(() => slides.value.filter(s => s.ativo).sort((a, b) => a.ordem - b.ordem))
const previewSlide = computed(() => slidesAtivos.value[previewIdx.value] ?? slidesAtivos.value[0] ?? null)

// ─── Supabase ─────────────────────────────────────────────────────────────────
async function load () {
  loading.value = true
  try {
    const { data, error } = await supabase
      .from('login_carousel_slides')
      .select('*')
      .order('ordem', { ascending: true })
    if (error) throw error
    slides.value = data || []
  } catch (e) {
    toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'Falha ao carregar slides.', life: 4000 })
  } finally {
    loading.value = false
  }
}

function stripHtml (s) {
  return String(s || '').replace(/<[^>]+>/g, '').trim()
}

async function saveSlide () {
  if (!stripHtml(form.value.title) || !stripHtml(form.value.body)) {
    toast.add({ severity: 'warn', summary: 'Atenção', detail: 'Título e conteúdo são obrigatórios.', life: 3000 })
    return
  }
  saving.value = true
  try {
    const payload = {
      title: form.value.title,
      body:  form.value.body,
      icon:  form.value.icon || 'pi-star',
      ordem: form.value.ordem,
      ativo: form.value.ativo,
    }
    if (editingSlide.value) {
      const { error } = await supabase
        .from('login_carousel_slides')
        .update(payload)
        .eq('id', editingSlide.value.id)
      if (error) throw error
      toast.add({ severity: 'success', summary: 'Salvo', detail: 'Slide atualizado com sucesso.', life: 3000 })
    } else {
      const maxOrdem = slides.value.length ? Math.max(...slides.value.map(s => s.ordem)) + 1 : 0
      payload.ordem = maxOrdem
      const { error } = await supabase
        .from('login_carousel_slides')
        .insert(payload)
      if (error) throw error
      toast.add({ severity: 'success', summary: 'Criado', detail: 'Slide adicionado com sucesso.', life: 3000 })
    }
    dialogOpen.value = false
    await load()
    previewIdx.value = 0
  } catch (e) {
    toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'Falha ao salvar.', life: 4000 })
  } finally {
    saving.value = false
  }
}

async function toggleAtivo (slide) {
  try {
    const { error } = await supabase
      .from('login_carousel_slides')
      .update({ ativo: !slide.ativo })
      .eq('id', slide.id)
    if (error) throw error
    slide.ativo = !slide.ativo
    toast.add({ severity: 'info', summary: slide.ativo ? 'Ativado' : 'Desativado', detail: `"${slide.title}"`, life: 2500 })
  } catch (e) {
    toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3000 })
  }
}

async function deleteSlide (slide) {
  confirm.require({
    message: `Remover o slide "${slide.title}"? Esta ação não pode ser desfeita.`,
    header: 'Confirmar remoção',
    icon: 'pi pi-exclamation-triangle',
    acceptClass: 'p-button-danger',
    acceptLabel: 'Remover',
    rejectLabel: 'Cancelar',
    accept: async () => {
      try {
        const { error } = await supabase.from('login_carousel_slides').delete().eq('id', slide.id)
        if (error) throw error
        toast.add({ severity: 'success', summary: 'Removido', detail: `Slide removido.`, life: 2500 })
        await load()
        previewIdx.value = 0
      } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3000 })
      }
    },
  })
}

async function moveSlide (slide, dir) {
  const sorted = [...slides.value].sort((a, b) => a.ordem - b.ordem)
  const idx = sorted.findIndex(s => s.id === slide.id)
  const swapIdx = idx + dir
  if (swapIdx < 0 || swapIdx >= sorted.length) return

  const a = sorted[idx]
  const b = sorted[swapIdx]
  const tempOrdem = a.ordem

  try {
    await supabase.from('login_carousel_slides').update({ ordem: b.ordem }).eq('id', a.id)
    await supabase.from('login_carousel_slides').update({ ordem: tempOrdem }).eq('id', b.id)
    await load()
  } catch (e) {
    toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3000 })
  }
}

// ─── Dialog helpers ───────────────────────────────────────────────────────────
function openNew () {
  editingSlide.value = null
  form.value = { title: '', body: '', icon: 'pi-calendar-clock', ordem: 0, ativo: true }
  dialogOpen.value = true
}

function openEdit (slide) {
  editingSlide.value = slide
  form.value = { title: slide.title, body: slide.body, icon: slide.icon || 'pi-star', ordem: slide.ordem, ativo: slide.ativo }
  dialogOpen.value = true
}

onMounted(load)
</script>

<template>
  <ConfirmDialog />

  <!-- Sentinel -->
  <div class="h-px" />

  <!-- Hero sticky -->
  <div
    class="sticky mx-3 md:mx-4 mb-4 z-20 overflow-hidden rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-5"
    :style="{ top: 'var(--layout-sticky-top, 56px)' }"
  >
    <div class="absolute inset-0 pointer-events-none overflow-hidden" aria-hidden="true">
      <div class="absolute rounded-full blur-[70px] w-72 h-72 -top-16 -right-20 bg-indigo-400/10" />
      <div class="absolute rounded-full blur-[70px] w-80 h-80 top-10 -left-24 bg-emerald-400/10" />
      <div class="absolute rounded-full blur-[70px] w-72 h-72 -bottom-20 right-24 bg-fuchsia-400/10" />
    </div>
    <div class="relative z-10 flex items-center justify-between gap-3 flex-wrap">
      <div class="min-w-0">
        <div class="text-[1rem] font-bold tracking-tight text-[var(--text-color)] flex items-center gap-2">
          <i class="pi pi-images text-indigo-500" />
          Carrossel do Login
        </div>
        <div class="text-[1rem] text-[var(--text-color-secondary)] mt-0.5">
          Gerencie os slides exibidos na tela de login do sistema
        </div>
      </div>
      <div class="flex items-center gap-2 shrink-0">
        <Button
          icon="pi pi-refresh"
          severity="secondary"
          outlined
          title="Recarregar"
          :loading="loading"
          @click="load"
        />
        <Button
          icon="pi pi-plus"
          label="Novo slide"
          @click="openNew"
        />
      </div>
    </div>
  </div>

  <div class="px-3 md:px-4 pb-8 flex flex-col gap-4">

    <div class="grid grid-cols-1 xl:grid-cols-[1fr_340px] gap-6 items-start">

      <!-- ── Tabela de slides ──────────────────────────────────────────────── -->
      <div class="bg-[var(--surface-card,#fff)] rounded-md border border-[var(--surface-border)] overflow-hidden">

        <!-- Loading skeleton -->
        <div v-if="loading" class="flex flex-col divide-y divide-[var(--surface-border)]">
          <div v-for="i in 4" :key="i" class="flex items-center gap-4 px-5 py-4 animate-pulse">
            <div class="w-10 h-10 rounded-md bg-[var(--surface-ground)] flex-shrink-0" />
            <div class="flex-1 space-y-2">
              <div class="h-3.5 w-40 rounded bg-[var(--surface-ground)]" />
              <div class="h-3 w-64 rounded bg-[var(--surface-ground)]" />
            </div>
          </div>
        </div>

        <!-- Lista vazia -->
        <div v-else-if="!slides.length" class="flex flex-col items-center justify-center py-16 gap-3 text-[var(--text-color-secondary)]">
          <i class="pi pi-images text-4xl opacity-30" />
          <span class="text-[1rem]">Nenhum slide cadastrado ainda.</span>
          <Button label="Criar primeiro slide" size="small" @click="openNew" />
        </div>

        <!-- Rows -->
        <div v-else class="divide-y divide-[var(--surface-border)]">
          <!-- Header -->
          <div class="grid grid-cols-[auto_1fr_auto_auto] items-center gap-4 px-5 py-2.5 bg-[var(--surface-ground)] text-xs font-bold uppercase tracking-widest text-[var(--text-color-secondary)]">
            <span class="w-10" />
            <span>Slide</span>
            <span class="text-center w-[60px]">Status</span>
            <span class="w-[96px]" />
          </div>

          <div
            v-for="(slide, i) in [...slides].sort((a,b) => a.ordem - b.ordem)"
            :key="slide.id"
            class="grid grid-cols-[auto_1fr_auto_auto] items-center gap-4 px-5 py-3.5 transition-colors duration-100 hover:bg-[var(--surface-ground,#f8fafc)] group"
          >
            <!-- Ícone + ordem -->
            <div class="relative flex-shrink-0">
              <div
                class="w-10 h-10 rounded-md flex items-center justify-center text-lg"
                :class="slide.ativo ? 'bg-indigo-500/10 text-indigo-500' : 'bg-[var(--surface-ground)] text-[var(--text-color-secondary)]'"
              >
                <i :class="['pi', slide.icon || 'pi-star']" />
              </div>
              <span class="absolute -top-1 -right-1 w-4 h-4 rounded-full bg-[var(--surface-border)] text-[0.58rem] font-bold flex items-center justify-center text-[var(--text-color-secondary)]">
                {{ slide.ordem + 1 }}
              </span>
            </div>

            <!-- Conteúdo -->
            <div class="min-w-0">
              <div class="text-[1rem] font-semibold text-[var(--text-color)] truncate [&_*]:inline" :class="!slide.ativo && 'opacity-40 line-through'" v-html="slide.title" />
              <div class="text-[1rem] text-[var(--text-color-secondary)] truncate mt-0.5 [&_*]:inline" :class="!slide.ativo && 'opacity-40'" v-html="slide.body" />
            </div>

            <!-- Toggle ativo -->
            <div class="flex justify-center w-[60px]">
              <InputSwitch
                :modelValue="slide.ativo"
                @update:modelValue="() => toggleAtivo(slide)"
              />
            </div>

            <!-- Ações -->
            <div class="flex items-center gap-1 w-[96px] justify-end opacity-0 group-hover:opacity-100 transition-opacity duration-150">
              <button
                class="w-7 h-7 rounded-md flex items-center justify-center text-[var(--text-color-secondary)] hover:bg-[var(--surface-border)] hover:text-[var(--text-color)] transition-colors duration-100 disabled:opacity-30"
                :disabled="i === 0"
                title="Mover para cima"
                @click="moveSlide(slide, -1)"
              >
                <i class="pi pi-chevron-up text-xs" />
              </button>
              <button
                class="w-7 h-7 rounded-md flex items-center justify-center text-[var(--text-color-secondary)] hover:bg-[var(--surface-border)] hover:text-[var(--text-color)] transition-colors duration-100 disabled:opacity-30"
                :disabled="i === slides.length - 1"
                title="Mover para baixo"
                @click="moveSlide(slide, 1)"
              >
                <i class="pi pi-chevron-down text-xs" />
              </button>
              <button
                class="w-7 h-7 rounded-md flex items-center justify-center text-[var(--text-color-secondary)] hover:bg-indigo-50 hover:text-indigo-600 transition-colors duration-100"
                title="Editar"
                @click="openEdit(slide)"
              >
                <i class="pi pi-pencil text-xs" />
              </button>
              <button
                class="w-7 h-7 rounded-md flex items-center justify-center text-[var(--text-color-secondary)] hover:bg-red-50 hover:text-red-500 transition-colors duration-100"
                title="Remover"
                @click="deleteSlide(slide)"
              >
                <i class="pi pi-trash text-xs" />
              </button>
            </div>
          </div>
        </div>
      </div>

      <!-- ── Preview ──────────────────────────────────────────────────────── -->
      <div class="sticky top-6 flex flex-col gap-3">
        <div class="text-xs font-bold uppercase tracking-widest text-[var(--text-color-secondary)] flex items-center gap-1.5 px-1">
          <i class="pi pi-eye" /> Pré-visualização
        </div>

        <!-- Mock da tela de login — lado esquerdo -->
        <div class="relative overflow-hidden rounded-md aspect-[9/16] max-h-[480px] w-full select-none shadow-xl">
          <div class="absolute inset-0 bg-gradient-to-br from-indigo-600 via-violet-600 to-purple-700" />

          <!-- Grade decorativa -->
          <div
            class="absolute inset-0 opacity-[0.08]"
            style="background-image: linear-gradient(to right, white 1px, transparent 1px), linear-gradient(to bottom, white 1px, transparent 1px); background-size: 32px 32px;"
          />

          <!-- Orbs -->
          <div class="absolute -top-20 -left-20 h-64 w-64 rounded-full bg-white/10 blur-3xl pointer-events-none" />
          <div class="absolute bottom-0 right-0 h-48 w-48 rounded-full bg-violet-300/20 blur-3xl pointer-events-none" />

          <div class="relative z-10 flex flex-col h-full p-6">
            <!-- Brand mock -->
            <div class="flex items-center gap-2">
              <div class="grid h-7 w-7 place-items-center rounded-lg bg-white/20 border border-white/20">
                <i class="pi pi-heart-fill text-white text-[0.6rem]" />
              </div>
              <span class="text-white/90 font-bold text-xs tracking-tight">Agência PSI</span>
            </div>

            <!-- Slide content -->
            <div class="flex-1 flex flex-col justify-center gap-4">
              <Transition name="prev-fade" mode="out-in">
                <div v-if="previewSlide" :key="previewSlide.id ?? previewIdx" class="space-y-4">
                  <div class="grid h-11 w-11 place-items-center rounded-md bg-white/15 border border-white/20 shadow-lg">
                    <i :class="['pi', previewSlide.icon || 'pi-star', 'text-white text-lg']" />
                  </div>
                  <div class="space-y-2">
                    <div class="text-xl font-bold text-white leading-tight prose prose-invert prose-sm max-w-none" v-html="previewSlide.title" />
                    <div class="text-[1rem] text-white/70 leading-relaxed prose prose-invert prose-sm max-w-none" v-html="previewSlide.body" />
                  </div>
                </div>
                <div v-else class="flex flex-col items-center justify-center gap-2 text-white/30 text-xs">
                  <i class="pi pi-ban text-2xl" />
                  Nenhum slide ativo
                </div>
              </Transition>
            </div>

            <!-- Dots -->
            <div class="flex items-center gap-1.5">
              <button
                v-for="(s, i) in slidesAtivos"
                :key="s.id"
                class="transition-all duration-300 rounded-full"
                :class="i === previewIdx ? 'w-5 h-1.5 bg-white shadow' : 'w-1.5 h-1.5 bg-white/35 hover:bg-white/60'"
                @click="previewIdx = i"
              />
              <span v-if="slidesAtivos.length" class="ml-2 text-[0.6rem] text-white/40 tabular-nums">
                {{ previewIdx + 1 }}/{{ slidesAtivos.length }}
              </span>
            </div>
          </div>
        </div>

        <!-- Info -->
        <div class="rounded-lg border border-[var(--surface-border)] bg-[var(--surface-card)] px-4 py-3 text-xs text-[var(--text-color-secondary)] flex items-start gap-2">
          <i class="pi pi-info-circle text-indigo-500 mt-px flex-shrink-0" />
          <span>Clique nos pontos para navegar entre os slides ativos. A ordem e visibilidade refletem o que o usuário verá no login.</span>
        </div>
      </div>
    </div>

    <!-- ── SQL Helper ───────────────────────────────────────────────────────── -->
    <div class="bg-[var(--surface-card)] rounded-md border border-[var(--surface-border)] px-5 py-4">
      <div class="flex items-center gap-2 mb-3">
        <i class="pi pi-database text-amber-500 text-[1rem]" />
        <span class="text-xs font-bold text-[var(--text-color)] uppercase tracking-widest">SQL de referência</span>
        <span class="ml-auto text-xs text-[var(--text-color-secondary)]">Execute no Supabase caso a tabela não exista</span>
      </div>
      <pre class="text-[0.7rem] bg-[var(--surface-ground)] rounded-lg p-3.5 overflow-x-auto text-[var(--text-color-secondary)] leading-relaxed whitespace-pre-wrap"><code>create table if not exists public.login_carousel_slides (
  id      uuid primary key default gen_random_uuid(),
  title   text not null,
  body    text not null,
  icon    text not null default 'pi-star',
  ordem   integer not null default 0,
  ativo   boolean not null default true,
  created_at timestamptz default now(),
  updated_at timestamptz default now()
);

-- RLS: apenas saas_admin pode gerenciar
alter table public.login_carousel_slides enable row level security;

create policy "saas_admin_full" on public.login_carousel_slides
  for all using (
    exists (
      select 1 from public.profiles
      where id = auth.uid() and role = 'saas_admin'
    )
  );

-- Leitura pública (login não tem usuário autenticado)
create policy "public_read" on public.login_carousel_slides
  for select using (ativo = true);</code></pre>
    </div>

  </div>

  <!-- /px-3 content wrapper -->

  <!-- ── Dialog: Criar / Editar slide ───────────────────────────────────────── -->
  <Dialog
    v-model:visible="dialogOpen"
    modal
    :header="editingSlide ? 'Editar slide' : 'Novo slide'"
    :draggable="false"
    :style="{ width: '46rem', maxWidth: '96vw' }"
  >
    <div class="flex flex-col gap-4 pt-1">

      <!-- Título -->
      <div class="flex flex-col gap-1.5">
        <label class="text-[1rem] font-semibold text-[var(--text-color)]">Título <span class="text-red-500">*</span></label>
        <Editor
          v-model="form.title"
          :pt="{ toolbar: { style: 'display:none' } }"
          style="height: 72px"
          editorStyle="font-size: 1rem; font-weight: 600;"
          placeholder="Ex: Gestão clínica simplificada"
        >
          <template #toolbar>
            <span class="ql-formats">
              <button class="ql-bold" />
              <button class="ql-italic" />
              <button class="ql-underline" />
            </span>
          </template>
        </Editor>
      </div>

      <!-- Conteúdo -->
      <div class="flex flex-col gap-1.5">
        <label class="text-[1rem] font-semibold text-[var(--text-color)]">Conteúdo <span class="text-red-500">*</span></label>
        <Editor
          v-model="form.body"
          style="height: 160px"
          editorStyle="font-size: 1rem;"
        >
          <template #toolbar>
            <span class="ql-formats">
              <button class="ql-bold" />
              <button class="ql-italic" />
              <button class="ql-underline" />
            </span>
            <span class="ql-formats">
              <button class="ql-list" value="ordered" />
              <button class="ql-list" value="bullet" />
            </span>
            <span class="ql-formats">
              <button class="ql-link" />
              <button class="ql-clean" />
            </span>
          </template>
        </Editor>
      </div>

      <!-- Ícone -->
      <div class="flex flex-col gap-1.5">
        <label class="text-[1rem] font-semibold text-[var(--text-color)]">Ícone</label>
        <div class="grid grid-cols-4 sm:grid-cols-8 gap-1.5">
          <button
            v-for="ic in ICONS"
            :key="ic.value"
            type="button"
            class="flex flex-col items-center justify-center gap-1 py-2 rounded-lg border text-xs transition-all duration-100"
            :class="form.icon === ic.value
              ? 'border-indigo-500 bg-indigo-50 text-indigo-600 shadow-sm'
              : 'border-[var(--surface-border)] bg-[var(--surface-ground)] text-[var(--text-color-secondary)] hover:border-indigo-300 hover:text-indigo-500'"
            :title="ic.label"
            @click="form.icon = ic.value"
          >
            <i :class="['pi', ic.value, 'text-base']" />
            <span class="text-[0.6rem] leading-none">{{ ic.label }}</span>
          </button>
        </div>
      </div>

      <!-- Ativo -->
      <div class="flex items-center gap-3">
        <InputSwitch v-model="form.ativo" inputId="slide-ativo" />
        <label for="slide-ativo" class="text-[1rem] text-[var(--text-color)] cursor-pointer select-none">
          Slide ativo (visível no carrossel)
        </label>
      </div>

      <!-- Mini preview -->
      <div
        class="relative overflow-hidden rounded-md p-5 flex items-center gap-4"
        style="background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%)"
      >
        <div class="grid h-12 w-12 flex-shrink-0 place-items-center rounded-md bg-white/15 border border-white/20 shadow">
          <i :class="['pi', form.icon || 'pi-star', 'text-white text-xl']" />
        </div>
        <div class="min-w-0 overflow-hidden">
          <div class="text-[1rem] font-bold text-white line-clamp-2 prose prose-invert prose-sm max-w-none" v-html="stripHtml(form.title) ? form.title : 'Título do slide'" />
          <div class="text-[1rem] text-white/70 mt-0.5 line-clamp-3 prose prose-invert prose-sm max-w-none" v-html="stripHtml(form.body) ? form.body : 'Conteúdo descritivo...'" />
        </div>
      </div>

      <!-- Ações -->
      <div class="flex justify-end gap-2 pt-1">
        <Button label="Cancelar" severity="secondary" outlined :disabled="saving" @click="dialogOpen = false" />
        <Button
          :label="editingSlide ? 'Salvar alterações' : 'Criar slide'"
          icon="pi pi-check"
          :loading="saving"
          @click="saveSlide"
        />
      </div>
    </div>
  </Dialog>

</template>

<style scoped>
.prev-fade-enter-active,
.prev-fade-leave-active {
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.prev-fade-enter-from {
  opacity: 0;
  transform: translateY(12px);
}
.prev-fade-leave-to {
  opacity: 0;
  transform: translateY(-8px);
}
</style>
