<script setup lang="ts">
import type { MandateCreate, MandateStepCreate } from '~/stores/mandates'

const mandates = useMandatesStore()
const { $api } = useApi()

// ── Wizard steps ──────────────────────────────────────────────────────────────
type WizardStep = 'info' | 'nomination' | 'toolbox' | 'summary'
const wizardStep = ref<WizardStep>('info')

// ── Step 1 : Infos de base ────────────────────────────────────────────────────
const title = ref('')
const origin = ref('')
const description = ref('')
const mandateType = ref<'techcomm' | 'smith' | 'custom'>('custom')

// Durée
type DurationMode = 'relative' | 'dates'
const durationMode = ref<DurationMode>('relative')
const durationValue = ref(3)
const durationUnit = ref<'days' | 'weeks' | 'months'>('months')
const startsAt = ref('')
const endsAt = ref('')

function computedDates(): { starts_at: string | null; ends_at: string | null } {
  if (durationMode.value === 'dates') {
    return {
      starts_at: startsAt.value || null,
      ends_at: endsAt.value || null,
    }
  }
  const now = new Date()
  const end = new Date(now)
  if (durationUnit.value === 'days') end.setDate(end.getDate() + durationValue.value)
  else if (durationUnit.value === 'weeks') end.setDate(end.getDate() + durationValue.value * 7)
  else end.setMonth(end.getMonth() + durationValue.value)
  return {
    starts_at: now.toISOString(),
    ends_at: end.toISOString(),
  }
}

const durationLabel = computed(() => {
  if (durationMode.value === 'dates') {
    if (!startsAt.value && !endsAt.value) return 'Dates non définies'
    return `${startsAt.value ? new Date(startsAt.value).toLocaleDateString('fr-FR') : '?'} → ${endsAt.value ? new Date(endsAt.value).toLocaleDateString('fr-FR') : '?'}`
  }
  const u = durationUnit.value === 'days' ? 'jour' : durationUnit.value === 'weeks' ? 'semaine' : 'mois'
  return `${durationValue.value} ${u}${durationValue.value > 1 && durationUnit.value !== 'months' ? 's' : ''}`
})

const canGoToNomination = computed(() =>
  title.value.trim().length > 0 && (
    durationMode.value === 'relative' ||
    (startsAt.value !== '' && endsAt.value !== '')
  )
)

// ── Step 2 : Nomination ───────────────────────────────────────────────────────
type NominationCase = 'self' | 'election'
const nominationCase = ref<NominationCase | null>(null)

// Case 1 — self : ratification vote params
const selfParams = reactive({ duration_days: 7, quorum_pct: 30, majority_pct: 51 })

// ── Step 3 : Boîte à outils élection ─────────────────────────────────────────
type ElectionMode = 'direct' | 'candidacy'
const electionMode = ref<ElectionMode>('direct')
const selectedModalityId = ref<string | null>(null)

interface ModalityParam {
  id: string
  label: string
  unit: string
  min: number
  max: number
  default: number
}
interface Modality {
  id: string
  icon: string
  title: string
  desc: string
  recommended: boolean
  recommendedReason?: string
  params: ModalityParam[]
  requiresCandidacy: boolean
}

