<script setup lang="ts">
// <!-- ld-v2 --> /mandats/nouveau — wizard 3 étapes porté du v1 (la structure
// à pépite : pills de progression, cartes cliquables, transitions), branché sur
// le pivot : la nomination EST une décision (createsMandate, route collective).
// Pré-remplissage par query ?titre=&tags= (suggestion R6 du chemin).
import type { Id, MandateDraft, NominationMethod, TriageInput } from '~/types/domain'
import type { ApplyPathEdits } from '~/stores/decisions'
import { useCollectiveStore } from '~/stores/collective'
import { useDecisionsStore } from '~/stores/decisions'
import { MANDATE_CLAIM, NOMINATION_LABELS } from '~/lexicon'

const col = useCollectiveStore()
const decisions = useDecisionsStore()
const route = useRoute()

const STEPS = ['Rôle et domaine', 'Nomination', 'Durée et comptes'] as const
const step = ref(0)

// ── Étape 1 : rôle et domaine ──
const title = ref(typeof route.query.titre === 'string' ? route.query.titre : '')
const mission = ref('')
const circleIds = ref<Id[]>([])
const tags = ref<string[]>(
  typeof route.query.tags === 'string'
    ? route.query.tags.split(',').map(t => t.trim()).filter(t => t.length > 0)
    : [],
)
const tagInput = ref('')

