<template>
  <div v-if="commune">
    <div class="page-header">
      <NuxtLink to="/" style="color: var(--color-text-muted); font-size: 0.875rem;">&larr; Toutes les communes</NuxtLink>
      <h1>{{ commune.name }}</h1>
      <p style="color: var(--color-text-muted);">{{ commune.description }}</p>
    </div>

    <!-- Loading -->
    <div v-if="loading" class="card" style="text-align: center; padding: 3rem;">
      <div class="spinner" style="margin: 0 auto;"></div>
      <p style="margin-top: 1rem; color: var(--color-text-muted);">Chargement...</p>
    </div>

    <template v-else-if="curveData">
      <!-- CMS content (published by admin) -->
      <div v-if="contentPages.length" style="margin-bottom: 1.5rem;">
        <div v-for="page in contentPages" :key="page.slug" class="card" style="margin-bottom: 1rem;">
          <h3 style="margin-bottom: 0.5rem;">{{ page.title }}</h3>
          <div class="cms-body" v-html="renderMarkdown(page.body_markdown)"></div>
        </div>
      </div>

      <!-- ═══════════════════════════════════════════════════════
           GRAPH 1: Interactive Bezier curve — Prix au m3
           (= dernier graph de eau.py — NewModel bottom subplot)
           ═══════════════════════════════════════════════════════ -->
      <div class="card" style="margin-bottom: 1.5rem;">
        <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.5rem;">
          <h3>Tarification progressive — Prix au m<sup>3</sup></h3>
          <span v-if="curveData.has_votes" class="badge badge-green">
            Mediane de {{ curveData.vote_count }} vote(s)
          </span>
          <span v-else class="badge badge-amber">Courbe par defaut</span>
        </div>
        <p style="font-size: 0.8rem; color: var(--color-text-muted); margin-bottom: 1rem;">
          Deplacez les poignees pour ajuster la forme de la courbe.
          Le prix d'inflexion p<sub>0</sub> s'ajuste automatiquement pour equilibrer les recettes.
        </p>

        <div class="editor-layout">
          <!-- SVG: Prix au m3 vs Volume (the Bezier curve) -->
          <div class="chart-container">
            <svg
              ref="svgRef"
              :viewBox="`0 0 ${W} ${H}`"
              preserveAspectRatio="xMidYMid meet"
              @mousemove="onMouseMove"
              @mouseup="onMouseUp"
              @mouseleave="onMouseUp"
              @touchmove.prevent="onTouchMove"
              @touchend="onMouseUp"
            >
              <!-- Grid -->
              <g>
                <line v-for="v in gridVols" :key="'gv'+v"
                  :x1="cx(v)" :y1="cy(0)" :x2="cx(v)" :y2="cy(pmax)"
                  stroke="#e2e8f0" stroke-width="0.5" />
                <line v-for="p in gridPrices" :key="'gp'+p"
                  :x1="cx(0)" :y1="cy(p)" :x2="cx(vmax)" :y2="cy(p)"
                  stroke="#e2e8f0" stroke-width="0.5" />
                <!-- Volume labels -->
                <text v-for="v in gridVols" :key="'lv'+v"
                  :x="cx(v)" :y="H - 2" text-anchor="middle" font-size="10" fill="#94a3b8">
                  {{ v }}
                </text>
                <!-- Price labels -->
                <text v-for="p in gridPrices" :key="'lp'+p"
                  :x="margin.left - 4" :y="cy(p) + 3" text-anchor="end" font-size="10" fill="#94a3b8">
                  {{ p }}
                </text>
                <!-- Axes labels -->
                <text :x="W / 2" :y="H - 0" text-anchor="middle" font-size="10" fill="#64748b">
                  volume (m3)
                </text>
                <text :x="12" :y="margin.top - 4" font-size="10" fill="#64748b">
                  Prix/m3
                </text>
              </g>

              <!-- Tangent lines (control arms) -->
              <line :x1="cx(cp.p1.x)" :y1="cy(cp.p1.y)" :x2="cx(cp.p2.x)" :y2="cy(cp.p2.y)"
                stroke="#93c5fd" stroke-width="1" stroke-dasharray="4" />
              <line :x1="cx(cp.p3.x)" :y1="cy(cp.p3.y)" :x2="cx(cp.p4.x)" :y2="cy(cp.p4.y)"
                stroke="#93c5fd" stroke-width="1" stroke-dasharray="4" />
              <line :x1="cx(cp.p4.x)" :y1="cy(cp.p4.y)" :x2="cx(cp.p5.x)" :y2="cy(cp.p5.y)"
                stroke="#fca5a5" stroke-width="1" stroke-dasharray="4" />
              <line :x1="cx(cp.p6.x)" :y1="cy(cp.p6.y)" :x2="cx(cp.p7.x)" :y2="cy(cp.p7.y)"
                stroke="#fca5a5" stroke-width="1" stroke-dasharray="4" />

              <!-- Bezier curve: tier 1 (blue) -->
              <path :d="tier1Path" fill="none" stroke="#2563eb" stroke-width="2.5" />
              <!-- Bezier curve: tier 2 (red) -->
              <path :d="tier2Path" fill="none" stroke="#dc2626" stroke-width="2.5" />

              <!-- Inflection reference lines -->
              <line :x1="cx(bp.vinf)" :y1="cy(0)" :x2="cx(bp.vinf)" :y2="cy(localP0)"
                stroke="#94a3b8" stroke-width="1" stroke-dasharray="4" />
              <line :x1="cx(0)" :y1="cy(localP0)" :x2="cx(bp.vinf)" :y2="cy(localP0)"
                stroke="#94a3b8" stroke-width="1" stroke-dasharray="4" />

              <!-- p0 label -->
              <text :x="cx(0) + 30" :y="cy(localP0) - 6" font-size="12" fill="#1e293b" font-weight="600">
                p0 = {{ localP0.toFixed(2) }} EUR/m3
              </text>

              <!-- Draggable control points -->
              <circle v-for="(pt, key) in dragPoints" :key="key"
                :cx="cx(pt.x)" :cy="cy(pt.y)"
                :r="dragging === key ? 9 : 7"
                :fill="ptColors[key]" stroke="white" stroke-width="2"
                style="cursor: grab;"
                @mousedown.prevent="startDrag(key)"
                @touchstart.prevent="startDrag(key)"
              />
              <!-- Point labels -->
              <text v-for="(pt, key) in dragPoints" :key="'l-'+key"
                :x="cx(pt.x) + 10" :y="cy(pt.y) - 10"
                font-size="11" :fill="ptColors[key]" font-weight="500">
                {{ ptLabels[key] }}
              </text>
            </svg>
          </div>

          <!-- Right panel: parameters + impacts -->
          <div class="side-panel">
            <div class="card" style="margin-bottom: 1rem;">
              <h4 style="margin-bottom: 0.5rem;">Parametres de la courbe</h4>
              <div class="param-grid">
                <div class="param-row">
                  <span class="param-label">v<sub>inf</sub></span>
                  <span class="param-val">{{ bp.vinf.toFixed(0) }} m3</span>
                </div>
                <div class="param-row">
                  <span class="param-label">a</span>
                  <span class="param-val">{{ bp.a.toFixed(3) }}</span>
                </div>
                <div class="param-row">
                  <span class="param-label">b</span>
                  <span class="param-val">{{ bp.b.toFixed(3) }}</span>
                </div>
                <div class="param-row">
                  <span class="param-label">c</span>
                  <span class="param-val">{{ bp.c.toFixed(3) }}</span>
                </div>
                <div class="param-row">
                  <span class="param-label">d</span>
                  <span class="param-val">{{ bp.d.toFixed(3) }}</span>
                </div>
                <div class="param-row">
                  <span class="param-label">e</span>
                  <span class="param-val">{{ bp.e.toFixed(3) }}</span>
                </div>
                <div class="param-row" style="grid-column: span 2; border-top: 1px solid var(--color-border); padding-top: 0.5rem;">
                  <span class="param-label" style="font-weight: 600;">p<sub>0</sub></span>
                  <span class="param-val" style="font-size: 1.1rem;">{{ localP0.toFixed(2) }} EUR/m3</span>
                </div>
              </div>
            </div>

            <!-- Impact table -->
            <div class="card" style="margin-bottom: 1rem;">
              <h4 style="margin-bottom: 0.5rem;">Impact par volume</h4>
              <table class="table table-sm">
                <thead>
                  <tr><th>Vol.</th><th>Ancien</th><th>Nouveau RP</th><th>Nouveau RS</th></tr>
                </thead>
                <tbody>
                  <tr v-for="imp in impacts" :key="imp.volume">
                    <td>{{ imp.volume }} m3</td>
                    <td>{{ imp.old_price.toFixed(0) }} EUR</td>
                    <td :class="imp.new_price_rp > imp.old_price ? 'text-up' : 'text-down'">
                      {{ imp.new_price_rp.toFixed(0) }} EUR
                    </td>
                    <td :class="imp.new_price_rs > imp.old_price ? 'text-up' : 'text-down'">
                      {{ imp.new_price_rs.toFixed(0) }} EUR
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>

            <!-- Vote action -->
            <div class="card">
              <div v-if="!isCitizenAuth">
                <p style="font-size: 0.85rem; color: var(--color-text-muted); margin-bottom: 0.75rem;">
                  Pour soumettre votre vote, entrez votre code foyer :
                </p>
                <div v-if="authError" class="alert alert-error" style="margin-bottom: 0.5rem;">{{ authError }}</div>
                <form @submit.prevent="authenticate" style="display: flex; gap: 0.5rem;">
                  <input v-model="authCode" type="text" maxlength="8" placeholder="Code foyer"
                    class="form-input" style="flex: 1; text-transform: uppercase; font-family: monospace; letter-spacing: 0.15em;" />
                  <button type="submit" class="btn btn-primary" :disabled="authLoading">OK</button>
                </form>
              </div>
              <div v-else>
                <button class="btn btn-primary" style="width: 100%;" @click="submitVote" :disabled="submitting">
                  <span v-if="submitting" class="spinner" style="width: 1rem; height: 1rem;"></span>
                  Soumettre mon vote
                </button>
                <div v-if="voteSuccess" class="alert alert-success" style="margin-top: 0.5rem;">
                  Vote enregistre !
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- ═══════════════════════════════════════════════════════
           GRAPH 2: Static baseline — Modele lineaire actuel
           (= 1er graph de eau.py — CurrentModel)
           ═══════════════════════════════════════════════════════ -->
      <div class="card" style="margin-bottom: 1.5rem;">
        <h3 style="margin-bottom: 0.5rem;">Tarification actuelle (modele lineaire)</h3>
        <p style="font-size: 0.8rem; color: var(--color-text-muted); margin-bottom: 1rem;">
          Situation tarifaire en vigueur : prix fixe de {{ curveData.p0_linear?.toFixed(2) }} EUR/m3 + abonnement.
        </p>

        <div class="baseline-charts">
          <!-- Left: Facture totale -->
          <div class="chart-container">
            <h4 style="text-align: center; font-size: 0.85rem; margin-bottom: 0.25rem;">Facture totale (EUR)</h4>
            <svg :viewBox="`0 0 ${W2} ${H2}`" preserveAspectRatio="xMidYMid meet">
              <!-- Grid -->
              <g>
                <line v-for="v in gridVols2" :key="'bg1v'+v"
                  :x1="cx2(v)" :y1="cy2bill(0)" :x2="cx2(v)" :y2="cy2bill(maxBill)"
                  stroke="#e2e8f0" stroke-width="0.5" />
                <line v-for="b in gridBills" :key="'bg1b'+b"
                  :x1="cx2(0)" :y1="cy2bill(b)" :x2="cx2(vmax)" :y2="cy2bill(b)"
                  stroke="#e2e8f0" stroke-width="0.5" />
                <text v-for="v in gridVols2" :key="'bg1lv'+v"
                  :x="cx2(v)" :y="H2 - 2" text-anchor="middle" font-size="9" fill="#94a3b8">{{ v }}</text>
                <text v-for="b in gridBills" :key="'bg1lb'+b"
                  :x="margin2.left - 4" :y="cy2bill(b) + 3" text-anchor="end" font-size="9" fill="#94a3b8">{{ b }}</text>
              </g>
              <!-- RP curve -->
              <polyline :points="baselineBillRP" fill="none" stroke="#2563eb" stroke-width="1.5" />
              <!-- RS curve -->
              <polyline :points="baselineBillRS" fill="none" stroke="#dc2626" stroke-width="1.5" />
              <!-- Legend -->
              <g :transform="`translate(${W2 - 100}, 15)`">
                <line x1="0" y1="0" x2="15" y2="0" stroke="#2563eb" stroke-width="1.5" />
                <text x="18" y="3" font-size="9" fill="#1e293b">RP/PRO</text>
                <line x1="0" y1="12" x2="15" y2="12" stroke="#dc2626" stroke-width="1.5" />
                <text x="18" y="15" font-size="9" fill="#1e293b">RS</text>
              </g>
              <text :x="W2/2" :y="H2" text-anchor="middle" font-size="9" fill="#64748b">volume (m3)</text>
            </svg>
          </div>

          <!-- Right: Prix au m3 -->
          <div class="chart-container">
            <h4 style="text-align: center; font-size: 0.85rem; margin-bottom: 0.25rem;">Prix au m<sup>3</sup> (EUR)</h4>
            <svg :viewBox="`0 0 ${W2} ${H2}`" preserveAspectRatio="xMidYMid meet">
              <!-- Grid -->
              <g>
                <line v-for="v in gridVols2" :key="'bg2v'+v"
                  :x1="cx2(v)" :y1="cy2price(0)" :x2="cx2(v)" :y2="cy2price(pmax)"
                  stroke="#e2e8f0" stroke-width="0.5" />
                <line v-for="p in gridPrices2" :key="'bg2p'+p"
                  :x1="cx2(0)" :y1="cy2price(p)" :x2="cx2(vmax)" :y2="cy2price(p)"
                  stroke="#e2e8f0" stroke-width="0.5" />
                <text v-for="v in gridVols2" :key="'bg2lv'+v"
                  :x="cx2(v)" :y="H2 - 2" text-anchor="middle" font-size="9" fill="#94a3b8">{{ v }}</text>
                <text v-for="p in gridPrices2" :key="'bg2lp'+p"
                  :x="margin2.left - 4" :y="cy2price(p) + 3" text-anchor="end" font-size="9" fill="#94a3b8">{{ p }}</text>
              </g>
              <!-- RP price/m3 curve (hyperbolic) -->
              <polyline :points="baselinePriceRP" fill="none" stroke="#2563eb" stroke-width="1.5" />
              <!-- RS price/m3 curve -->
              <polyline :points="baselinePriceRS" fill="none" stroke="#dc2626" stroke-width="1.5" />
              <!-- p0 baseline line -->
              <line :x1="cx2(0)" :y1="cy2price(curveData.p0_linear)" :x2="cx2(vmax)" :y2="cy2price(curveData.p0_linear)"
                stroke="#94a3b8" stroke-width="1" stroke-dasharray="4" />
              <text :x="cx2(vmax) - 5" :y="cy2price(curveData.p0_linear) - 5" text-anchor="end"
                font-size="10" fill="#475569">
                p0 = {{ curveData.p0_linear?.toFixed(2) }}
              </text>
              <text :x="W2/2" :y="H2" text-anchor="middle" font-size="9" fill="#64748b">volume (m3)</text>
            </svg>
          </div>
        </div>
      </div>

      <!-- Tariff params info -->
      <div class="card">
        <h3 style="margin-bottom: 0.75rem;">Informations tarifaires</h3>
        <div v-if="params" class="grid grid-5-info">
          <div><strong>{{ params.recettes.toLocaleString() }} EUR</strong><br/><span class="info-label">Recettes cibles</span></div>
          <div><strong>{{ params.abop }} EUR</strong><br/><span class="info-label">Abo RP/PRO</span></div>
          <div><strong>{{ params.abos }} EUR</strong><br/><span class="info-label">Abo RS</span></div>
          <div><strong>{{ params.pmax }} EUR/m3</strong><br/><span class="info-label">Prix max</span></div>
          <div><strong>{{ params.vmax }} m3</strong><br/><span class="info-label">Volume max</span></div>
        </div>
      </div>
    </template>
  </div>

  <div v-else-if="loadError" class="alert alert-error">{{ loadError }}</div>

  <div v-else style="text-align: center; padding: 3rem;">
    <div class="spinner" style="margin: 0 auto;"></div>
  </div>