const MODALITIES: Modality[] = [
  // ── Sans candidature ──
  {
    id: 'vote_simple',
    icon: 'i-lucide-check-square',
    title: 'Vote de désignation',
    desc: 'Vote direct parmi les membres du cercle concerné. Simple et rapide pour les petits groupes.',
    recommended: mandateType.value !== 'smith',
    recommendedReason: 'Adapté aux petits collectifs et décisions peu contestées.',
    params: [
      { id: 'duration_days', label: 'Durée du vote', unit: 'jours', min: 1, max: 30, default: 7 },
      { id: 'quorum_pct', label: 'Quorum', unit: '%', min: 10, max: 100, default: 30 },
      { id: 'majority_pct', label: 'Seuil de majorité', unit: '%', min: 51, max: 100, default: 51 },
    ],
    requiresCandidacy: false,
  },
  {
    id: 'vote_wot',
    icon: 'i-lucide-network',
    title: 'Vote WoT',
    desc: 'Vote pondéré par la Toile de Confiance. Le poids de chaque voix dépend de la distance certificationnelle.',
    recommended: true,
    recommendedReason: 'Recommandé pour les mandats impliquant la communauté G1 au-delà des 10 personnes.',
    params: [
      { id: 'duration_days', label: 'Durée du vote', unit: 'jours', min: 1, max: 60, default: 14 },
      { id: 'quorum_pct', label: 'Quorum WoT', unit: '% de la WoT', min: 5, max: 100, default: 20 },
      { id: 'majority_pct', label: 'Seuil', unit: '%', min: 51, max: 100, default: 51 },
    ],
    requiresCandidacy: false,
  },
  {
    id: 'vote_smith',
    icon: 'i-lucide-hammer',
    title: 'Vote Smith',
    desc: 'Réservé aux Forgerons (critère de Smith). Utilisé pour les décisions techniques du réseau.',
    recommended: mandateType.value === 'smith' || mandateType.value === 'techcomm',
    recommendedReason: 'Standard pour les mandats Forgeron et Comité Technique.',
    params: [
      { id: 'duration_days', label: 'Durée du vote', unit: 'jours', min: 1, max: 30, default: 14 },
      { id: 'smith_min', label: 'Forgerons minimum', unit: 'forgerons', min: 1, max: 20, default: 3 },
    ],
    requiresCandidacy: false,
  },
  // ── Avec candidature ──
  {
    id: 'candidacy_vote_majoritaire',
    icon: 'i-lucide-user-check',
    title: 'Candidature + Vote majoritaire',
    desc: 'Appel à candidature ouvert, suivi d\'un vote binaire (Pour/Contre) pour chaque candidat.',
    recommended: false,
    params: [
      { id: 'candidacy_days', label: 'Fenêtre de candidature', unit: 'jours', min: 1, max: 30, default: 7 },
      { id: 'duration_days', label: 'Durée du vote', unit: 'jours', min: 1, max: 30, default: 7 },
      { id: 'quorum_pct', label: 'Quorum', unit: '%', min: 10, max: 100, default: 30 },
      { id: 'majority_pct', label: 'Seuil', unit: '%', min: 51, max: 100, default: 51 },
    ],
    requiresCandidacy: true,
  },
  {
    id: 'candidacy_vote_preferentiel',
    icon: 'i-lucide-list-ordered',
    title: 'Candidature + Vote préférentiel',
    desc: 'Candidature ouverte, puis classement des candidats par les votants (méthode Condorcet ou Borda).',
    recommended: true,
    recommendedReason: 'Recommandé dès 3 candidats pour éviter les effets de vote utile.',
    params: [
      { id: 'candidacy_days', label: 'Fenêtre de candidature', unit: 'jours', min: 1, max: 30, default: 7 },
      { id: 'duration_days', label: 'Durée du vote', unit: 'jours', min: 1, max: 60, default: 14 },
    ],
    requiresCandidacy: true,
  },
  {
    id: 'candidacy_vote_wot',
    icon: 'i-lucide-network',
    title: 'Candidature + Vote WoT',
    desc: 'Candidature ouverte, puis vote pondéré par la Toile de Confiance.',
    recommended: false,
    params: [
      { id: 'candidacy_days', label: 'Fenêtre de candidature', unit: 'jours', min: 1, max: 30, default: 7 },
      { id: 'duration_days', label: 'Durée du vote', unit: 'jours', min: 1, max: 60, default: 14 },
      { id: 'majority_pct', label: 'Seuil WoT', unit: '%', min: 51, max: 100, default: 51 },
    ],
    requiresCandidacy: true,
  },
]

const visibleModalities = computed(() =>
  MODALITIES.filter(m => m.requiresCandidacy === (electionMode.value === 'candidacy'))
)

// Paramètres par modalité (valeurs mutable)
const paramValues = reactive<Record<string, Record<string, number>>>({})
function getParam(modalityId: string, paramId: string): number {
  if (!paramValues[modalityId]) {
    const m = MODALITIES.find(x => x.id === modalityId)
    if (m) paramValues[modalityId] = Object.fromEntries(m.params.map(p => [p.id, p.default]))
  }
  return paramValues[modalityId]?.[paramId] ?? 0
}
function setParam(modalityId: string, paramId: string, value: number) {
  if (!paramValues[modalityId]) getParam(modalityId, paramId)
  paramValues[modalityId][paramId] = value
}

// ── Génération des steps à créer ──────────────────────────────────────────────
interface StepDef { step_type: string; title: string; description: string }

const stepsToCreate = computed<StepDef[]>(() => {
  const steps: StepDef[] = []
  steps.push({ step_type: 'formulation', title: 'Rédaction du mandat', description: 'Définition du périmètre, des objectifs et des attendus.' })

  if (nominationCase.value === 'self') {
    steps.push({ step_type: 'vote', title: 'Ratification', description: `Vote de ratification — durée ${selfParams.duration_days}j, quorum ${selfParams.quorum_pct}%, seuil ${selfParams.majority_pct}%.` })
    steps.push({ step_type: 'assignment', title: 'Prise de mandat', description: 'La personne entre en mandat après ratification.' })
  } else if (nominationCase.value === 'election' && selectedModalityId.value) {
    const m = MODALITIES.find(x => x.id === selectedModalityId.value)
    if (m?.requiresCandidacy) {
      const cdays = getParam(m.id, 'candidacy_days')
      steps.push({ step_type: 'candidacy', title: 'Appel à candidature', description: `Fenêtre de candidature : ${cdays} jour${cdays > 1 ? 's' : ''}.` })
    }
    if (m) {
      const pv = paramValues[m.id] ?? {}
      const paramStr = Object.entries(pv).filter(([k]) => k !== 'candidacy_days').map(([k, v]) => {
        const p = m.params.find(x => x.id === k)
        return p ? `${p.label} : ${v} ${p.unit}` : ''
      }).filter(Boolean).join(', ')
      steps.push({ step_type: 'vote', title: `Élection — ${m.title}`, description: paramStr })
    }
    steps.push({ step_type: 'assignment', title: 'Désignation du mandataire', description: 'Le candidat élu entre en mandat.' })
  }

  steps.push({ step_type: 'reporting', title: 'Compte-rendu', description: 'Rapport d\'activité en fin de mandat.' })
  steps.push({ step_type: 'completion', title: 'Clôture', description: 'Validation de la fin du mandat.' })
  return steps
})