function toggleCircle(id: Id): void {
  circleIds.value = circleIds.value.includes(id)
    ? circleIds.value.filter(c => c !== id)
    : [...circleIds.value, id]
}
function addTag(): void {
  const tag = tagInput.value.trim().replace(/^#/, '').toLowerCase()
  if (tag && !tags.value.includes(tag)) tags.value.push(tag)
  tagInput.value = ''
}
function removeTag(tag: string): void {
  tags.value = tags.value.filter(t => t !== tag)
}

// ── Étape 2 : modalité de nomination (6) ──
const method = ref<NominationMethod | null>(null)

// ── Étape 3 : durée bornée, cadence, cercle électeur ──
const durationDays = ref(180)
const withReports = ref(true)
const reportEveryDays = ref(90)
const electorCircleId = ref<Id>(col.current?.collective.rootCircleId ?? '')

const canNext = computed(() => {
  if (step.value === 0) return title.value.trim().length > 0
  if (step.value === 1) return method.value !== null
  return durationDays.value >= 1 && electorCircleId.value !== ''
})

const electorCircle = computed(() => col.circles.find(c => c.id === electorCircleId.value))
const domainNames = computed(() =>
  circleIds.value
    .map(id => col.circles.find(c => c.id === id)?.name)
    .filter(n => n !== undefined),
)

/** La modalité choisie résout le protocole via le Pacte (repli : consentement). */
function protocolFor(m: NominationMethod): Id | undefined {
  const byRange = col.settings?.protocolByRange
  if (!byRange) return undefined
  if (m === 'election-no-candidate') return byRange.election ?? byRange.consent
  if (m === 'nuanced-vote') return byRange.nuanced ?? byRange.consent
  return byRange.consent // ratification par consentement (auto-désignation, tirage, rotation)
}

// ── Sortie : une Decision createsMandate, route collective ──
const submitting = ref(false)
const error = ref<string | null>(null)

function submit(): void {
  if (!method.value || submitting.value) return
  submitting.value = true
  error.value = null
  const captured = decisions.capture(`Confier le mandat « ${title.value.trim()} »`)
  if ('ok' in captured) { error.value = captured.reason; submitting.value = false; return }

  const scope = {
    selfOnly: false,
    // Le cercle électeur EN PREMIER : il devient le périmètre d'élection et de révocation.
    circleIds: [electorCircleId.value, ...circleIds.value.filter(id => id !== electorCircleId.value)],
    personIds: [] as Id[],
  }
  const input: TriageInput = {
    title: captured.title,
    tags: tags.value,
    scope,
    reversibility: 'costly',
    weight: 'binding',
    urgent: false,
  }
  const path = decisions.runTriage(input)
  if ('ok' in path) { error.value = path.reason; submitting.value = false; return }

  const draft: MandateDraft = {
    title: title.value.trim(),
    domainCircleIds: [...circleIds.value],
    domainTags: [...tags.value],
    durationDays: durationDays.value,
    ...(withReports.value ? { reportEveryDays: reportEveryDays.value } : {}),
  }
  const protocolId = protocolFor(method.value)
  const edits: ApplyPathEdits = {
    route: 'collective',
    scope,
    reversibility: 'costly',
    weight: 'binding',
    tags: [...tags.value],
    visibility: 'collective',
    createsMandate: draft,
    ...(mission.value.trim() ? { body: mission.value.trim() } : {}),
    ...(protocolId !== undefined ? { protocolId } : {}),
  }
  const applied = decisions.applyPath(captured, path, edits)
  if ('ok' in applied) { error.value = applied.reason; submitting.value = false; return }
  navigateTo(`/decisions/${applied.id}`)
}
</script>

<template>
  <!-- ld-v2 -->
  <div class="mwiz">
    <nav class="mwiz__nav">
      <button v-if="step > 0" type="button" class="mwiz__back" @click="step--">
        <UIcon name="i-lucide-arrow-left" />
        Retour
      </button>
      <NuxtLink v-else to="/mandats" class="mwiz__back">
        <UIcon name="i-lucide-arrow-left" />
        Mandats
      </NuxtLink>
      <div class="mwiz__progress">
        <template v-for="(label, i) in STEPS" :key="label">
          <span v-if="i > 0" class="mwiz__sep">›</span>
          <span
            class="mwiz__pill"
            :class="{ 'mwiz__pill--active': step === i, 'mwiz__pill--done': step > i }"
          >
            {{ i + 1 }} · {{ label }}
          </span>
        </template>
      </div>
    </nav>

    <Transition name="slide-fade" mode="out-in">
      <!-- ── ÉTAPE 1 : rôle et domaine ── -->
      <div v-if="step === 0" key="role" class="mwiz__step">
        <header class="mwiz__header">
          <h1 class="mwiz__title">{{ MANDATE_CLAIM }}</h1>
          <p class="mwiz__sub">Un rôle nommé, un domaine explicite — le pouvoir se voit.</p>
        </header>

        <label class="mwiz__label" for="mwiz-title">Titre du rôle</label>
        <input
          id="mwiz-title"
          v-model="title"
          type="text"
          class="mwiz__input"
          lang="fr"
          spellcheck="true"
          placeholder="ex : Trésorerie, Animation du jardin…"
        >

        <label class="mwiz__label" for="mwiz-mission">La mission, en une phrase</label>
        <input
          id="mwiz-mission"
          v-model="mission"
          type="text"
          class="mwiz__input"
          lang="fr"
          spellcheck="true"
          placeholder="ex : Tenir les comptes et rendre la caisse lisible par tous."
        >

        <p class="mwiz__label">Cercles du domaine</p>
        <div class="mwiz__chips">
          <button
            v-for="c in col.circles"
            :key="c.id"
            type="button"
            class="mwiz__chip"
            :class="{ 'mwiz__chip--on': circleIds.includes(c.id) }"
            @click="toggleCircle(c.id)"
          >
            {{ c.name }}
          </button>
        </div>

        <label class="mwiz__label" for="mwiz-tag">Tags du domaine</label>
        <div class="mwiz__chips">
          <span v-for="tag in tags" :key="tag" class="mwiz__chip mwiz__chip--on">
            #{{ tag }}
            <button type="button" class="mwiz__chip-x" :aria-label="`Retirer ${tag}`" @click="removeTag(tag)">
              <UIcon name="i-lucide-x" />
            </button>
          </span>
          <input
            id="mwiz-tag"
            v-model="tagInput"
            type="text"
            class="mwiz__input mwiz__input--tag"
            placeholder="ajouter un tag ⏎"
            @keydown.enter.prevent="addTag"
            @blur="addTag"
          >
        </div>
      </div>

      <!-- ── ÉTAPE 2 : modalité de nomination ── -->
      <div v-else-if="step === 1" key="nomination" class="mwiz__step">
        <header class="mwiz__header">
          <h1 class="mwiz__title">Comment nommer ?</h1>
          <p class="mwiz__sub">Six modalités, chacune avec sa pédagogie — le cercle électeur tranchera.</p>
        </header>
        <MandateNominationPicker v-model="method" />
      </div>

      <!-- ── ÉTAPE 3 : durée bornée, cadence, cercle électeur ── -->
      <div v-else key="terms" class="mwiz__step">
        <header class="mwiz__header">
          <h1 class="mwiz__title">Borné, redevable</h1>
          <p class="mwiz__sub">Un mandat a toujours une fin — et des comptes à rendre avant.</p>
        </header>

        <label class="mwiz__label" for="mwiz-duration">Durée du mandat (jours)</label>
        <div class="mwiz__row">
          <input
            id="mwiz-duration"
            v-model.number="durationDays"
            type="number"
            class="mwiz__input mwiz__input--num"
            min="7"
            max="730"
          >
          <input
            v-model.number="durationDays"
            type="range"
            class="mwiz__slider"
            min="7"
            max="730"
            step="1"
            aria-label="Durée du mandat en jours"
          >
        </div>

        <label class="mwiz__check">
          <input v-model="withReports" type="checkbox" class="mwiz__checkbox">
          <span>Avec rapports réguliers</span>
        </label>
        <div v-if="withReports" class="mwiz__row">
          <label class="mwiz__label mwiz__label--inline" for="mwiz-cadence">tous les</label>
          <input
            id="mwiz-cadence"
            v-model.number="reportEveryDays"
            type="number"
            class="mwiz__input mwiz__input--num"
            min="7"
            :max="durationDays"
          >
          <span class="mwiz__unit">jours</span>
        </div>

        <label class="mwiz__label" for="mwiz-elector">Cercle électeur — il nomme, il révoque</label>
        <select id="mwiz-elector" v-model="electorCircleId" class="mwiz__input">
          <option v-for="c in col.circles" :key="c.id" :value="c.id">{{ c.name }}</option>
        </select>

        <div class="mwiz__recap">
          <p class="mwiz__recap-title">{{ title }}</p>
          <p v-if="mission" class="mwiz__recap-line">{{ mission }}</p>
          <p class="mwiz__recap-line">
            {{ method ? NOMINATION_LABELS[method] : '—' }} ·
            {{ durationDays }} jours<template v-if="withReports"> · rapport tous les {{ reportEveryDays }} jours</template>
          </p>
          <p v-if="domainNames.length || tags.length" class="mwiz__recap-line">
            Domaine : {{ [...domainNames, ...tags.map(t => `#${t}`)].join(' · ') }}
          </p>
          <p class="mwiz__recap-note">
            La nomination est une décision — elle part au vote du cercle
            « {{ electorCircle?.name ?? '—' }} ».
          </p>
        </div>

        <p v-if="error" class="mwiz__error">{{ error }}</p>
      </div>
    </Transition>

    <div class="mwiz__actions">
      <button
        v-if="step < 2"
        type="button"
        class="ld-btn"
        :disabled="!canNext"
        @click="step++"
      >
        Continuer
        <UIcon name="i-lucide-arrow-right" />
      </button>
      <button
        v-else
        type="button"
        class="ld-btn"
        :disabled="!canNext || !method || submitting"
        @click="submit"
      >
        <UIcon name="i-lucide-scale" />
        {{ submitting ? 'Ouverture…' : 'Soumettre au cercle électeur' }}
      </button>
    </div>
  </div>
</template>

<style scoped>
.mwiz { max-width: 46rem; margin: 0 auto; width: 100%; display: flex; flex-direction: column; gap: 1.5rem; }
.mwiz__nav { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.mwiz__back {
  display: inline-flex; align-items: center; gap: 0.375rem;
  font-size: 0.875rem; font-weight: 600; color: var(--mood-text-muted);
  background: none; cursor: pointer; text-decoration: none;
}
.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-text-muted); font-size: 0.75rem; }
.mwiz__pill {
  font-size: 0.75rem; font-weight: 600; padding: 0.25rem 0.625rem;
  border-radius: var(--r-pill); color: var(--mood-text-muted);
  background: var(--mood-surface); white-space: nowrap;
}
.mwiz__pill--active { background: var(--mood-accent); color: var(--mood-accent-text); }
.mwiz__pill--done { background: var(--mood-accent-soft); color: var(--mood-accent); }