</template>

<script setup lang="ts">
import {
  computeP0, computeImpacts, generateCurve,
  paramsToControlPoints,
  type HouseholdData, type ImpactRow, type ControlPoints,
} from '~/utils/bezier-math'

const route = useRoute()
const authStore = useAuthStore()
const api = useApi()

const slug = route.params.slug as string
const commune = ref<any>(null)
const params = ref<any>(null)
const curveData = ref<any>(null)
const loading = ref(true)
const loadError = ref('')
const contentPages = ref<any[]>([])

// Bezier params (citizen-adjustable)
const bp = reactive({ vinf: 1050, a: 0.5, b: 0.5, c: 0.5, d: 0.5, e: 0.5 })
const localP0 = ref(0)
const impacts = ref<any[]>([])
const households = ref<HouseholdData[]>([])

// Tariff fixed params
const vmax = ref(2100)
const pmax = ref(20)
const recettes = ref(75000)
const abop = ref(100)
const abos = ref(100)

// Auth
const authCode = ref('')
const authError = ref('')
const authLoading = ref(false)
const isCitizenAuth = computed(() => authStore.isCitizen && authStore.communeSlug === slug)
const submitting = ref(false)
const voteSuccess = ref(false)

// ── Chart 1: Interactive Bezier ──
const W = 620
const H = 380
const margin = { top: 20, right: 20, bottom: 28, left: 45 }
const plotW = W - margin.left - margin.right
const plotH = H - margin.top - margin.bottom