const canGoToSummary = computed(() => {
  if (nominationCase.value === 'self') return true
  if (nominationCase.value === 'election') return selectedModalityId.value !== null
  return false
})

// ── Création ──────────────────────────────────────────────────────────────────
const submitting = ref(false)
const submitError = ref<string | null>(null)

async function createMandate() {
  submitting.value = true
  submitError.value = null
  try {
    const dates = computedDates()
    const mandate = await mandates.create({
      title: title.value.trim(),
      origin: origin.value.trim() || null,
      description: description.value.trim() || null,
      mandate_type: mandateType.value,
      starts_at: dates.starts_at,
      ends_at: dates.ends_at,
    })
    if (!mandate) throw new Error('Erreur création mandat')

    // Create steps
    for (let i = 0; i < stepsToCreate.value.length; i++) {
      const s = stepsToCreate.value[i]
      await $api(`/mandates/${mandate.id}/steps`, {
        method: 'POST',
        body: { step_order: i, step_type: s.step_type, title: s.title, description: s.description },
      })
    }

    navigateTo(`/mandates/${mandate.id}`)
  } catch (e: any) {
    submitError.value = e?.message ?? 'Erreur lors de la création'
  } finally {
    submitting.value = false
  }
}

// ── Navigation ────────────────────────────────────────────────────────────────
function goBack() {
  if (wizardStep.value === 'summary') wizardStep.value = nominationCase.value === 'election' ? 'toolbox' : 'nomination'
  else if (wizardStep.value === 'toolbox') wizardStep.value = 'nomination'
  else if (wizardStep.value === 'nomination') wizardStep.value = 'info'
}

function goToNomination() { if (canGoToNomination.value) wizardStep.value = 'nomination' }
function goToToolbox() { wizardStep.value = 'toolbox' }
function goToSummary() { if (canGoToSummary.value) wizardStep.value = 'summary' }

// Typage
const MANDATE_TYPE_OPTIONS = [
  { value: 'custom', label: 'Mandat libre', icon: 'i-lucide-circle' },
  { value: 'techcomm', label: 'Comité Technique', icon: 'i-lucide-cpu' },
  { value: 'smith', label: 'Forgeron', icon: 'i-lucide-hammer' },
]
</script>