.mwiz__step { display: flex; flex-direction: column; gap: 0.75rem; }
.mwiz__header { margin-bottom: 0.5rem; }
.mwiz__title { margin: 0 0 0.25rem; font-size: clamp(1.25rem, 3vw, 1.625rem); font-weight: 800; }
.mwiz__sub { margin: 0; font-size: 0.9375rem; color: var(--mood-text-muted); }

.mwiz__label { font-size: 0.875rem; font-weight: 700; margin-top: 0.375rem; }
.mwiz__label--inline { margin-top: 0; }
.mwiz__input {
  width: 100%; padding: 0.6875rem 1rem; font: inherit; font-size: 0.9375rem;
  color: var(--mood-text); background: var(--mood-input-bg); border: none;
  border-radius: var(--r-input); box-shadow: inset 0 0 0 1px var(--mood-input-border);
}
.mwiz__input:focus { outline: none; box-shadow: inset 0 0 0 2px var(--mood-input-focus); }
.mwiz__input--num { width: 6rem; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }
.mwiz__input--tag { width: 11rem; padding: 0.375rem 0.75rem; font-size: 0.875rem; }
.mwiz__row { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.mwiz__slider { flex: 1; min-width: 10rem; accent-color: var(--mood-accent); }
.mwiz__unit { font-size: 0.875rem; color: var(--mood-text-muted); }
.mwiz__chips { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.mwiz__chip {
  display: inline-flex; align-items: center; gap: 0.375rem;
  padding: 0.375rem 0.875rem; font-size: 0.875rem; font-weight: 600;
  color: var(--mood-text-muted); background: var(--mood-surface);
  border-radius: var(--r-pill); box-shadow: var(--shadow-card);
  cursor: pointer; transition: transform 0.1s ease;
}
.mwiz__chip:hover { transform: translateY(-1px); }
.mwiz__chip--on { background: var(--mood-accent); color: var(--mood-accent-text); }
.mwiz__chip-x { display: inline-flex; background: none; color: inherit; cursor: pointer; padding: 0; }
.mwiz__check {
  display: flex; align-items: center; gap: 0.625rem; margin-top: 0.375rem;
  font-size: 0.9375rem; font-weight: 600; cursor: pointer;
}
.mwiz__checkbox { width: 1.125rem; height: 1.125rem; accent-color: var(--mood-accent); }

.mwiz__recap {
  margin-top: 0.75rem; padding: 1.125rem 1.25rem; border-radius: var(--r-card);
  background: var(--mood-surface); box-shadow: var(--shadow-card);
  display: flex; flex-direction: column; gap: 0.375rem;
}
.mwiz__recap-title { margin: 0; font-size: 1.0625rem; font-weight: 800; }
.mwiz__recap-line { margin: 0; font-size: 0.875rem; color: var(--mood-text-muted); }
.mwiz__recap-note { margin: 0.375rem 0 0; font-size: 0.875rem; font-weight: 600; color: var(--mood-accent); }
.mwiz__error { margin: 0; font-size: 0.875rem; font-weight: 600; color: var(--mood-error); }
.mwiz__actions { display: flex; justify-content: flex-end; }

.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); }
</style>