function cx(v: number) { return margin.left + (v / vmax.value) * plotW }
function cy(p: number) { return margin.top + plotH - (p / pmax.value) * plotH }
function fromX(sx: number) { return ((sx - margin.left) / plotW) * vmax.value }
function fromY(sy: number) { return ((margin.top + plotH - sy) / plotH) * pmax.value }

const gridVols = computed(() => {
  const step = Math.ceil(vmax.value / 7 / 100) * 100
  const arr: number[] = []
  for (let v = step; v < vmax.value; v += step) arr.push(v)
  return arr
})
const gridPrices = computed(() => {
  const step = Math.ceil(pmax.value / 5)
  const arr: number[] = []
  for (let p = step; p <= pmax.value; p += step) arr.push(p)
  return arr
})

// Control points
const cp = computed<ControlPoints>(() =>
  paramsToControlPoints(bp.vinf, vmax.value, pmax.value, localP0.value, bp.a, bp.b, bp.c, bp.d, bp.e)
)

const dragPoints = computed(() => ({
  p2: cp.value.p2,
  p3: cp.value.p3,
  p4: cp.value.p4,
  p5: cp.value.p5,
  p6: cp.value.p6,
}))

const ptColors: Record<string, string> = {
  p2: '#3b82f6', p3: '#3b82f6', p4: '#8b5cf6', p5: '#ef4444', p6: '#ef4444',
}
const ptLabels: Record<string, string> = {
  p2: 'a', p3: 'b', p4: 'vinf', p5: 'c', p6: 'd,e',
}