<template>
  <div class="mwiz">
    <!-- Nav -->
    <div class="mwiz__nav">
      <button v-if="wizardStep !== 'info'" class="mwiz__back" @click="goBack">
        <UIcon name="i-lucide-arrow-left" class="text-sm" />
        <span>Retour</span>
      </button>
      <NuxtLink v-else to="/mandates" class="mwiz__back">
        <UIcon name="i-lucide-arrow-left" class="text-sm" />
        <span>Mandats</span>
      </NuxtLink>

      <!-- Progress pills -->
      <div class="mwiz__progress">
        <span class="mwiz__pill" :class="{ 'mwiz__pill--active': wizardStep === 'info', 'mwiz__pill--done': wizardStep !== 'info' }">1 Infos</span>
        <span class="mwiz__sep">›</span>
        <span class="mwiz__pill" :class="{ 'mwiz__pill--active': wizardStep === 'nomination', 'mwiz__pill--done': ['toolbox','summary'].includes(wizardStep) }">2 Nomination</span>
        <span class="mwiz__sep">›</span>
        <span v-if="nominationCase === 'election'" class="mwiz__pill" :class="{ 'mwiz__pill--active': wizardStep === 'toolbox', 'mwiz__pill--done': wizardStep === 'summary' }">3 Modalités</span>
        <span v-if="nominationCase === 'election'" class="mwiz__sep">›</span>
        <span class="mwiz__pill" :class="{ 'mwiz__pill--active': wizardStep === 'summary' }">{{ nominationCase === 'election' ? '4' : '3' }} Récap</span>
      </div>
    </div>

    <Transition name="slide-fade" mode="out-in">

      <!-- ─── ÉTAPE 1 : Infos de base ──────────────────────────────────── -->
      <div v-if="wizardStep === 'info'" key="info" class="mwiz__step">
        <div class="mwiz__header">
          <h1 class="mwiz__title">Nouveau mandat</h1>
          <p class="mwiz__subtitle">Définissez le périmètre et la durée du mandat</p>
        </div>

        <div class="mwiz__form">

          <!-- Type de mandat -->
          <div class="mwiz__section">
            <p class="mwiz__label">Type de mandat</p>
            <div class="mwiz__type-grid">
              <button
                v-for="opt in MANDATE_TYPE_OPTIONS"
                :key="opt.value"
                class="mwiz__type-btn"
                :class="{ 'mwiz__type-btn--active': mandateType === opt.value }"
                @click="mandateType = opt.value as any"
              >
                <UIcon :name="opt.icon" class="text-base" />
                <span>{{ opt.label }}</span>
              </button>
            </div>
          </div>

          <!-- Nom -->
          <div class="mwiz__section">
            <label class="mwiz__label">Nom du mandat <span class="mwiz__req">*</span></label>
            <input
              v-model="title"
              type="text"
              class="mwiz__input"
              lang="fr"
              spellcheck="true"
              placeholder="Ex : Responsable communication, Délégué technique G1..."
            />
          </div>

          <!-- Origine -->
          <div class="mwiz__section">
            <label class="mwiz__label">Origine <span class="mwiz__optional">(optionnel)</span></label>
            <textarea
              v-model="origin"
              class="mwiz__textarea"
              rows="2"
              lang="fr"
              spellcheck="true"
              placeholder="Qui propose ce mandat, dans quel contexte, suite à quelle décision ou besoin ?"
            />
          </div>

          <!-- Description -->
          <div class="mwiz__section">
            <label class="mwiz__label">Description du mandat <span class="mwiz__optional">(optionnel)</span></label>
            <textarea
              v-model="description"
              class="mwiz__textarea"
              rows="3"
              lang="fr"
              spellcheck="true"
              placeholder="Périmètre, responsabilités, attendus du mandataire..."
            />
          </div>

          <!-- Durée -->
          <div class="mwiz__section">
            <p class="mwiz__label">Durée du mandat</p>
            <div class="mwiz__dur-toggle">
              <button class="mwiz__dur-btn" :class="{ 'mwiz__dur-btn--active': durationMode === 'relative' }" @click="durationMode = 'relative'">
                <UIcon name="i-lucide-clock" class="text-sm" /> Durée
              </button>
              <button class="mwiz__dur-btn" :class="{ 'mwiz__dur-btn--active': durationMode === 'dates' }" @click="durationMode = 'dates'">
                <UIcon name="i-lucide-calendar" class="text-sm" /> Dates fixes
              </button>
            </div>

            <div v-if="durationMode === 'relative'" class="mwiz__dur-relative">
              <input v-model.number="durationValue" type="number" class="mwiz__dur-number" min="1" max="999" />
              <div class="mwiz__type-grid mwiz__type-grid--sm">
                <button class="mwiz__type-btn" :class="{ 'mwiz__type-btn--active': durationUnit === 'days' }" @click="durationUnit = 'days'">Jours</button>
                <button class="mwiz__type-btn" :class="{ 'mwiz__type-btn--active': durationUnit === 'weeks' }" @click="durationUnit = 'weeks'">Semaines</button>
                <button class="mwiz__type-btn" :class="{ 'mwiz__type-btn--active': durationUnit === 'months' }" @click="durationUnit = 'months'">Mois</button>
              </div>
            </div>

            <div v-else class="mwiz__dur-dates">
              <div class="mwiz__dur-date-field">
                <label class="mwiz__label-sm">Début</label>
                <input v-model="startsAt" type="date" class="mwiz__input" />
              </div>
              <UIcon name="i-lucide-arrow-right" class="text-sm mwiz__dur-arrow" />
              <div class="mwiz__dur-date-field">
                <label class="mwiz__label-sm">Fin</label>
                <input v-model="endsAt" type="date" class="mwiz__input" />
              </div>
            </div>
          </div>

          <button class="mwiz__submit" :disabled="!canGoToNomination" @click="goToNomination">
            Étape suivante — Nomination
            <UIcon name="i-lucide-arrow-right" class="text-sm" />
          </button>
        </div>
      </div>

      <!-- ─── ÉTAPE 2 : Nomination ─────────────────────────────────────── -->
      <div v-else-if="wizardStep === 'nomination'" key="nomination" class="mwiz__step">
        <div class="mwiz__header">
          <h1 class="mwiz__title">Processus de nomination</h1>
          <p class="mwiz__subtitle">Ce mandat est-il demandé par son futur titulaire, ou faut-il désigner quelqu'un ?</p>
        </div>

        <div class="mwiz__nom-grid">
          <!-- Cas 1 : soi-même -->
          <button
            class="mwiz__nom-card"
            :class="{ 'mwiz__nom-card--active': nominationCase === 'self' }"
            @click="nominationCase = 'self'"
          >
            <div class="mwiz__nom-icon">
              <UIcon name="i-lucide-user-check" class="text-2xl" />
            </div>
            <div class="mwiz__nom-body">
              <p class="mwiz__nom-title">Auto-désignation</p>
              <p class="mwiz__nom-desc">La personne à l'origine du mandat le demande pour elle-même. Un vote de ratification valide la prise de mandat.</p>
            </div>
          </button>

          <!-- Cas 2 : élection -->
          <button
            class="mwiz__nom-card"
            :class="{ 'mwiz__nom-card--active': nominationCase === 'election' }"
            @click="nominationCase = 'election'"
          >
            <div class="mwiz__nom-icon">
              <UIcon name="i-lucide-users" class="text-2xl" />
            </div>
            <div class="mwiz__nom-body">
              <p class="mwiz__nom-title">Désignation par le collectif</p>
              <p class="mwiz__nom-desc">Le mandataire est élu ou désigné par le groupe. La boîte à outils propose les modalités d'élection adaptées.</p>
            </div>
          </button>
        </div>

        <!-- Cas 1 : paramètres ratification -->
        <Transition name="slide-down">
          <div v-if="nominationCase === 'self'" class="mwiz__self-params">
            <p class="mwiz__label">Paramètres du vote de ratification</p>
            <div class="mwiz__param-row">
              <div class="mwiz__param-field">
                <label class="mwiz__label-sm">Durée du vote</label>
                <div class="mwiz__param-input-row">
                  <input v-model.number="selfParams.duration_days" type="number" class="mwiz__param-input" min="1" max="30" />
                  <span class="mwiz__param-unit">jours</span>
                </div>
              </div>
              <div class="mwiz__param-field">
                <label class="mwiz__label-sm">Quorum</label>
                <div class="mwiz__param-input-row">
                  <input v-model.number="selfParams.quorum_pct" type="number" class="mwiz__param-input" min="10" max="100" />
                  <span class="mwiz__param-unit">%</span>
                </div>
              </div>
              <div class="mwiz__param-field">
                <label class="mwiz__label-sm">Seuil de majorité</label>
                <div class="mwiz__param-input-row">
                  <input v-model.number="selfParams.majority_pct" type="number" class="mwiz__param-input" min="51" max="100" />
                  <span class="mwiz__param-unit">%</span>
                </div>
              </div>
            </div>
            <button class="mwiz__submit" @click="goToSummary">
              Récapitulatif
              <UIcon name="i-lucide-arrow-right" class="text-sm" />
            </button>
          </div>
        </Transition>

        <Transition name="slide-down">
          <div v-if="nominationCase === 'election'" class="mwiz__election-cta">
            <button class="mwiz__submit" @click="goToToolbox">
              Choisir les modalités d'élection
              <UIcon name="i-lucide-arrow-right" class="text-sm" />
            </button>
          </div>
        </Transition>
      </div>

      <!-- ─── ÉTAPE 3 : Boîte à outils élection ───────────────────────── -->
      <div v-else-if="wizardStep === 'toolbox'" key="toolbox" class="mwiz__step">
        <div class="mwiz__header">
          <h1 class="mwiz__title">Modalités d'élection</h1>
          <p class="mwiz__subtitle">Choisissez le mode de désignation et configurez les paramètres</p>
        </div>

        <!-- Mode toggle -->
        <div class="mwiz__mode-toggle">
          <button class="mwiz__mode-btn" :class="{ 'mwiz__mode-btn--active': electionMode === 'direct' }" @click="electionMode = 'direct'">
            <UIcon name="i-lucide-vote" class="text-sm" />
            Sans candidature
          </button>
          <button class="mwiz__mode-btn" :class="{ 'mwiz__mode-btn--active': electionMode === 'candidacy' }" @click="electionMode = 'candidacy'">
            <UIcon name="i-lucide-user-plus" class="text-sm" />
            Avec candidature
          </button>
        </div>

        <!-- Modalités -->
        <div class="mwiz__modalities">
          <div
            v-for="m in visibleModalities"
            :key="m.id"
            class="mwiz__modality"
            :class="{
              'mwiz__modality--selected': selectedModalityId === m.id,
              'mwiz__modality--recommended': m.recommended,
            }"
            @click="selectedModalityId = m.id"
          >
            <div class="mwiz__modality-head">
              <div class="mwiz__modality-icon">
                <UIcon :name="m.icon" class="text-lg" />
              </div>
              <div class="mwiz__modality-info">
                <p class="mwiz__modality-title">{{ m.title }}</p>
                <p class="mwiz__modality-desc">{{ m.desc }}</p>
              </div>
              <div class="mwiz__modality-check">
                <UIcon v-if="selectedModalityId === m.id" name="i-lucide-circle-check" class="text-lg" />
                <UIcon v-else name="i-lucide-circle" class="text-lg" />
              </div>
            </div>

            <span v-if="m.recommended" class="mwiz__modality-badge">
              <UIcon name="i-lucide-sparkles" class="text-xs" />
              Recommandé
            </span>
            <p v-if="m.recommended && m.recommendedReason" class="mwiz__modality-reason">{{ m.recommendedReason }}</p>

            <!-- Paramètres (visibles si sélectionné) -->
            <Transition name="slide-down">
              <div v-if="selectedModalityId === m.id" class="mwiz__modality-params">
                <div v-for="p in m.params" :key="p.id" class="mwiz__param-field">
                  <label class="mwiz__label-sm">{{ p.label }}</label>
                  <div class="mwiz__param-input-row">
                    <input
                      :value="getParam(m.id, p.id)"
                      type="number"
                      class="mwiz__param-input"
                      :min="p.min"
                      :max="p.max"
                      @input="setParam(m.id, p.id, +($event.target as HTMLInputElement).value)"
                    />
                    <span class="mwiz__param-unit">{{ p.unit }}</span>
                    <input
                      :value="getParam(m.id, p.id)"
                      type="range"
                      class="mwiz__param-slider"
                      :min="p.min"
                      :max="p.max"
                      @input="setParam(m.id, p.id, +($event.target as HTMLInputElement).value)"
                    />
                  </div>
                </div>
              </div>
            </Transition>
          </div>
        </div>

        <button class="mwiz__submit" :disabled="!canGoToSummary" @click="goToSummary">
          Récapitulatif
          <UIcon name="i-lucide-arrow-right" class="text-sm" />
        </button>
      </div>

      <!-- ─── ÉTAPE 4 : Récapitulatif ──────────────────────────────────── -->
      <div v-else-if="wizardStep === 'summary'" key="summary" class="mwiz__step">
        <div class="mwiz__header">
          <h1 class="mwiz__title">Récapitulatif</h1>
          <p class="mwiz__subtitle">Vérifiez avant de créer le mandat</p>
        </div>

        <div class="mwiz__recap">
          <!-- Infos -->
          <div class="mwiz__recap-block">
            <p class="mwiz__recap-label">Mandat</p>
            <p class="mwiz__recap-title">{{ title }}</p>
            <p v-if="origin" class="mwiz__recap-meta">Origine : {{ origin }}</p>
            <p v-if="description" class="mwiz__recap-meta">{{ description }}</p>
            <p class="mwiz__recap-meta">
              <UIcon name="i-lucide-clock" class="text-xs" />
              {{ durationLabel }}
            </p>
            <p class="mwiz__recap-meta">
              <UIcon :name="MANDATE_TYPE_OPTIONS.find(o => o.value === mandateType)?.icon ?? 'i-lucide-circle'" class="text-xs" />
              {{ MANDATE_TYPE_OPTIONS.find(o => o.value === mandateType)?.label }}
            </p>
          </div>

          <!-- Nomination -->
          <div class="mwiz__recap-block">
            <p class="mwiz__recap-label">Nomination</p>
            <p class="mwiz__recap-value">
              {{ nominationCase === 'self' ? 'Auto-désignation avec ratification' : `Élection — ${MODALITIES.find(m => m.id === selectedModalityId)?.title ?? ''}` }}
            </p>
            <p v-if="nominationCase === 'self'" class="mwiz__recap-meta">
              Durée : {{ selfParams.duration_days }}j · Quorum : {{ selfParams.quorum_pct }}% · Seuil : {{ selfParams.majority_pct }}%
            </p>
          </div>

          <!-- Steps -->
          <div class="mwiz__recap-block">
            <p class="mwiz__recap-label">Étapes générées ({{ stepsToCreate.length }})</p>
            <ol class="mwiz__steps-list">
              <li v-for="(s, i) in stepsToCreate" :key="i" class="mwiz__steps-item">
                <span class="mwiz__steps-num">{{ i + 1 }}</span>
                <div>
                  <p class="mwiz__steps-title">{{ s.title }}</p>
                  <p class="mwiz__steps-desc">{{ s.description }}</p>
                </div>
              </li>
            </ol>
          </div>
        </div>

        <p v-if="submitError" class="mwiz__error">{{ submitError }}</p>

        <div class="mwiz__recap-actions">
          <button class="mwiz__back-btn" @click="goBack">
            <UIcon name="i-lucide-arrow-left" class="text-sm" /> Modifier
          </button>
          <button class="mwiz__create-btn" :disabled="submitting" @click="createMandate">
            <UIcon v-if="submitting" name="i-lucide-loader-2" class="animate-spin text-sm" />
            <UIcon v-else name="i-lucide-check" class="text-sm" />
            {{ submitting ? 'Création…' : 'Créer le mandat' }}
          </button>
        </div>
      </div>

    </Transition>
  </div>
</template>

<style scoped>
.mwiz {
  max-width: 720px;
  margin: 0 auto;
  padding: 1.5rem 1rem 4rem;
}

/* Nav */
.mwiz__nav {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 2rem;
  flex-wrap: wrap;
}
.mwiz__back {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.875rem;
  color: var(--mood-muted);
  cursor: pointer;
  transition: color 0.1s;
}
.mwiz__back:hover { color: var(--mood-text); }
.mwiz__progress {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-left: auto;
  flex-wrap: wrap;
}
.mwiz__sep { color: var(--mood-muted); font-size: 0.75rem; }
.mwiz__pill {
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.25rem 0.625rem;
  border-radius: 20px;
  color: var(--mood-muted);
  background: var(--mood-surface);
}
.mwiz__pill--active {
  background: var(--mood-accent);
  color: var(--mood-accent-text);
}
.mwiz__pill--done {
  background: var(--mood-accent-soft);
  color: var(--mood-accent);
}

/* Header */
.mwiz__header { margin-bottom: 2rem; }
.mwiz__title { font-size: clamp(1.375rem, 3vw, 1.75rem); font-weight: 800; color: var(--mood-text); margin-bottom: 0.375rem; }
.mwiz__subtitle { font-size: 0.9375rem; color: var(--mood-muted); }