const tier1Path = computed(() => {
  const c = cp.value
  return `M ${cx(c.p1.x)} ${cy(c.p1.y)} C ${cx(c.p2.x)} ${cy(c.p2.y)}, ${cx(c.p3.x)} ${cy(c.p3.y)}, ${cx(c.p4.x)} ${cy(c.p4.y)}`
})
const tier2Path = computed(() => {
  const c = cp.value
  return `M ${cx(c.p4.x)} ${cy(c.p4.y)} C ${cx(c.p5.x)} ${cy(c.p5.y)}, ${cx(c.p6.x)} ${cy(c.p6.y)}, ${cx(c.p7.x)} ${cy(c.p7.y)}`
})

// ── Drag handling ──
const svgRef = ref<SVGSVGElement | null>(null)
const dragging = ref<string | null>(null)

function getSvgPt(event: MouseEvent | Touch) {
  if (!svgRef.value) return { x: 0, y: 0 }
  const rect = svgRef.value.getBoundingClientRect()
  return {
    x: (event.clientX - rect.left) * (W / rect.width),
    y: (event.clientY - rect.top) * (H / rect.height),
  }
}
function startDrag(key: string) { dragging.value = key }
function onMouseMove(e: MouseEvent) { if (dragging.value) handleDrag(getSvgPt(e)) }
function onTouchMove(e: TouchEvent) { if (dragging.value && e.touches[0]) handleDrag(getSvgPt(e.touches[0])) }
function onMouseUp() {
  if (dragging.value) {
    dragging.value = null
    debouncedServerCompute()
  }
}

function handleDrag(pt: { x: number; y: number }) {
  const v = Math.max(0, Math.min(vmax.value, fromX(pt.x)))
  const p = Math.max(0, Math.min(pmax.value, fromY(pt.y)))

  switch (dragging.value) {
    case 'p2':
      bp.a = localP0.value > 0 ? Math.max(0, Math.min(1, p / localP0.value)) : 0.5
      break
    case 'p3':
      bp.b = bp.vinf > 0 ? Math.max(0, Math.min(1, v / bp.vinf)) : 0.5
      break
    case 'p4':
      bp.vinf = Math.max(1, Math.min(vmax.value - 1, v))
      break
    case 'p5': {
      const wmax = vmax.value - bp.vinf
      bp.c = wmax > 0 ? Math.max(0, Math.min(1, (v - bp.vinf) / wmax)) : 0.5
      break
    }
    case 'p6': {
      const wmax = vmax.value - bp.vinf
      const qmax = pmax.value - localP0.value
      bp.e = qmax > 0 ? Math.max(0, Math.min(1, (p - localP0.value) / qmax)) : 0.5
      if (wmax > 0 && Math.abs(1 - bp.c) > 1e-10) {
        const ratio = (v - bp.vinf) / wmax
        bp.d = Math.max(0, Math.min(1, (1 - ratio) / (1 - bp.c)))
      }
      break
    }
  }
  recalculate()
}