/* Form */
.mwiz__form { display: flex; flex-direction: column; gap: 1.5rem; }
.mwiz__section { display: flex; flex-direction: column; gap: 0.5rem; }
.mwiz__label { font-size: 0.9375rem; font-weight: 600; color: var(--mood-text); }
.mwiz__label-sm { font-size: 0.8125rem; font-weight: 600; color: var(--mood-muted); }
.mwiz__req { color: var(--mood-accent); }
.mwiz__optional { font-weight: 400; font-size: 0.8125rem; color: var(--mood-muted); }
.mwiz__input {
  width: 100%;
  padding: 0.6875rem 1rem;
  font-size: 0.9375rem;
  color: var(--mood-text);
  background: var(--mood-accent-soft);
  border-radius: 12px;
  outline: none;
}
.mwiz__textarea {
  width: 100%;
  padding: 0.6875rem 1rem;
  font-size: 0.9375rem;
  color: var(--mood-text);
  background: var(--mood-accent-soft);
  border-radius: 12px;
  outline: none;
  resize: vertical;
  font-family: inherit;
}

/* Type grid */
.mwiz__type-grid {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.mwiz__type-grid--sm .mwiz__type-btn { padding: 0.375rem 0.75rem; font-size: 0.875rem; }
.mwiz__type-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.5rem 1rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--mood-muted);
  background: var(--mood-surface);
  border-radius: 16px;
  cursor: pointer;
  transition: background 0.1s, color 0.1s, transform 0.1s;
}
.mwiz__type-btn:hover { transform: translateY(-1px); }
.mwiz__type-btn--active { background: var(--mood-accent); color: var(--mood-accent-text); }