function recalculate() {
  if (!households.value.length) return
  localP0.value = computeP0(
    households.value, recettes.value, abop.value, abos.value,
    bp.vinf, vmax.value, pmax.value, bp.a, bp.b, bp.c, bp.d, bp.e,
  )
  const result = computeImpacts(
    households.value, recettes.value, abop.value, abos.value,
    bp.vinf, vmax.value, pmax.value, bp.a, bp.b, bp.c, bp.d, bp.e,
  )
  impacts.value = result.impacts.map(imp => ({
    volume: imp.volume,
    old_price: imp.oldPrice,
    new_price_rp: imp.newPriceRP,
    new_price_rs: imp.newPriceRS,
  }))
}

let serverTimeout: ReturnType<typeof setTimeout> | null = null
function debouncedServerCompute() {
  if (serverTimeout) clearTimeout(serverTimeout)
  serverTimeout = setTimeout(async () => {
    try {
      const result = await api.post<any>('/tariff/compute', {
        commune_slug: slug, vinf: bp.vinf,
        a: bp.a, b: bp.b, c: bp.c, d: bp.d, e: bp.e,
      })
      localP0.value = result.p0
      impacts.value = result.impacts.map((imp: any) => ({
        volume: imp.volume,
        old_price: imp.old_price,
        new_price_rp: imp.new_price_rp,
        new_price_rs: imp.new_price_rs,
      }))
    } catch {}
  }, 300)
}