/* Duration */
.mwiz__dur-toggle {
  display: inline-flex;
  background: var(--mood-surface);
  border-radius: 12px;
  padding: 0.25rem;
  gap: 0.25rem;
  margin-bottom: 0.75rem;
}
.mwiz__dur-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.375rem 0.875rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--mood-muted);
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.mwiz__dur-btn--active { background: var(--mood-accent); color: var(--mood-accent-text); }
.mwiz__dur-relative { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.mwiz__dur-number {
  width: 5rem;
  padding: 0.5rem 0.75rem;
  font-size: 1.125rem;
  font-weight: 700;
  text-align: center;
  background: var(--mood-accent-soft);
  border-radius: 10px;
  outline: none;
  color: var(--mood-text);
}
.mwiz__dur-dates { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.mwiz__dur-date-field { display: flex; flex-direction: column; gap: 0.25rem; flex: 1; min-width: 140px; }
.mwiz__dur-arrow { color: var(--mood-muted); }

/* Submit */
.mwiz__submit {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1.75rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--mood-accent-text);
  background: var(--mood-accent);
  border-radius: 20px;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
  align-self: flex-start;
  margin-top: 0.5rem;
}
.mwiz__submit:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 4px 16px var(--mood-shadow); }
.mwiz__submit:disabled { opacity: 0.4; cursor: not-allowed; }

/* Nomination cards */
.mwiz__nom-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1.5rem; }
@media (max-width: 480px) { .mwiz__nom-grid { grid-template-columns: 1fr; } }
.mwiz__nom-card {
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  padding: 1.25rem;
  background: var(--mood-surface);
  border-radius: 16px;
  cursor: pointer;
  text-align: left;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.mwiz__nom-card:hover { transform: translateY(-3px); box-shadow: 0 6px 20px var(--mood-shadow); }
.mwiz__nom-card--active { box-shadow: 0 0 0 2px var(--mood-accent), 0 6px 20px var(--mood-shadow); background: var(--mood-accent-soft); }
.mwiz__nom-icon { color: var(--mood-accent); }
.mwiz__nom-title { font-weight: 700; font-size: 1rem; color: var(--mood-text); margin-bottom: 0.25rem; }
.mwiz__nom-desc { font-size: 0.875rem; color: var(--mood-muted); line-height: 1.5; }

/* Params */
.mwiz__self-params, .mwiz__election-cta { display: flex; flex-direction: column; gap: 1rem; }
.mwiz__param-row { display: flex; gap: 1rem; flex-wrap: wrap; }
.mwiz__param-field { display: flex; flex-direction: column; gap: 0.375rem; min-width: 120px; }
.mwiz__param-input-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.mwiz__param-input {
  width: 5rem;
  padding: 0.375rem 0.5rem;
  font-size: 0.9375rem;
  font-weight: 700;
  text-align: center;
  background: var(--mood-accent-soft);
  border-radius: 8px;
  outline: none;
  color: var(--mood-text);
}
.mwiz__param-unit { font-size: 0.8125rem; color: var(--mood-muted); white-space: nowrap; }
.mwiz__param-slider { flex: 1; min-width: 80px; accent-color: var(--mood-accent); }

/* Mode toggle (toolbox) */
.mwiz__mode-toggle {
  display: inline-flex;
  background: var(--mood-surface);
  border-radius: 14px;
  padding: 0.3125rem;
  gap: 0.25rem;
  margin-bottom: 1.5rem;
}
.mwiz__mode-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.5rem 1.125rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--mood-muted);
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.mwiz__mode-btn--active { background: var(--mood-accent); color: var(--mood-accent-text); }