// ── Chart 2: Baseline linear model ──
const W2 = 300
const H2 = 220
const margin2 = { top: 10, right: 10, bottom: 24, left: 40 }
const plotW2 = W2 - margin2.left - margin2.right
const plotH2 = H2 - margin2.top - margin2.bottom

function cx2(v: number) { return margin2.left + (v / vmax.value) * plotW2 }

const maxBill = computed(() => {
  if (!curveData.value?.baseline_bills_rp?.length) return 500
  const mx = Math.max(...curveData.value.baseline_bills_rp)
  return Math.ceil(mx * 1.1 / 100) * 100
})

function cy2bill(b: number) { return margin2.top + plotH2 - (b / maxBill.value) * plotH2 }
function cy2price(p: number) { return margin2.top + plotH2 - (p / pmax.value) * plotH2 }

const gridVols2 = computed(() => {
  const step = Math.ceil(vmax.value / 5 / 100) * 100
  const arr: number[] = []
  for (let v = step; v < vmax.value; v += step) arr.push(v)
  return arr
})
const gridBills = computed(() => {
  const step = Math.ceil(maxBill.value / 4 / 100) * 100
  const arr: number[] = []
  for (let b = step; b < maxBill.value; b += step) arr.push(b)
  return arr
})
const gridPrices2 = computed(() => {
  const step = Math.ceil(pmax.value / 4)
  const arr: number[] = []
  for (let p = step; p <= pmax.value; p += step) arr.push(p)
  return arr
})

function toPolyline(vols: number[], vals: number[], cyFn: (v: number) => number) {
  if (!vols?.length) return ''
  // Downsample for performance (every 4th point)
  return vols
    .filter((_: number, i: number) => i % 4 === 0 || i === vols.length - 1)
    .map((_: number, i: number) => {
      const idx = i * 4 >= vols.length ? vols.length - 1 : i * 4
      return `${cx2(vols[idx])},${cyFn(vals[idx])}`
    })
    .join(' ')
}

const baselineBillRP = computed(() => toPolyline(curveData.value?.baseline_volumes, curveData.value?.baseline_bills_rp, cy2bill))
const baselineBillRS = computed(() => toPolyline(curveData.value?.baseline_volumes, curveData.value?.baseline_bills_rs, cy2bill))
const baselinePriceRP = computed(() => toPolyline(curveData.value?.baseline_volumes, curveData.value?.baseline_price_m3_rp, cy2price))
const baselinePriceRS = computed(() => toPolyline(curveData.value?.baseline_volumes, curveData.value?.baseline_price_m3_rs, cy2price))

// ── Auth & vote ──
async function authenticate() {
  authError.value = ''
  authLoading.value = true
  try {
    const data = await api.post<{ access_token: string; role: string; commune_slug: string }>(
      '/auth/citizen/verify',
      { commune_slug: slug, auth_code: authCode.value.toUpperCase() },
    )
    authStore.setAuth(data.access_token, data.role, data.commune_slug)
  } catch (e: any) {
    authError.value = e.message || 'Code invalide'
  } finally {
    authLoading.value = false
  }
}

async function submitVote() {
  submitting.value = true
  voteSuccess.value = false
  try {
    await api.post(`/communes/${slug}/votes`, {
      vinf: bp.vinf, a: bp.a, b: bp.b, c: bp.c, d: bp.d, e: bp.e,
    })
    voteSuccess.value = true
  } catch (e: any) {
    alert(e.message || 'Erreur lors de la soumission')
  } finally {
    submitting.value = false
  }
}