/* Modalities */
.mwiz__modalities { display: flex; flex-direction: column; gap: 0.75rem; margin-bottom: 1.5rem; }
.mwiz__modality {
  background: var(--mood-surface);
  border-radius: 16px;
  padding: 1.125rem 1.25rem;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
  border-left: 3px solid transparent;
}
.mwiz__modality:hover { transform: translateY(-2px); box-shadow: 0 4px 14px var(--mood-shadow); }
.mwiz__modality--selected { border-left-color: var(--mood-accent); box-shadow: 0 4px 14px var(--mood-shadow); }
.mwiz__modality--recommended { border-left-color: var(--mood-success, var(--mood-accent)); }
.mwiz__modality--selected.mwiz__modality--recommended { border-left-color: var(--mood-accent); }
.mwiz__modality-head { display: flex; align-items: flex-start; gap: 0.875rem; }
.mwiz__modality-icon {
  width: 2.5rem;
  height: 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--mood-accent-soft);
  color: var(--mood-accent);
  border-radius: 12px;
  flex-shrink: 0;
}
.mwiz__modality-info { flex: 1; }
.mwiz__modality-title { font-weight: 700; font-size: 0.9375rem; color: var(--mood-text); margin-bottom: 0.25rem; }
.mwiz__modality-desc { font-size: 0.8125rem; color: var(--mood-muted); line-height: 1.5; }
.mwiz__modality-check { color: var(--mood-accent); margin-top: 0.125rem; }
.mwiz__modality-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  margin-top: 0.625rem;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--mood-success, var(--mood-accent));
  background: color-mix(in srgb, var(--mood-success, var(--mood-accent)) 12%, transparent);
  border-radius: 12px;
  padding: 0.1875rem 0.625rem;
}
.mwiz__modality-reason { font-size: 0.8125rem; color: var(--mood-muted); margin-top: 0.25rem; font-style: italic; }
.mwiz__modality-params {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--mood-border, rgba(0,0,0,0.06));
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

/* Recap */
.mwiz__recap { display: flex; flex-direction: column; gap: 1.25rem; margin-bottom: 2rem; }
.mwiz__recap-block {
  background: var(--mood-surface);
  border-radius: 16px;
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}
.mwiz__recap-label { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--mood-muted); margin-bottom: 0.25rem; }
.mwiz__recap-title { font-size: 1.125rem; font-weight: 800; color: var(--mood-text); }
.mwiz__recap-value { font-size: 0.9375rem; font-weight: 600; color: var(--mood-text); }
.mwiz__recap-meta { font-size: 0.875rem; color: var(--mood-muted); display: flex; align-items: center; gap: 0.375rem; }

/* Steps list */
.mwiz__steps-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.625rem; }
.mwiz__steps-item { display: flex; gap: 0.75rem; align-items: flex-start; }
.mwiz__steps-num {
  width: 1.5rem; height: 1.5rem;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.75rem; font-weight: 700;
  background: var(--mood-accent-soft);
  color: var(--mood-accent);
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 0.125rem;
}
.mwiz__steps-title { font-weight: 600; font-size: 0.875rem; color: var(--mood-text); }
.mwiz__steps-desc { font-size: 0.8125rem; color: var(--mood-muted); }

/* Recap actions */
.mwiz__recap-actions { display: flex; gap: 1rem; align-items: center; }
.mwiz__back-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.625rem 1.25rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--mood-muted);
  background: var(--mood-surface);
  border-radius: 16px;
  cursor: pointer;
  transition: transform 0.1s;
}
.mwiz__back-btn:hover { transform: translateY(-1px); }
.mwiz__create-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1.75rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--mood-accent-text);
  background: var(--mood-accent);
  border-radius: 20px;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.mwiz__create-btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 4px 16px var(--mood-shadow); }
.mwiz__create-btn:disabled { opacity: 0.4; cursor: not-allowed; }

.mwiz__error { color: var(--mood-danger, #e53e3e); font-size: 0.875rem; padding: 0.5rem 0; }

/* Transitions */
.slide-fade-enter-active, .slide-fade-leave-active { transition: all 0.2s ease; }
.slide-fade-enter-from { opacity: 0; transform: translateX(20px); }
.slide-fade-leave-to { opacity: 0; transform: translateX(-20px); }
.slide-down-enter-active, .slide-down-leave-active { transition: all 0.2s ease; overflow: hidden; }
.slide-down-enter-from, .slide-down-leave-to { opacity: 0; max-height: 0; }
.slide-down-enter-to, .slide-down-leave-from { max-height: 600px; }
</style>