// ── Load data ──
onMounted(async () => {
  try {
    const [c, p, curve, pages] = await Promise.all([
      api.get<any>(`/communes/${slug}`),
      api.get<any>(`/communes/${slug}/params`),
      api.get<any>(`/communes/${slug}/votes/current`),
      api.get<any[]>(`/communes/${slug}/content`).catch(() => []),
    ])
    contentPages.value = pages
    commune.value = c
    params.value = p
    curveData.value = curve

    // Set tariff params
    vmax.value = p.vmax
    pmax.value = p.pmax
    recettes.value = p.recettes
    abop.value = p.abop
    abos.value = p.abos

    // Set initial Bezier params from median (or default)
    if (curve.median) {
      bp.vinf = curve.median.vinf
      bp.a = curve.median.a
      bp.b = curve.median.b
      bp.c = curve.median.c
      bp.d = curve.median.d
      bp.e = curve.median.e
    }
    localP0.value = curve.p0

    // Set impacts from server
    impacts.value = curve.impacts || []

    // Build simplified household list for client-side compute
    const stats = await api.get<any>(`/communes/${slug}/households/stats`)
    const hh: HouseholdData[] = []
    const avgVol = stats.avg_volume || 90
    for (let i = 0; i < (stats.rs_count || 0); i++) hh.push({ volume_m3: avgVol, status: 'RS' })
    for (let i = 0; i < (stats.rp_count || 0); i++) hh.push({ volume_m3: avgVol, status: 'RP' })
    for (let i = 0; i < (stats.pro_count || 0); i++) hh.push({ volume_m3: avgVol, status: 'PRO' })
    households.value = hh
  } catch (e: any) {
    loadError.value = e.message
  } finally {
    loading.value = false
  }
})

function renderMarkdown(md: string): string {
  if (!md) return ''
  return md
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/^### (.+)$/gm, '<h3>$1</h3>')
    .replace(/^## (.+)$/gm, '<h2>$1</h2>')
    .replace(/^# (.+)$/gm, '<h1>$1</h1>')
    .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
    .replace(/\*(.+?)\*/g, '<em>$1</em>')
    .replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2">$1</a>')
    .replace(/^- (.+)$/gm, '<li>$1</li>')
    .replace(/\n\n/g, '</p><p>')
    .replace(/^(?!<[hulo])(.+)$/gm, '<p>$1</p>')
}
</script>

<style scoped>
.editor-layout {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 1rem;
}
@media (max-width: 900px) {
  .editor-layout { grid-template-columns: 1fr; }
}

.chart-container svg {
  width: 100%;
  height: auto;
  user-select: none;
}

.side-panel .card {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
}

.param-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.25rem 1rem;
}
.param-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.15rem 0;
}
.param-label { font-size: 0.75rem; color: var(--color-text-muted); }
.param-val { font-family: monospace; font-weight: 600; font-size: 0.85rem; }

.table-sm { font-size: 0.8rem; }
.table-sm th, .table-sm td { padding: 0.25rem 0.5rem; }

.text-up { color: #dc2626; }
.text-down { color: #059669; }

.baseline-charts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
@media (max-width: 700px) {
  .baseline-charts { grid-template-columns: 1fr; }
}

.grid-5-info {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1rem;
  text-align: center;
}
@media (max-width: 700px) {
  .grid-5-info { grid-template-columns: repeat(3, 1fr); }
}
.info-label { font-size: 0.75rem; color: var(--color-text-muted); }

.alert-success {
  background: #dcfce7;
  color: #166534;
  padding: 0.5rem 0.75rem;
  border-radius: 0.375rem;
  font-size: 0.85rem;
}

.cms-body { line-height: 1.7; font-size: 0.9rem; }
.cms-body :deep(h2) { font-size: 1.2rem; margin: 0.75rem 0 0.5rem; }
.cms-body :deep(h3) { font-size: 1.05rem; margin: 0.5rem 0 0.25rem; }
.cms-body :deep(p) { margin: 0.5rem 0; }
.cms-body :deep(a) { color: var(--color-primary); }
.cms-body :deep(ul) { margin: 0.5rem 0; padding-left: 1.5rem; }
</style>
